Manifest.cpp (8505B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "winget/Manifest.h" 5 #include "winget/Locale.h" 6 #include "winget/UserSettings.h" 7 8 namespace AppInstaller::Manifest 9 { 10 namespace 11 { 12 void AddFoldedStringToSetIfNotEmpty(std::set<string_t>& set, const string_t& value) 13 { 14 if (!value.empty()) 15 { 16 set.emplace(Utility::FoldCase(value)); 17 } 18 } 19 } 20 21 void Manifest::ApplyLocale(const std::string& locale) 22 { 23 CurrentLocalization = DefaultLocalization; 24 25 // Get target locale from Preferred Languages settings if applicable 26 std::vector<std::string> targetLocales; 27 if (locale.empty()) 28 { 29 targetLocales = Locale::GetUserPreferredLanguages(); 30 } 31 else 32 { 33 targetLocales.emplace_back(locale); 34 } 35 36 for (auto const& targetLocale : targetLocales) 37 { 38 const ManifestLocalization* bestLocalization = nullptr; 39 double bestScore = Locale::GetDistanceOfLanguage(targetLocale, DefaultLocalization.Locale); 40 41 for (auto const& localization : Localizations) 42 { 43 double score = Locale::GetDistanceOfLanguage(targetLocale, localization.Locale); 44 if (score > bestScore) 45 { 46 bestLocalization = &localization; 47 bestScore = score; 48 } 49 } 50 51 // If there's better locale than default And is compatible with target locale, merge and return; 52 if (bestScore >= Locale::MinimumDistanceScoreAsCompatibleMatch) 53 { 54 if (bestLocalization != nullptr) 55 { 56 CurrentLocalization.ReplaceOrMergeWith(*bestLocalization); 57 } 58 break; 59 } 60 } 61 } 62 63 std::vector<string_t> Manifest::GetAggregatedTags() const 64 { 65 std::vector<string_t> resultTags = DefaultLocalization.Get<Localization::Tags>(); 66 67 for (const auto& locale : Localizations) 68 { 69 auto tags = locale.Get<Localization::Tags>(); 70 for (const auto& tag : tags) 71 { 72 if (std::find(resultTags.begin(), resultTags.end(), tag) == resultTags.end()) 73 { 74 resultTags.emplace_back(tag); 75 } 76 } 77 } 78 79 return resultTags; 80 } 81 82 std::vector<string_t> Manifest::GetAggregatedCommands() const 83 { 84 std::vector<string_t> resultCommands; 85 86 for (const auto& installer : Installers) 87 { 88 for (const auto& command : installer.Commands) 89 { 90 if (std::find(resultCommands.begin(), resultCommands.end(), command) == resultCommands.end()) 91 { 92 resultCommands.emplace_back(command); 93 } 94 } 95 } 96 97 return resultCommands; 98 } 99 100 Utility::VersionRange Manifest::GetArpVersionRange() const 101 { 102 bool arpVersionFound = false; 103 Utility::Version minVersion; 104 Utility::Version maxVersion; 105 106 for (auto const& installer : Installers) 107 { 108 if (DoesInstallerTypeSupportArpVersionRange(installer.EffectiveInstallerType())) 109 { 110 for (auto const& entry : installer.AppsAndFeaturesEntries) 111 { 112 if (!entry.DisplayVersion.empty()) 113 { 114 Utility::Version arpVersion{ entry.DisplayVersion }; 115 116 if (!arpVersionFound) 117 { 118 // This is the first arp version found, populate both min and max version 119 minVersion = arpVersion; 120 maxVersion = arpVersion; 121 arpVersionFound = true; 122 continue; 123 } 124 125 if (arpVersion < minVersion) 126 { 127 minVersion = arpVersion; 128 } 129 else if (arpVersion > maxVersion) 130 { 131 maxVersion = arpVersion; 132 } 133 } 134 } 135 } 136 } 137 138 return arpVersionFound ? Utility::VersionRange{ minVersion, maxVersion } : Utility::VersionRange{}; 139 } 140 141 std::vector<string_t> Manifest::GetPackageFamilyNames() const 142 { 143 return GetSystemReferenceStrings( 144 [](const ManifestInstaller& i) -> const Utility::NormalizedString& { return i.PackageFamilyName; }); 145 } 146 147 std::vector<string_t> Manifest::GetProductCodes() const 148 { 149 return GetSystemReferenceStrings( 150 [](const ManifestInstaller& i) -> const Utility::NormalizedString& { return i.ProductCode; }, 151 [](const AppsAndFeaturesEntry& e) -> const Utility::NormalizedString& { return e.ProductCode; }); 152 } 153 154 std::vector<string_t> Manifest::GetUpgradeCodes() const 155 { 156 return GetSystemReferenceStrings( 157 {}, 158 [](const AppsAndFeaturesEntry& e) -> const Utility::NormalizedString& { return e.UpgradeCode; }); 159 } 160 161 std::vector<string_t> Manifest::GetPackageNames() const 162 { 163 std::set<string_t> set; 164 165 AddFoldedStringToSetIfNotEmpty(set, DefaultLocalization.Get<Localization::PackageName>()); 166 for (const auto& loc : Localizations) 167 { 168 AddFoldedStringToSetIfNotEmpty(set, loc.Get<Localization::PackageName>()); 169 } 170 171 // In addition to the names used for our display, add the display names from the ARP entries 172 for (const auto& installer : Installers) 173 { 174 for (const auto& appsAndFeaturesEntry : installer.AppsAndFeaturesEntries) 175 { 176 AddFoldedStringToSetIfNotEmpty(set, appsAndFeaturesEntry.DisplayName); 177 } 178 } 179 180 std::vector<Utility::NormalizedString> result( 181 std::make_move_iterator(set.begin()), 182 std::make_move_iterator(set.end())); 183 184 return result; 185 } 186 187 std::vector<string_t> Manifest::GetPublishers() const 188 { 189 std::set<string_t> set; 190 191 AddFoldedStringToSetIfNotEmpty(set, DefaultLocalization.Get<Localization::Publisher>()); 192 for (const auto& loc : Localizations) 193 { 194 AddFoldedStringToSetIfNotEmpty(set, loc.Get<Localization::Publisher>()); 195 } 196 197 // In addition to the publishers used for our display, add the publisher from the ARP entries 198 for (const auto& installer : Installers) 199 { 200 for (const auto& appsAndFeaturesEntry : installer.AppsAndFeaturesEntries) 201 { 202 AddFoldedStringToSetIfNotEmpty(set, appsAndFeaturesEntry.Publisher); 203 } 204 } 205 206 std::vector<Utility::NormalizedString> result( 207 std::make_move_iterator(set.begin()), 208 std::make_move_iterator(set.end())); 209 210 return result; 211 } 212 213 std::vector<string_t> Manifest::GetSystemReferenceStrings( 214 std::function<const string_t& (const ManifestInstaller&)> extractStringFromInstaller, 215 std::function<const string_t& (const AppsAndFeaturesEntry&)> extractStringFromAppsAndFeaturesEntry) const 216 { 217 std::set<string_t> set; 218 219 for (const auto& installer : Installers) 220 { 221 if (extractStringFromInstaller) 222 { 223 const auto& installerString = extractStringFromInstaller(installer); 224 AddFoldedStringToSetIfNotEmpty(set, installerString); 225 } 226 227 if (extractStringFromAppsAndFeaturesEntry) 228 { 229 for (const auto& entry : installer.AppsAndFeaturesEntries) 230 { 231 const auto& entryString = extractStringFromAppsAndFeaturesEntry(entry); 232 AddFoldedStringToSetIfNotEmpty(set, entryString); 233 } 234 } 235 } 236 237 std::vector<Utility::NormalizedString> result( 238 std::make_move_iterator(set.begin()), 239 std::make_move_iterator(set.end())); 240 241 return result; 242 } 243 }