48#include <wx/mstream.h>
49#include <wx/tokenzr.h>
50#include <wx/wfstream.h>
51#include <wx/zipstrm.h>
59static const wxChar
tracePcm[] = wxT(
"KICAD_PCM" );
61static const std::string
PCM_ACCEPT_V2 =
"application/vnd.kicad.pcm.v2+json";
70 void error(
const json::json_pointer& ptr,
const json& instance,
71 const std::string& message )
override
73 throw std::invalid_argument( std::string(
"At " ) + ptr.to_string() +
", value:\n"
74 + instance.dump() +
"\n" + message +
"\n" );
89 schema_v1_file.AppendDir( wxS(
"schemas" ) );
95 schema_v2_file.AppendDir( wxS(
"schemas" ) );
104 std::ifstream installed_stream( f.GetFullPath().fn_str() );
105 nlohmann::json installed;
109 installed_stream >> installed;
111 if( installed.contains(
"packages" ) && installed[
"packages"].is_array() )
113 for(
const auto& js_entry : installed[
"packages"] )
120 catch( std::exception& e )
122 wxLogError( wxString::Format(
_(
"Error loading installed packages list: %s" ),
136 wxDir package_dir( d.GetPath() );
138 if( !package_dir.IsOpened() )
142 bool more = package_dir.GetFirst( &subdir,
"", wxDIR_DIRS | wxDIR_HIDDEN );
146 wxString actual_package_id = subdir;
147 actual_package_id.Replace(
'_',
'.' );
152 wxFileName subdir_file( d.GetPath(), subdir );
156 int stat_code = wxStat( subdir_file.GetFullPath(), &stat );
176 more = package_dir.GetNext( &subdir );
183 [&]( std::pair<const wxString, PCM_INSTALLATION_ENTRY>& entry )
185 PreparePackage( entry.second.package );
204 const size_t aSizeLimit,
205 const std::string& aAccept )
207 bool size_exceeded =
false;
209 TRANSFER_CALLBACK callback = [&](
size_t dltotal,
size_t dlnow,
size_t ultotal,
size_t ulnow )
211 if( aSizeLimit > 0 && ( dltotal > aSizeLimit || dlnow > aSizeLimit ) )
213 size_exceeded =
true;
222 aReporter->
Report( wxString::Format(
_(
"Downloading %lld/%lld kB" ), dlnow / 1000,
235 curl.
SetURL( aUrl.ToUTF8().data() );
245 if( !aAccept.empty() )
253 if( code != CURLE_OK )
257 if( code == CURLE_ABORTED_BY_CALLBACK && size_exceeded )
258 wxMessageBox(
_(
"Download is too large." ) );
259 else if( code != CURLE_ABORTED_BY_CALLBACK )
273 std::stringstream repository_stream;
275 aReporter->
SetTitle(
_(
"Fetching repository" ) );
283 nlohmann::json repository_json;
287 repository_stream >> repository_json;
289 int schema_version = 1;
291 if( repository_json.contains(
"schema_version" ) )
292 schema_version = repository_json[
"schema_version"].get<
int>();
294 if( schema_version >= 2 )
297 nlohmann::json_uri(
"#/definitions/Repository" ) );
302 nlohmann::json_uri(
"#/definitions/Repository" ) );
308 catch(
const std::exception& e )
312 wxLogError(
_(
"Unable to parse repository: %s" ), e.what() );
313 wxLogError(
_(
"The given repository URL does not look like a valid KiCad package "
314 "repository. Please double check the URL." ) );
325 const nlohmann::json_uri& aUri )
const
334 const nlohmann::json_uri& aUri )
const
337 aValidator.
Validate( aJson, error_handler, aUri );
342 const std::optional<wxString>& aHash,
343 std::vector<PCM_PACKAGE>& aPackages,
347 std::stringstream packages_stream;
349 aReporter->
SetTitle(
_(
"Fetching repository packages" ) );
355 wxLogError(
_(
"Unable to load repository packages url." ) );
360 std::istringstream isstream( packages_stream.str() );
362 if( aHash && !
VerifyHash( isstream, *aHash ) )
365 wxLogError(
_(
"Packages hash doesn't match. Repository may be corrupted." ) );
372 nlohmann::json packages_json = nlohmann::json::parse( packages_stream.str() );
378 nlohmann::json_uri(
"#/definitions/PackageArray" ) );
380 aPackages = packages_json[
"packages"].get<std::vector<PCM_PACKAGE>>();
382 catch( std::exception& e )
386 wxLogError( wxString::Format(
_(
"Unable to parse packages metadata:\n\n%s" ),
399 std::vector<unsigned char> bytes( picosha2::k_digest_size );
401 picosha2::hash256( std::istreambuf_iterator<char>( aStream ), std::istreambuf_iterator<char>(),
402 bytes.begin(), bytes.end() );
403 std::string hex_str = picosha2::bytes_to_hex_string( bytes.begin(), bytes.end() );
405 return aHash.compare( hex_str ) == 0;
409STRING_TUPLE_LIST::const_iterator
413 [&aRepositoryId](
const std::tuple<wxString, wxString, wxString>& aRepo )
415 return std::get<0>( aRepo ) == aRepositoryId;
424 wxT(
"Repository is not cached." ) );
440 wxString url = std::get<2>( *repository_tuple );
446 std::shared_ptr<PROGRESS_REPORTER>
reporter;
456 bool packages_cache_exists =
false;
460 repo_cache.AppendDir( wxT(
"pcm" ) );
461 repo_cache.AppendDir( aRepositoryId );
462 wxFileName packages_cache( repo_cache.GetPath(), wxT(
"packages.json" ) );
464 if( repo_cache.FileExists() && packages_cache.FileExists() )
466 std::ifstream repo_stream( repo_cache.GetFullPath().fn_str() );
476 wxLogError(
_(
"Failed to parse locally stored repository.json." ) );
483 std::ifstream packages_cache_stream( packages_cache.GetFullPath().fn_str() );
487 packages_cache_stream >> js;
488 saved_repo.
package_list = js[
"packages"].get<std::vector<PCM_PACKAGE>>();
490 for(
size_t i = 0; i < saved_repo.
package_list.size(); i++ )
498 packages_cache_exists =
true;
504 wxLogError(
_(
"Packages cache for current repository is corrupted, it will "
505 "be redownloaded." ) );
511 if( !packages_cache_exists )
521 for(
size_t i = 0; i < current_repo.
package_list.size(); i++ )
527 repo_cache.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
529 std::ofstream repo_cache_stream( repo_cache.GetFullPath().fn_str() );
530 repo_cache_stream << std::setw( 4 ) << nlohmann::json( current_repo ) << std::endl;
532 std::ofstream packages_cache_stream( packages_cache.GetFullPath().fn_str() );
534 js[
"packages"] = nlohmann::json( current_repo.
package_list );
535 packages_cache_stream << std::setw( 4 ) << js << std::endl;
546 wxFileName resource_file( repo_cache.GetPath(), wxT(
"resources.zip" ) );
550 if( resource_file.FileExists() )
551 mtime = wxFileModificationTime( resource_file.GetFullPath() );
555 std::ofstream resources_stream( resource_file.GetFullPath().fn_str(),
556 std::ios_base::binary );
558 reporter->SetTitle(
_(
"Downloading resources" ) );
564 resources_stream.close();
568 std::ifstream read_stream( resource_file.GetFullPath().fn_str(),
569 std::ios_base::binary );
578 wxLogError(
_(
"Resources file hash doesn't match and will not be used. "
579 "Repository may be corrupted." ) );
582 wxRemoveFile( resource_file.GetFullPath() );
588 wxRemoveFile( resource_file.GetFullPath() );
609 wxLogTrace(
tracePcm, wxS(
"Invalid/Missing repository " ) + aRepositoryId );
613 for( std::pair<const wxString, PCM_INSTALLATION_ENTRY>& pair :
m_installed )
625 std::optional<PACKAGE_VERSION> current_version;
627 auto current_version_it =
631 return version.version == entry.current_version;
635 current_version = *current_version_it;
645 return version.version == entry.current_version;
648 if( current_version_it == entry.
package.
versions.end() && current_version )
656 return a.parsed_version > b.parsed_version;
668 int epoch = 0, major = 0, minor = 0, patch = 0;
673 wxStringTokenizer version_tokenizer( ver.
version,
"." );
675 major = wxAtoi( version_tokenizer.GetNextToken() );
677 if( version_tokenizer.HasMoreTokens() )
678 minor = wxAtoi( version_tokenizer.GetNextToken() );
680 if( version_tokenizer.HasMoreTokens() )
681 patch = wxAtoi( version_tokenizer.GetNextToken() );
683 ver.
parsed_version = std::make_tuple( epoch, major, minor, patch );
688 auto parse_version_tuple =
689 [](
const wxString& version,
int deflt )
691 int ver_major = deflt;
692 int ver_minor = deflt;
693 int ver_patch = deflt;
695 wxStringTokenizer tokenizer( version,
"." );
697 ver_major = wxAtoi( tokenizer.GetNextToken() );
699 if( tokenizer.HasMoreTokens() )
700 ver_minor = wxAtoi( tokenizer.GetNextToken() );
702 if( tokenizer.HasMoreTokens() )
703 ver_patch = wxAtoi( tokenizer.GetNextToken() );
705 return std::tuple<int, int, int>( ver_major, ver_minor, ver_patch );
716 wxString platform = wxT(
"windows" );
717#elif defined( __APPLE__ )
718 wxString platform = wxT(
"macos" );
720 wxString platform = wxT(
"linux" );
739 return a.parsed_version > b.parsed_version;
749 auto ver_it = std::find_if( aPackage.
versions.begin(), aPackage.
versions.end(),
752 return ver.version == aVersion;
755 if( ver_it == aPackage.
versions.end() )
762const std::vector<PCM_PACKAGE>&
765 static std::vector<PCM_PACKAGE>
empty{};
783 auto it = std::find_if( aRepositories.begin(), aRepositories.end(),
784 [&](
const auto& new_entry )
786 return new_entry.first == std::get<1>( entry );
789 if( it == aRepositories.end() )
798 for(
const std::pair<wxString, wxString>& repo : aRepositories )
800 std::string url_sha = picosha2::hash256_hex_string( repo.second );
801 m_repository_list.push_back( std::make_tuple( url_sha.substr( 0, 16 ), repo.first,
813 repo_cache.AppendDir( wxT(
"pcm" ) );
814 repo_cache.AppendDir( aRepositoryId );
816 if( repo_cache.DirExists() )
817 repo_cache.Rmdir( wxPATH_RMDIR_RECURSIVE );
822 const wxString& aRepositoryId )
840 if( !aRepositoryId.IsEmpty() )
857 && !
Pgm().GetCommonSettings()->m_Api.enable_server )
873 const wxString& aPackageId )
910 return ver.compatible;
919 const wxString& aPackageId,
const wxString& aRecordedName,
921 const std::unordered_map<wxString, PCM_REPOSITORY>& aCache )
923 std::vector<wxString> publishers;
924 std::vector<wxString> nameMatches;
926 for(
const auto& [
id,
name, url] : aRepositoryList )
928 auto cached = aCache.find(
id );
930 if( cached == aCache.end() || cached->second.package_map.count( aPackageId ) == 0 )
933 publishers.push_back(
id );
937 if( cached->second.name == aRecordedName )
938 nameMatches.push_back(
id );
941 if( nameMatches.size() == 1 )
942 return nameMatches.front();
946 if( publishers.size() == 1 )
947 return publishers.front();
972 if( resolved.IsEmpty() )
974 wxLogTrace(
tracePcm, wxS(
"Package %s is not published by any configured repository" ),
979 wxLogTrace(
tracePcm, wxS(
"Package %s repository id repaired from '%s' to '%s'" ),
994 for( std::pair<const wxString, PCM_INSTALLATION_ENTRY>& pair :
m_installed )
1002 wxT(
"GetPackageUpdateVersion called on a not installed package" ) );
1006 auto installed_ver_it = std::find_if(
1010 return ver.version == entry.current_version;
1013 wxCHECK_MSG( installed_ver_it != entry.
package.
versions.end(), wxEmptyString,
1014 wxT(
"Installed package version not found" ) );
1016 auto ver_it = std::find_if( aPackage.
versions.begin(), aPackage.
versions.end(),
1019 return ver.compatible
1020 && installed_ver_it->status >= ver.status
1021 && installed_ver_it->parsed_version < ver.parsed_version;
1024 return ver_it == aPackage.
versions.end() ? wxString( wxT(
"" ) ) : ver_it->version;
1029 return std::chrono::duration_cast<std::chrono::seconds>(
1030 std::chrono::system_clock::now().time_since_epoch() ).count();
1039 js[
"packages"] = nlohmann::json::array();
1041 for( std::pair<const wxString, PCM_INSTALLATION_ENTRY>& pair :
m_installed )
1043 js[
"packages"].emplace_back( pair.second );
1047 std::ofstream stream( f.GetFullPath().fn_str() );
1049 stream << std::setw( 4 ) << js << std::endl;
1051 catch( nlohmann::detail::exception& )
1060 std::vector<PCM_INSTALLATION_ENTRY> v;
1063 [&v](
const std::pair<const wxString, PCM_INSTALLATION_ENTRY>& entry )
1065 v.push_back( entry.second );
1068 std::sort( v.begin(), v.end(),
1071 return ( a.install_timestamp < b.install_timestamp )
1072 || ( a.install_timestamp == b.install_timestamp
1073 && a.package.identifier < b.package.identifier );
1084 wxT(
"Installed package not found." ) );
1086 return m_installed.at( aPackageId ).current_version;
1109 const wxString& aSearchTerm )
1111 wxArrayString terms = wxStringTokenize( aSearchTerm.Lower(), wxS(
" " ), wxTOKEN_STRTOK );
1114 const auto find_term_matches =
1115 [&](
const wxString& str )
1118 wxString lower = str.Lower();
1120 for(
const wxString& term : terms )
1122 if( lower.Find( term ) != wxNOT_FOUND )
1130 if( terms.size() == 1 && terms[0] == aPackage.
identifier )
1133 if( terms.size() == 1 && find_term_matches( aPackage.
identifier ) )
1137 rank += 500 * find_term_matches( aPackage.
name );
1140 for(
const std::string& tag : aPackage.
tags )
1141 rank += 100 * find_term_matches( wxString( tag ) );
1144 rank += 10 * find_term_matches( aPackage.
description );
1148 rank += find_term_matches( aPackage.
author.
name );
1151 rank += 3 * find_term_matches( aPackage.
maintainer->name );
1154 for(
const std::pair<const std::string, wxString>& entry : aPackage.
resources )
1156 rank += find_term_matches( entry.first );
1157 rank += find_term_matches( entry.second );
1161 if( terms.size() == 1 && terms[0] == aPackage.
license )
1168std::unordered_map<wxString, wxBitmap>
1171 std::unordered_map<wxString, wxBitmap> bitmaps;
1174 resources_file.AppendDir( wxT(
"pcm" ) );
1175 resources_file.AppendDir( aRepositoryId );
1177 if( !resources_file.FileExists() )
1180 wxFFileInputStream stream( resources_file.GetFullPath() );
1181 wxZipInputStream
zip( stream );
1183 if( !
zip.IsOk() ||
zip.GetTotalEntries() == 0 )
1186 for( wxArchiveEntry* entry =
zip.GetNextEntry(); entry; entry =
zip.GetNextEntry() )
1188 wxArrayString path_parts = wxSplit( entry->GetName(), wxFileName::GetPathSeparator(),
1191 if( path_parts.size() != 2 || path_parts[1] != wxT(
"icon.png" ) )
1196 wxMemoryInputStream image_stream(
zip, entry->GetSize() );
1197 wxImage
image( image_stream, wxBITMAP_TYPE_PNG );
1198 bitmaps.emplace( path_parts[0], wxBitmap(
image ) );
1203 wxLogTrace( wxT(
"Error loading png bitmap for entry %s from %s" ), entry->GetName(),
1204 resources_file.GetFullPath() );
1214 std::unordered_map<wxString, wxBitmap> bitmaps;
1217 resources_dir_fn.AppendDir( wxT(
"resources" ) );
1218 wxDir resources_dir( resources_dir_fn.GetPath() );
1220 if( !resources_dir.IsOpened() )
1224 bool more = resources_dir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS | wxDIR_HIDDEN );
1228 wxFileName icon( resources_dir_fn.GetPath(), wxT(
"icon.png" ) );
1229 icon.AppendDir( subdir );
1231 if( icon.FileExists() )
1233 wxString actual_package_id = subdir;
1234 actual_package_id.Replace(
'_',
'.' );
1238 wxBitmap bitmap( icon.GetFullPath(), wxBITMAP_TYPE_PNG );
1239 bitmaps.emplace( actual_package_id, bitmap );
1244 wxLogTrace( wxT(
"Error loading png bitmap from %s" ), icon.GetFullPath() );
1248 more = resources_dir.GetNext( &subdir );
1292 std::unordered_set<wxString> repo_ids;
1294 for( std::pair<const wxString, PCM_INSTALLATION_ENTRY>& pair :
m_installed )
1296 if( !pair.second.pinned )
1297 repo_ids.insert( pair.second.repository_id );
1303 if( repo_ids.count( repository_id ) == 0 )
1307 _(
"Fetching repository..." ) );
1318 int availableUpdateCount = 0;
1321 for( std::pair<const wxString, PCM_INSTALLATION_ENTRY>& pair :
m_installed )
1333 availableUpdateCount++;
1374 && wxMessageBox(
_(
"This plugin requires the KiCad API, which is currently "
1375 "disabled in preferences. Would you like to enable it?" ),
1376 _(
"Enable KiCad API" ), wxICON_QUESTION | wxYES_NO,
m_dialog )
1380 m_dialog->ParentFrame()->Kiway().CommonSettingsChanged();
wxString GetMajorMinorVersion()
Get only the major and minor version in a string major.minor.
const std::tuple< int, int, int > & GetMajorMinorPatchTuple()
Get the build version numbers as a tuple.
std::shared_ptr< BACKGROUND_JOB > Create(const wxString &aName)
Creates a background job with the given name.
void Remove(std::shared_ptr< BACKGROUND_JOB > job)
Removes the given background job from any lists and frees it.
Code outside of kicommon must validate through this class rather than instantiating nlohmann::json_sc...
nlohmann::json Validate(const nlohmann::json &aJson, nlohmann::json_schema::error_handler &aErrorHandler, const nlohmann::json_uri &aInitialUri=nlohmann::json_uri("#")) const
int Perform()
Equivalent to curl_easy_perform.
void SetHeader(const std::string &aName, const std::string &aValue)
Set an arbitrary header for the HTTP(s) request.
bool SetTransferCallback(const TRANSFER_CALLBACK &aCallback, size_t aInterval)
bool SetURL(const std::string &aURL)
Set the request URL.
bool SetFollowRedirects(bool aFollow)
Enable the following of HTTP(s) and other redirects, by default curl does not follow redirects.
bool SetStallTimeout(long aMinBytesPerSec, long aDurationSecs)
Detect stalled transfers without limiting overall transfer time.
bool SetOutputStream(const std::ostream *aOutput)
const std::string GetErrorText(int aCode)
Fetch CURL's "friendly" error string for a given error code.
static wxString GetDefault3rdPartyPath()
Gets the default path for PCM packages.
static wxString GetStockDataPath(bool aRespectRunFromBuildDir=true)
Gets the stock (install) data path, which is the base path for things like scripting,...
static wxString GetUserCachePath()
Gets the stock (install) 3d viewer plugins path.
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.
virtual COMMON_SETTINGS * GetCommonSettings() const
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
virtual BACKGROUND_JOBS_MONITOR & GetBackgroundJobMonitor() const
time_t getCurrentTimestamp() const
const std::vector< PCM_PACKAGE > & GetRepositoryPackages(const wxString &aRepositoryId) const
Get the packages metadata from a previously cached repository.
void SetRepositoryList(const STRING_PAIR_LIST &aRepositories)
Set list of repositories.
std::unique_ptr< JSON_SCHEMA_VALIDATOR > m_schema_v1_validator
bool DownloadToStream(const wxString &aUrl, std::ostream *aOutput, PROGRESS_REPORTER *aReporter, const size_t aSizeLimit=DEFAULT_DOWNLOAD_MEM_LIMIT, const std::string &aAccept="")
Downloads url to an output stream.
void ValidateJson(const nlohmann::json &aJson, const nlohmann::json_uri &aUri=nlohmann::json_uri("#")) const
Validates json against a specific definition in the PCM schema.
std::unordered_map< wxString, PCM_REPOSITORY > m_repository_cache
bool m_apiEnablePromptNeeded
const PCM_REPOSITORY & getCachedRepository(const wxString &aRepositoryId) const
Get the cached repository metadata.
int GetPackageSearchRank(const PCM_PACKAGE &aPackage, const wxString &aSearchTerm)
Get the approximate measure of how much given package matches the search term.
void MarkUninstalled(const PCM_PACKAGE &aPackage)
Mark package as uninstalled.
std::unique_ptr< JSON_SCHEMA_VALIDATOR > m_schema_v2_validator
bool CacheRepository(const wxString &aRepositoryId)
Cache specified repository packages and other metadata.
void SaveInstalledPackages()
Saves metadata of installed packages to disk.
~PLUGIN_CONTENT_MANAGER()
const std::vector< PCM_INSTALLATION_ENTRY > GetInstalledPackages() const
Get list of installed packages.
void SetPinned(const wxString &aPackageId, const bool aPinned)
Set the pinned status of a package.
static void PreparePackage(PCM_PACKAGE &aPackage)
Parses version strings and calculates compatibility.
PLUGIN_CONTENT_MANAGER(std::function< void(int)> aAvailableUpdateCallbac)
bool fetchPackages(const wxString &aUrl, const std::optional< wxString > &aHash, std::vector< PCM_PACKAGE > &aPackages, PROGRESS_REPORTER *aReporter, int aSchemaVersion=1)
Downloads packages metadata to in memory stream, verifies hash and attempts to parse it.
std::thread m_updateThread
PCM_PACKAGE_STATE GetPackageState(const wxString &aRepositoryId, const wxString &aPackageId)
Get current state of the package.
STRING_TUPLE_LIST::const_iterator findRepository(const wxString &aRepositoryId) const
Find a configured repository by id.
std::map< wxString, PCM_INSTALLATION_ENTRY > m_installed
void RunBackgroundUpdate()
Runs a background update thread that checks for new package versions.
std::unordered_map< wxString, wxBitmap > GetRepositoryPackageBitmaps(const wxString &aRepositoryId)
Get the icon bitmaps for repository packages.
const wxString GetPackageUpdateVersion(const PCM_PACKAGE &aPackage)
Get the preferred package update version or empty string if there is none.
void MarkInstalled(const PCM_PACKAGE &aPackage, const wxString &aVersion, const wxString &aRepositoryId)
Mark package as installed.
static bool UsesSWIGRuntime(const PCM_PACKAGE &aPackage, const wxString &aVersion)
Returns true if the selected package version requires SWIG.
std::unordered_map< wxString, wxBitmap > GetInstalledPackageBitmaps()
Get the icon bitmaps for installed packages.
const wxString & GetInstalledPackageVersion(const wxString &aPackageId) const
Get the current version of an installed package.
void updateInstalledPackagesMetadata(const wxString &aRepositoryId)
Updates metadata of installed packages from freshly fetched repo.
bool IsPackagePinned(const wxString &aPackageId) const
Returns pinned status of a package.
static const std::tuple< int, int, int > m_kicad_version
std::shared_ptr< BACKGROUND_JOB > m_updateBackgroundJob
void StopBackgroundUpdate()
Interrupts and joins() the update thread.
static constexpr size_t DEFAULT_DOWNLOAD_MEM_LIMIT
< Default download limit of 10 Mb to not use too much memory
STRING_TUPLE_LIST m_repository_list
std::function< void(int)> m_availableUpdateCallback
static wxString ResolveRepositoryId(const wxString &aPackageId, const wxString &aRecordedName, const STRING_TUPLE_LIST &aRepositoryList, const std::unordered_map< wxString, PCM_REPOSITORY > &aCache)
Find the cached repository that publishes a given package.
bool FetchRepository(const wxString &aUrl, PCM_REPOSITORY &aRepository, PROGRESS_REPORTER *aReporter)
Fetches repository metadata from given url.
void ResolveInstalledPackageRepositories()
Repair the repository id of every installed package.
void ShowApiEnablePromptIfNeeded()
void DiscardRepositoryCache(const wxString &aRepositoryId)
Discard in-memory and on-disk cache of a repository.
bool VerifyHash(std::istream &aStream, const wxString &aHash) const
Verifies SHA256 hash of a binary stream.
void ReadEnvVar()
Stores 3rdparty path from environment variables.
bool resolveInstalledPackageRepository(PCM_INSTALLATION_ENTRY &aEntry)
Repair the repository id of a single installed package.
A progress reporter interface for use in multi-threaded environments.
virtual bool IsCancelled() const =0
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void Report(const wxString &aMessage)=0
Display aMessage in the progress bar dialog.
virtual void SetTitle(const wxString &aTitle)=0
Change the title displayed on the window caption.
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
void error(const json::json_pointer &ptr, const json &instance, const std::string &message) override
static bool empty(const wxTextEntryBase *aCtrl)
Base window classes and related definitions.
Functions related to environment variables, including help functions.
static const wxChar tracePcm[]
Flag to enable PCM debugging output.
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
std::function< int(size_t, size_t, size_t, size_t)> TRANSFER_CALLBACK
Wrapper interface around the curl_easy API/.
KICOMMON_API std::optional< wxString > GetVersionedEnvVarValue(const std::map< wxString, ENV_VAR_ITEM > &aMap, const wxString &aBaseName)
Attempt to retrieve the value of a versioned environment variable, such as KICAD8_TEMPLATE_DIR.
static const std::string PCM_ACCEPT_V2
std::vector< std::pair< wxString, wxString > > STRING_PAIR_LIST
const std::unordered_set< wxString > PCM_PACKAGE_DIRECTORIES({ "plugins", "footprints", "3dmodels", "symbols", "resources", "colors", "templates", "scripts" })
< Contains list of all valid directories that get extracted from a package archive
std::vector< std::tuple< wxString, wxString, wxString > > STRING_TUPLE_LIST
PGM_BASE & Pgm()
The global program "get" accessor.
< Package version metadataPackage metadata
PCM_PACKAGE_VERSION_STATUS status
std::optional< wxString > kicad_version_max
std::optional< int > version_epoch
std::vector< std::string > platforms
std::tuple< int, int, int, int > parsed_version
uint64_t install_timestamp
Repository reference to a resource.
wxString description_full
std::vector< std::string > tags
std::optional< PCM_CONTACT > maintainer
std::vector< PACKAGE_VERSION > versions
Package installation entry.
PCM_RESOURCE_REFERENCE packages
std::vector< PCM_PACKAGE > package_list
std::optional< PCM_RESOURCE_REFERENCE > resources
std::unordered_map< wxString, size_t > package_map
std::optional< wxString > sha256
uint64_t update_timestamp
UPDATE_CANCELLER(std::shared_ptr< BACKGROUND_JOB > &aJob)
std::shared_ptr< BACKGROUND_JOB > & m_jobToCancel
JSON_SCHEMA_VALIDATOR validator(schema)
IbisParser parser & reporter
wxString result
Test unit parsing edge cases and error handling.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().