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" );
 
   68    void error( 
const json::json_pointer& ptr, 
const json& instance,
 
   69                const std::string& message )
 override 
   71        throw std::invalid_argument( std::string( 
"At " ) + ptr.to_string() + 
", value:\n" 
   72                                     + instance.dump() + 
"\n" + message + 
"\n" );
 
 
 
   78                                        std::function<
void( 
int )> aAvailableUpdateCallback ) :
 
   87    schema_file.AppendDir( wxS( 
"schemas" ) );
 
   96        std::ifstream  installed_stream( f.GetFullPath().fn_str() );
 
   97        nlohmann::json installed;
 
  101            installed_stream >> installed;
 
  103            if( installed.contains( 
"packages" ) && installed[
"packages"].is_array() )
 
  105                for( 
const auto& js_entry : installed[
"packages"] )
 
  112        catch( std::exception& e )
 
  114            wxLogError( wxString::Format( 
_( 
"Error loading installed packages list: %s" ),
 
  128            wxDir package_dir( d.GetPath() );
 
  130            if( !package_dir.IsOpened() )
 
  134            bool     more = package_dir.GetFirst( &subdir, 
"", wxDIR_DIRS | wxDIR_HIDDEN );
 
  138                wxString actual_package_id = subdir;
 
  139                actual_package_id.Replace( 
'_', 
'.' );
 
  144                    wxFileName             subdir_file( d.GetPath(), subdir );
 
  148                    int          stat_code = wxStat( subdir_file.GetFullPath(), &stat );
 
  168                more = package_dir.GetNext( &subdir );
 
  175                   [&]( std::pair<const wxString, PCM_INSTALLATION_ENTRY>& entry )
 
  177                       PreparePackage( entry.second.package );
 
 
  196                                               const size_t       aSizeLimit )
 
  198    bool size_exceeded = 
false;
 
  200    TRANSFER_CALLBACK callback = [&]( 
size_t dltotal, 
size_t dlnow, 
size_t ultotal, 
size_t ulnow )
 
  202        if( aSizeLimit > 0 && ( dltotal > aSizeLimit || dlnow > aSizeLimit ) )
 
  204            size_exceeded = 
true;
 
  213            aReporter->
Report( wxString::Format( 
_( 
"Downloading %lld/%lld kB" ), dlnow / 1000,
 
  226    curl.
SetURL( aUrl.ToUTF8().data() );
 
  235    if( code != CURLE_OK )
 
  239            if( code == CURLE_ABORTED_BY_CALLBACK && size_exceeded )
 
  240                wxMessageBox( 
_( 
"Download is too large." ) );
 
  241            else if( code != CURLE_ABORTED_BY_CALLBACK )
 
 
  255    std::stringstream repository_stream;
 
  257    aReporter->
SetTitle( 
_( 
"Fetching repository" ) );
 
  262    nlohmann::json repository_json;
 
  266        repository_stream >> repository_json;
 
  268        ValidateJson( repository_json, nlohmann::json_uri( 
"#/definitions/Repository" ) );
 
  272    catch( 
const std::exception& e )
 
  276            wxLogError( 
_( 
"Unable to parse repository: %s" ), e.what() );
 
  277            wxLogError( 
_( 
"The given repository URL does not look like a valid KiCad package " 
  278                           "repository. Please double check the URL." ) );
 
 
  289                                           const nlohmann::json_uri& aUri )
 const 
 
  297                                            const std::optional<wxString>& aHash,
 
  298                                            std::vector<PCM_PACKAGE>&      aPackages,
 
  301    std::stringstream packages_stream;
 
  303    aReporter->
SetTitle( 
_( 
"Fetching repository packages" ) );
 
  308            wxLogError( 
_( 
"Unable to load repository packages url." ) );
 
  313    std::istringstream isstream( packages_stream.str() );
 
  315    if( aHash && !
VerifyHash( isstream, *aHash ) )
 
  318            wxLogError( 
_( 
"Packages hash doesn't match. Repository may be corrupted." ) );
 
  325        nlohmann::json packages_json = nlohmann::json::parse( packages_stream.str() );
 
  326        ValidateJson( packages_json, nlohmann::json_uri( 
"#/definitions/PackageArray" ) );
 
  328        aPackages = packages_json[
"packages"].get<std::vector<PCM_PACKAGE>>();
 
  330    catch( std::exception& e )
 
  334            wxLogError( wxString::Format( 
_( 
"Unable to parse packages metadata:\n\n%s" ),
 
 
  347    std::vector<unsigned char> bytes( picosha2::k_digest_size );
 
  349    picosha2::hash256( std::istreambuf_iterator<char>( aStream ), std::istreambuf_iterator<char>(),
 
  350                       bytes.begin(), bytes.end() );
 
  351    std::string hex_str = picosha2::bytes_to_hex_string( bytes.begin(), bytes.end() );
 
  353    return aHash.compare( hex_str ) == 0;
 
 
  361                  wxT( 
"Repository is not cached." ) );
 
 
  372    const auto repository_tuple =
 
  374                          [&aRepositoryId]( 
const std::tuple<wxString, wxString, wxString>& t )
 
  376                              return std::get<0>( t ) == aRepositoryId;
 
  382    wxString url = std::get<2>( *repository_tuple );
 
  388    std::shared_ptr<PROGRESS_REPORTER> reporter;
 
  398    bool packages_cache_exists = 
false;
 
  402    repo_cache.AppendDir( wxT( 
"pcm" ) );
 
  403    repo_cache.AppendDir( aRepositoryId );
 
  404    wxFileName packages_cache( repo_cache.GetPath(), wxT( 
"packages.json" ) );
 
  406    if( repo_cache.FileExists() && packages_cache.FileExists() )
 
  408        std::ifstream  repo_stream( repo_cache.GetFullPath().fn_str() );
 
  418                wxLogError( 
_( 
"Failed to parse locally stored repository.json." ) );
 
  425            std::ifstream packages_cache_stream( packages_cache.GetFullPath().fn_str() );
 
  429                packages_cache_stream >> js;
 
  430                saved_repo.
package_list = js[
"packages"].get<std::vector<PCM_PACKAGE>>();
 
  432                for( 
size_t i = 0; i < saved_repo.
package_list.size(); i++ )
 
  440                packages_cache_exists = 
true;
 
  446                    wxLogError( 
_( 
"Packages cache for current repository is corrupted, it will " 
  447                                   "be redownloaded." ) );
 
  453    if( !packages_cache_exists )
 
  462        for( 
size_t i = 0; i < current_repo.
package_list.size(); i++ )
 
  468        repo_cache.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
 
  470        std::ofstream repo_cache_stream( repo_cache.GetFullPath().fn_str() );
 
  471        repo_cache_stream << std::setw( 4 ) << nlohmann::json( current_repo ) << std::endl;
 
  473        std::ofstream packages_cache_stream( packages_cache.GetFullPath().fn_str() );
 
  475        js[
"packages"] = nlohmann::json( current_repo.
package_list );
 
  476        packages_cache_stream << std::setw( 4 ) << js << std::endl;
 
  487        wxFileName resource_file( repo_cache.GetPath(), wxT( 
"resources.zip" ) );
 
  491        if( resource_file.FileExists() )
 
  492            mtime = wxFileModificationTime( resource_file.GetFullPath() );
 
  496            std::ofstream resources_stream( resource_file.GetFullPath().fn_str(),
 
  497                                            std::ios_base::binary );
 
  499            reporter->SetTitle( 
_( 
"Downloading resources" ) );
 
  505            resources_stream.close();
 
  509                std::ifstream read_stream( resource_file.GetFullPath().fn_str(),
 
  510                                           std::ios_base::binary );
 
  519                        wxLogError( 
_( 
"Resources file hash doesn't match and will not be used. " 
  520                                       "Repository may be corrupted." ) );
 
  523                    wxRemoveFile( resource_file.GetFullPath() );
 
  529                wxRemoveFile( resource_file.GetFullPath() );
 
 
  550        wxLogTrace( 
tracePcm, wxS( 
"Invalid/Missing repository " ) + aRepositoryId );
 
  554    for( std::pair<const wxString, PCM_INSTALLATION_ENTRY>& pair : 
m_installed )
 
  566        std::optional<PACKAGE_VERSION> current_version;
 
  568        auto current_version_it =
 
  572                                  return version.version == entry.current_version;
 
  576            current_version = *current_version_it; 
 
  586                                  return version.version == entry.current_version;
 
  597                           return a.parsed_version > b.parsed_version;
 
 
  609        int epoch = 0, major = 0, minor = 0, patch = 0;
 
  614        wxStringTokenizer version_tokenizer( ver.
version, 
"." );
 
  616        major = wxAtoi( version_tokenizer.GetNextToken() );
 
  618        if( version_tokenizer.HasMoreTokens() )
 
  619            minor = wxAtoi( version_tokenizer.GetNextToken() );
 
  621        if( version_tokenizer.HasMoreTokens() )
 
  622            patch = wxAtoi( version_tokenizer.GetNextToken() );
 
  624        ver.
parsed_version = std::make_tuple( epoch, major, minor, patch );
 
  629        auto parse_version_tuple =
 
  630                []( 
const wxString& version, 
int deflt )
 
  632                    int ver_major = deflt;
 
  633                    int ver_minor = deflt;
 
  634                    int ver_patch = deflt;
 
  636                    wxStringTokenizer tokenizer( version, 
"." );
 
  638                    ver_major = wxAtoi( tokenizer.GetNextToken() );
 
  640                    if( tokenizer.HasMoreTokens() )
 
  641                        ver_minor = wxAtoi( tokenizer.GetNextToken() );
 
  643                    if( tokenizer.HasMoreTokens() )
 
  644                        ver_patch = wxAtoi( tokenizer.GetNextToken() );
 
  646                    return std::tuple<int, int, int>( ver_major, ver_minor, ver_patch );
 
  657        wxString platform = wxT( 
"windows" );
 
  658#elif defined( __APPLE__ ) 
  659        wxString platform = wxT( 
"macos" );
 
  661        wxString platform = wxT( 
"linux" );
 
  676                   return a.parsed_version > b.parsed_version;
 
 
  681const std::vector<PCM_PACKAGE>&
 
  684    static std::vector<PCM_PACKAGE> 
empty{};
 
 
  702        auto it = std::find_if( aRepositories.begin(), aRepositories.end(),
 
  703                                [&]( 
const auto& new_entry )
 
  705                                    return new_entry.first == std::get<1>( entry );
 
  708        if( it == aRepositories.end() )
 
  717    for( 
const std::pair<wxString, wxString>& repo : aRepositories )
 
  719        std::string url_sha = picosha2::hash256_hex_string( repo.second );
 
  720        m_repository_list.push_back( std::make_tuple( url_sha.substr( 0, 16 ), repo.first,
 
 
  732    repo_cache.AppendDir( wxT( 
"pcm" ) );
 
  733    repo_cache.AppendDir( aRepositoryId );
 
  735    if( repo_cache.DirExists() )
 
  736        repo_cache.Rmdir( wxPATH_RMDIR_RECURSIVE );
 
 
  741                                            const wxString& aRepositoryId )
 
  759        if( !aRepositoryId.IsEmpty() )
 
  777        && !
Pgm().GetCommonSettings()->m_Api.enable_server )
 
  779        if( wxMessageBox( 
_( 
"This plugin requires the KiCad API, which is currently " 
  780                             "disabled in preferences. Would you like to enable it?" ),
 
  781                         _( 
"Enable KiCad API" ), wxICON_QUESTION | wxYES_NO, 
m_dialog )
 
  785            m_dialog->ParentFrame()->Kiway().CommonSettingsChanged();
 
 
  798                                                           const wxString& aPackageId )
 
  835                                        return ver.compatible;
 
 
  846                  wxT( 
"GetPackageUpdateVersion called on a not installed package" ) );
 
  850    auto installed_ver_it = std::find_if(
 
  854                return ver.version == entry.current_version;
 
  858                  wxT( 
"Installed package version not found" ) );
 
  860    auto ver_it = std::find_if( aPackage.
versions.begin(), aPackage.
versions.end(),
 
  863                                    return ver.compatible
 
  864                                           && installed_ver_it->status >= ver.status
 
  865                                           && installed_ver_it->parsed_version < ver.parsed_version;
 
  868    return ver_it == aPackage.
versions.end() ? wxString( wxT( 
"" ) ) : ver_it->version;
 
 
  873    return std::chrono::duration_cast<std::chrono::seconds>(
 
  874                   std::chrono::system_clock::now().time_since_epoch() ).count();
 
 
  883        js[
"packages"] = nlohmann::json::array();
 
  885        for( std::pair<const wxString, PCM_INSTALLATION_ENTRY>& pair : 
m_installed )
 
  887            js[
"packages"].emplace_back( pair.second );
 
  891        std::ofstream stream( f.GetFullPath().fn_str() );
 
  893        stream << std::setw( 4 ) << js << std::endl;
 
  895    catch( nlohmann::detail::exception& )
 
 
  904    std::vector<PCM_INSTALLATION_ENTRY> v;
 
  907                   [&v]( 
const std::pair<const wxString, PCM_INSTALLATION_ENTRY>& entry )
 
  909                       v.push_back( entry.second );
 
  912    std::sort( v.begin(), v.end(),
 
  915                   return ( a.install_timestamp < b.install_timestamp )
 
  916                          || ( a.install_timestamp == b.install_timestamp
 
  917                               && a.package.identifier < b.package.identifier );
 
 
  928                  wxT( 
"Installed package not found." ) );
 
  930    return m_installed.at( aPackageId ).current_version;
 
 
  953                                                  const wxString&    aSearchTerm )
 
  955    wxArrayString terms = wxStringTokenize( aSearchTerm.Lower(), wxS( 
" " ), wxTOKEN_STRTOK );
 
  958    const auto find_term_matches =
 
  959            [&]( 
const wxString& str )
 
  962                wxString lower = str.Lower();
 
  964                for( 
const wxString& term : terms )
 
  966                    if( lower.Find( term ) != wxNOT_FOUND )
 
  974    if( terms.size() == 1 && terms[0] == aPackage.
identifier )
 
  977    if( terms.size() == 1 && find_term_matches( aPackage.
identifier ) )
 
  981    rank += 500 * find_term_matches( aPackage.
name );
 
  984    for( 
const std::string& tag : aPackage.
tags )
 
  985        rank += 100 * find_term_matches( wxString( tag ) );
 
  988    rank += 10 * find_term_matches( aPackage.
description );
 
  992    rank += find_term_matches( aPackage.
author.
name );
 
  995        rank += 3 * find_term_matches( aPackage.
maintainer->name );
 
  998    for( 
const std::pair<const std::string, wxString>& entry : aPackage.
resources )
 
 1000        rank += find_term_matches( entry.first );
 
 1001        rank += find_term_matches( entry.second );
 
 1005    if( terms.size() == 1 && terms[0] == aPackage.
license )
 
 
 1012std::unordered_map<wxString, wxBitmap>
 
 1015    std::unordered_map<wxString, wxBitmap> bitmaps;
 
 1018    resources_file.AppendDir( wxT( 
"pcm" ) );
 
 1019    resources_file.AppendDir( aRepositoryId );
 
 1021    if( !resources_file.FileExists() )
 
 1024    wxFFileInputStream stream( resources_file.GetFullPath() );
 
 1025    wxZipInputStream   
zip( stream );
 
 1027    if( !
zip.IsOk() || 
zip.GetTotalEntries() == 0 )
 
 1030    for( wxArchiveEntry* entry = 
zip.GetNextEntry(); entry; entry = 
zip.GetNextEntry() )
 
 1032        wxArrayString path_parts = wxSplit( entry->GetName(), wxFileName::GetPathSeparator(),
 
 1035        if( path_parts.size() != 2 || path_parts[1] != wxT( 
"icon.png" ) )
 
 1040            wxMemoryInputStream image_stream( 
zip, entry->GetSize() );
 
 1041            wxImage             
image( image_stream, wxBITMAP_TYPE_PNG );
 
 1042            bitmaps.emplace( path_parts[0], wxBitmap( 
image ) );
 
 1047            wxLogTrace( wxT( 
"Error loading png bitmap for entry %s from %s" ), entry->GetName(),
 
 1048                        resources_file.GetFullPath() );
 
 
 1058    std::unordered_map<wxString, wxBitmap> bitmaps;
 
 1061    resources_dir_fn.AppendDir( wxT( 
"resources" ) );
 
 1062    wxDir resources_dir( resources_dir_fn.GetPath() );
 
 1064    if( !resources_dir.IsOpened() )
 
 1068    bool     more = resources_dir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS | wxDIR_HIDDEN );
 
 1072        wxFileName icon( resources_dir_fn.GetPath(), wxT( 
"icon.png" ) );
 
 1073        icon.AppendDir( subdir );
 
 1075        if( icon.FileExists() )
 
 1077            wxString actual_package_id = subdir;
 
 1078            actual_package_id.Replace( 
'_', 
'.' );
 
 1082                wxBitmap bitmap( icon.GetFullPath(), wxBITMAP_TYPE_PNG );
 
 1083                bitmaps.emplace( actual_package_id, bitmap );
 
 1088                wxLogTrace( wxT( 
"Error loading png bitmap from %s" ), icon.GetFullPath() );
 
 1092        more = resources_dir.GetNext( &subdir );
 
 
 1136                std::unordered_set<wxString> repo_ids;
 
 1138                for( std::pair<const wxString, PCM_INSTALLATION_ENTRY>& pair : 
m_installed )
 
 1140                    if( !pair.second.pinned )
 
 1141                        repo_ids.insert( pair.second.repository_id );
 
 1147                    if( repo_ids.count( repository_id ) == 0 )
 
 1151                            _( 
"Fetching repository..." ) );
 
 1162                int availableUpdateCount = 0;
 
 1165                for( std::pair<const wxString, PCM_INSTALLATION_ENTRY>& pair : 
m_installed )
 
 1177                            availableUpdateCount++;
 
 
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.
 
int Perform()
Equivalent to curl_easy_perform.
 
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 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_validator
 
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
 
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.
 
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 DownloadToStream(const wxString &aUrl, std::ostream *aOutput, PROGRESS_REPORTER *aReporter, const size_t aSizeLimit=DEFAULT_DOWNLOAD_MEM_LIMIT)
Downloads url to an output stream.
 
std::thread m_updateThread
 
PCM_PACKAGE_STATE GetPackageState(const wxString &aRepositoryId, const wxString &aPackageId)
Get current state of the package.
 
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.
 
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.
 
STRING_TUPLE_LIST m_repository_list
 
bool fetchPackages(const wxString &aUrl, const std::optional< wxString > &aHash, std::vector< PCM_PACKAGE > &aPackages, PROGRESS_REPORTER *aReporter)
Downloads packages metadata to in memory stream, verifies hash and attempts to parse it.
 
std::function< void(int)> m_availableUpdateCallback
 
bool FetchRepository(const wxString &aUrl, PCM_REPOSITORY &aRepository, PROGRESS_REPORTER *aReporter)
Fetches repository metadata from given url.
 
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.
 
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.
 
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
 
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
 
wxString result
Test unit parsing edge cases and error handling.
 
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().