Imported Upstream version 17.30.1 upstream/17.30.1
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 20 Sep 2022 06:40:56 +0000 (15:40 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 20 Sep 2022 06:40:56 +0000 (15:40 +0900)
25 files changed:
VERSION.cmake
doc/autoinclude/FeatureTest.doc
doc/autoinclude/Plugins.doc
libzypp.spec.cmake
package/libzypp.changes
po/cs.po
po/fr.po
po/id.po
po/mk.po
po/nb.po
po/nn.po
po/pt_BR.po
zypp-core/base/Exception.h
zypp-core/fs/watchfile.h
zypp/CMakeLists.txt
zypp/Fetcher.cc
zypp/RepoManager.cc
zypp/ZYppCommitPolicy.cc
zypp/media/MediaCurl.cc
zypp/repo/Downloader.cc
zypp/repo/Downloader.h
zypp/repo/PluginRepoverification.cc [new file with mode: 0644]
zypp/repo/PluginRepoverification.h [new file with mode: 0644]
zypp/sat/Solvable.h
zypp/target/TargetImpl.cc

index 246d276..8cc6792 100644 (file)
@@ -61,8 +61,8 @@
 SET(LIBZYPP_MAJOR "17")
 SET(LIBZYPP_COMPATMINOR "22")
 SET(LIBZYPP_MINOR "30")
-SET(LIBZYPP_PATCH "0")
+SET(LIBZYPP_PATCH "1")
 #
-# LAST RELEASED: 17.30.0 (22)
+# LAST RELEASED: 17.30.1 (22)
 # (The number in parenthesis is LIBZYPP_COMPATMINOR)
 #=======
index 318dce5..6198792 100644 (file)
@@ -38,6 +38,13 @@ Packages requiring a feature may use the corresponding \c Requires: in their .sp
     <DD>Added COMMITBEGIN/COMMITEND.</DD>
   </DL></DD>
 
+  <DT>plugin:repoverification</DT>
+  <DD><DL>
+    <DT>\ref plugin-repoverification </DT>
+    <DT>version 0</DT>
+    <DD>Repository metadata verification beyond GPG.</DD>
+  </DL></DD>
+
   <DT>plugin:services</DT>
   <DD><DL>
     <DT>\ref plugin-services </DT>
index fb2ce37..2f7eb00 100644 (file)
@@ -102,6 +102,8 @@ The plugins default location is obtained from \ref zypp::ZConfig::pluginsPath()
 
 \subpage plugin-system Receive notification if system content has changed
 
+\subpage plugin-repoverification Repository metadata verification beyond GPG
+
 \ref plugin-services
 
 \ref plugin-url-resolver
index fa29dd1..d3befbb 100644 (file)
@@ -61,6 +61,7 @@ Provides:       libzypp(plugin:commit) = 1
 Provides:       libzypp(plugin:services) = 1
 Provides:       libzypp(plugin:system) = 1
 Provides:       libzypp(plugin:urlresolver) = 0
+Provides:       libzypp(plugin:repoverification) = 0
 Provides:       libzypp(repovarexpand) = 1.1
 
 %if 0%{?suse_version}
index 7c2a680..e40b9c9 100644 (file)
@@ -1,4 +1,19 @@
 -------------------------------------------------------------------
+Mon May 30 14:37:57 CEST 2022 - ma@suse.de
+
+- PluginRepoverification: initial version hooked into
+  repo::Downloader and repo refresh.
+- Immediately start monitoring the download.transfer_timeout.
+  Do not wait until the first data arrived. (bsc#1199042)
+- singletrans: no dry-run commit if doing just download-only.
+- Work around cases where sat repo.start points to an invalid
+  solvable.  May happen if (wrong arch) solvables were removed
+  at the  beginning of the repo.
+- fix misplaced #endif SINGLE_RPMTRANS_AS_DEFAULT_FOR_ZYPPER
+  (fixes #388)
+- version 17.30.1 (22)
+
+-------------------------------------------------------------------
 Fri Mar 25 17:08:46 CET 2022 - ma@suse.de
 
 - ZConfig: Update solver settings if target changes (bsc#1196368)
index ed22f82..f441017 100644 (file)
--- a/po/cs.po
+++ b/po/cs.po
@@ -20,16 +20,16 @@ msgstr ""
 "Project-Id-Version: zypp\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2022-03-14 15:21+0100\n"
-"PO-Revision-Date: 2021-07-26 20:11+0000\n"
+"PO-Revision-Date: 2022-04-06 23:12+0000\n"
 "Last-Translator: Aleš Kastner <alkas@volny.cz>\n"
-"Language-Team: Czech <https://l10n.opensuse.org/projects/libzypp/master/cs/"
-">\n"
+"Language-Team: Czech <https://l10n.opensuse.org/projects/libzypp/master/cs/>"
+"\n"
 "Language: cs\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
-"X-Generator: Weblate 4.7.1\n"
+"X-Generator: Weblate 4.9.1\n"
 
 #: zypp/CountryCode.cc:50
 msgid "Unknown country: "
@@ -4602,23 +4602,25 @@ msgstr "neinstalovatelní poskytovatelé: "
 #: zypp/solver/detail/SATResolver.cc:1253
 #, boost-format
 msgid "%1% is not yet fully integrated into %2%."
-msgstr ""
+msgstr "%1% ještě není plně zaintegrován do %2%."
 
 #: zypp/solver/detail/SATResolver.cc:1254
 msgid ""
 "Typically you want to keep the PTF and choose to not install the maintenance "
 "patches."
 msgstr ""
+"Obvykle budete chtít ponechat PTF a vybrat, že nechcete instalovat údržbové "
+"záplaty."
 
 #. translator: %1% is the name of a PTF.
 #: zypp/solver/detail/SATResolver.cc:1259
 #, boost-format
 msgid "The installed %1% blocks the desired action."
-msgstr ""
+msgstr "Nainstalovaný %1% blokuje vyžadovanou akci."
 
 #: zypp/solver/detail/SATResolver.cc:1260
 msgid "Typically you want to keep the PTF and choose to cancel the action."
-msgstr ""
+msgstr "Obvykle budete chtít ponechat PTF a vybrat zrušení této akce."
 
 #: zypp/solver/detail/SATResolver.cc:1316
 #, boost-format
@@ -4660,7 +4662,7 @@ msgstr "nežádejte instalaci řešení poskytující %1%"
 #: zypp/solver/detail/SATResolver.cc:1422
 #, boost-format
 msgid "do not ask to delete all solvables providing %1%"
-msgstr "nepožadujte smazání všech řešitelných problémů poskytujících %1%"
+msgstr "nepožadovat smazání všech řešitelných problémů poskytujících% 1%"
 
 #: zypp/solver/detail/SATResolver.cc:1435
 #, boost-format
@@ -4814,11 +4816,11 @@ msgstr "Nepodařilo se smazat veřejný klíč %1%"
 
 #: zypp/target/rpm/RpmDb.cc:1271
 msgid "Package header is not signed!"
-msgstr ""
+msgstr "Hlavička balíčku není podepsaná!"
 
 #: zypp/target/rpm/RpmDb.cc:1273
 msgid "Package payload is not signed!"
-msgstr ""
+msgstr "Obsah balíčku není podepsán!"
 
 #. Translator: %s = name of an rpm package. A list of diffs follows
 #. this message.
index 8241973..c9171f1 100644 (file)
--- a/po/fr.po
+++ b/po/fr.po
@@ -20,10 +20,10 @@ msgstr ""
 "Project-Id-Version: zypp.fr\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2022-03-14 15:21+0100\n"
-"PO-Revision-Date: 2022-03-04 11:12+0000\n"
-"Last-Translator: Sophie Leroy <sophie@stoquart.com>\n"
-"Language-Team: French <https://l10n.opensuse.org/projects/libzypp/master/fr/"
-">\n"
+"PO-Revision-Date: 2022-04-02 20:12+0000\n"
+"Last-Translator: Lucie Charrier <c.chalu@free.fr>\n"
+"Language-Team: French <https://l10n.opensuse.org/projects/libzypp/master/fr/>"
+"\n"
 "Language: fr\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -4640,7 +4640,7 @@ msgstr "Impossible de supprimer la clé publique %1%"
 
 #: zypp/target/rpm/RpmDb.cc:1271
 msgid "Package header is not signed!"
-msgstr ""
+msgstr "L'en-tête du paquet n'est pas signé !"
 
 #: zypp/target/rpm/RpmDb.cc:1273
 msgid "Package payload is not signed!"
index ab877c4..e16694c 100644 (file)
--- a/po/id.po
+++ b/po/id.po
@@ -9,8 +9,8 @@ msgstr ""
 "Project-Id-Version: YaST (@memory@)\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2022-03-14 15:21+0100\n"
-"PO-Revision-Date: 2022-03-09 05:31+0000\n"
-"Last-Translator: Andika Triwidada <andika@gmail.com>\n"
+"PO-Revision-Date: 2022-05-20 11:13+0000\n"
+"Last-Translator: Kukuh Syafaat <syafaatkukuh@gmail.com>\n"
 "Language-Team: Indonesian <https://l10n.opensuse.org/projects/libzypp/master/"
 "id/>\n"
 "Language: id\n"
@@ -5043,11 +5043,11 @@ msgstr "Gagal menghapus kunci publik %1%"
 
 #: zypp/target/rpm/RpmDb.cc:1271
 msgid "Package header is not signed!"
-msgstr ""
+msgstr "Header paket tidak ditandatangani!"
 
 #: zypp/target/rpm/RpmDb.cc:1273
 msgid "Package payload is not signed!"
-msgstr ""
+msgstr "Payload paket tidak ditandatangani!"
 
 #. Translator: %s = name of an rpm package. A list of diffs follows
 #. this message.
index 092b1ee..64cdfa2 100644 (file)
--- a/po/mk.po
+++ b/po/mk.po
@@ -7,81 +7,82 @@ msgstr ""
 "Project-Id-Version: YaST (@memory@)\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2022-03-14 15:21+0100\n"
-"PO-Revision-Date: 2001-07-17 16:12+0200\n"
-"Last-Translator: Зоран Димовски <zoki.dimovski@gmail.com>\n"
-"Language-Team: Macedonian <i18n@suse.de>\n"
+"PO-Revision-Date: 2022-05-26 04:13+0000\n"
+"Last-Translator: Kristijan Fremen Velkovski <me@krisfremen.com>\n"
+"Language-Team: Macedonian <https://l10n.opensuse.org/projects/libzypp/master/"
+"mk/>\n"
 "Language: mk\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.9.1\n"
 
 #: zypp/CountryCode.cc:50
 msgid "Unknown country: "
-msgstr ""
+msgstr "Непозната држава: "
 
 #. Defined CountryCode constants
 #. Defined LanguageCode constants
 #: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148
 msgid "No Code"
-msgstr ""
+msgstr "Без код"
 
 #: zypp/CountryCode.cc:158
 msgid "Andorra"
-msgstr ""
+msgstr "Андора"
 
 # US
 # fuzzy
 #. :AND:020:
 #: zypp/CountryCode.cc:159
-#, fuzzy
 msgid "United Arab Emirates"
-msgstr "Соединетите Американски Држави"
+msgstr "Соединети Американски Држави"
 
 #. :ARE:784:
 #: zypp/CountryCode.cc:160
 msgid "Afghanistan"
-msgstr ""
+msgstr "Афганистан"
 
 # AG
 #. :AFG:004:
 #: zypp/CountryCode.cc:161
 msgid "Antigua and Barbuda"
-msgstr "Antigua и Barbuda"
+msgstr "Антигва и Барбуда"
 
 #. :ATG:028:
 #: zypp/CountryCode.cc:162
 msgid "Anguilla"
-msgstr ""
+msgstr "Ангила"
 
 #. :AIA:660:
 #: zypp/CountryCode.cc:163
 msgid "Albania"
-msgstr ""
+msgstr "Албанија"
 
 # AM
 # fuzzy
 #. :ALB:008:
 #: zypp/CountryCode.cc:164
 msgid "Armenia"
-msgstr "Ð\90Ñ\80генÑ\82ина"
+msgstr "Ð\90Ñ\80мениÑ\98а"
 
 # AN
 # fuzzy
 #. :ARM:051:
 #: zypp/CountryCode.cc:165
 msgid "Netherlands Antilles"
-msgstr "Холандија"
+msgstr "Холандски Антили"
 
 #. :ANT:530:
 #: zypp/CountryCode.cc:166
 msgid "Angola"
-msgstr ""
+msgstr "Ангола"
 
 #. :AGO:024:
 #: zypp/CountryCode.cc:167
 msgid "Antarctica"
-msgstr ""
+msgstr "Антарктика"
 
 # AR
 #. :ATA:010:
@@ -94,7 +95,7 @@ msgstr "Аргентина"
 #. :ARG:032:
 #: zypp/CountryCode.cc:169
 msgid "American Samoa"
-msgstr "Америка, Северна"
+msgstr "Америчка Самоа"
 
 # AT
 #. :ASM:016:
@@ -111,7 +112,7 @@ msgstr "Австралија"
 #. :AUS:036:
 #: zypp/CountryCode.cc:172
 msgid "Aruba"
-msgstr ""
+msgstr "Аруба"
 
 # FO
 # fuzzy
@@ -131,7 +132,7 @@ msgstr "Српски"
 #. :AZE:031:
 #: zypp/CountryCode.cc:175
 msgid "Bosnia and Herzegovina"
-msgstr ""
+msgstr "Босна и Херцеговина"
 
 # BB
 #. :BIH:070:
@@ -155,7 +156,7 @@ msgstr "Белгија"
 #. :BEL:056:
 #: zypp/CountryCode.cc:179
 msgid "Burkina Faso"
-msgstr ""
+msgstr "Буркина Фасо"
 
 # BG
 #. :BFA:854:
@@ -173,22 +174,22 @@ msgstr "Бразил"
 #. :BHR:048:
 #: zypp/CountryCode.cc:182
 msgid "Burundi"
-msgstr ""
+msgstr "Бурунди"
 
 #. :BDI:108:
 #: zypp/CountryCode.cc:183
 msgid "Benin"
-msgstr ""
+msgstr "Бенин"
 
 #. :BEN:204:
 #: zypp/CountryCode.cc:184
 msgid "Bermuda"
-msgstr ""
+msgstr "Бермуда"
 
 #. :BMU:060:
 #: zypp/CountryCode.cc:185
 msgid "Brunei Darussalam"
-msgstr ""
+msgstr "Брунеј"
 
 # BO
 #. :BRN:096:
@@ -212,7 +213,7 @@ msgstr "Панама"
 #. :BHS:044:
 #: zypp/CountryCode.cc:189
 msgid "Bhutan"
-msgstr ""
+msgstr "Бутан"
 
 # FO
 # fuzzy
@@ -225,7 +226,7 @@ msgstr "Ирска"
 #. :BVT:074:
 #: zypp/CountryCode.cc:191
 msgid "Botswana"
-msgstr ""
+msgstr "Боцвана"
 
 # BY
 # fuzzy
@@ -249,14 +250,15 @@ msgstr "Канада"
 
 #. :CAN:124:
 #: zypp/CountryCode.cc:195
+#, fuzzy
 msgid "Cocos (Keeling) Islands"
-msgstr ""
+msgstr "Кокосови Острови"
 
 #. :CCK:166:
 #. :CAF:140:
 #: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198
 msgid "Congo"
-msgstr ""
+msgstr "Конго"
 
 # CF
 # fuzzy
@@ -274,15 +276,14 @@ msgstr "Швајцарија"
 #. :CHE:756:
 #: zypp/CountryCode.cc:200
 msgid "Cote D'Ivoire"
-msgstr ""
+msgstr "Брег на Слоновата Коска"
 
 # FO
 # fuzzy
 #. :CIV:384:
 #: zypp/CountryCode.cc:201
-#, fuzzy
 msgid "Cook Islands"
-msgstr "Ð\98Ñ\80Ñ\81ка"
+msgstr "Ð\9aÑ\83кови Ð\9eÑ\81Ñ\82Ñ\80ови"
 
 # CL
 #. :COK:184:
@@ -293,7 +294,7 @@ msgstr "Чиле"
 #. :CHL:152:
 #: zypp/CountryCode.cc:203
 msgid "Cameroon"
-msgstr ""
+msgstr "Камерун"
 
 # CN
 #. :CMR:120:
@@ -311,7 +312,7 @@ msgstr "Колумбија"
 #. :COL:170:
 #: zypp/CountryCode.cc:206
 msgid "Costa Rica"
-msgstr ""
+msgstr "Коста Рика"
 
 # CU
 # fuzzy
@@ -323,17 +324,17 @@ msgstr "Колумбија"
 #. :CUB:192:
 #: zypp/CountryCode.cc:208
 msgid "Cape Verde"
-msgstr ""
+msgstr "Зелен ’Рт"
 
 #. :CPV:132:
 #: zypp/CountryCode.cc:209
 msgid "Christmas Island"
-msgstr ""
+msgstr "Божиќен Остров"
 
 #. :CXR:162:
 #: zypp/CountryCode.cc:210
 msgid "Cyprus"
-msgstr ""
+msgstr "Кипар"
 
 # CZ
 # fuzzy
@@ -351,7 +352,7 @@ msgstr "Германија"
 #. :DEU:276:
 #: zypp/CountryCode.cc:213
 msgid "Djibouti"
-msgstr ""
+msgstr "Џибути"
 
 # DK
 #. :DJI:262:
@@ -402,12 +403,12 @@ msgstr "Енергија"
 #. :EGY:818:
 #: zypp/CountryCode.cc:221
 msgid "Western Sahara"
-msgstr ""
+msgstr "Западна Сахара"
 
 #. :ESH:732:
 #: zypp/CountryCode.cc:222
 msgid "Eritrea"
-msgstr ""
+msgstr "Еритреја"
 
 # ES
 #. :ERI:232:
@@ -431,17 +432,17 @@ msgstr "Финска"
 #. :FIN:246:
 #: zypp/CountryCode.cc:226
 msgid "Fiji"
-msgstr ""
+msgstr "Фиџи"
 
 #. :FJI:242:
 #: zypp/CountryCode.cc:227
 msgid "Falkland Islands (Malvinas)"
-msgstr ""
+msgstr "Фолкландските Острови (Малвини)"
 
 #. :FLK:238:
 #: zypp/CountryCode.cc:228
 msgid "Federated States of Micronesia"
-msgstr ""
+msgstr "Сојузни Држави на Микронезија"
 
 # FO
 # fuzzy
@@ -459,17 +460,17 @@ msgstr "Франција"
 #. :FRA:250:
 #: zypp/CountryCode.cc:231
 msgid "Metropolitan France"
-msgstr ""
+msgstr "Метрополитна Франција"
 
 #. :FXX:249:
 #: zypp/CountryCode.cc:232
 msgid "Gabon"
-msgstr ""
+msgstr "Габон"
 
 #. :GAB:266:
 #: zypp/CountryCode.cc:233
 msgid "United Kingdom"
-msgstr ""
+msgstr "Обединето Кралство"
 
 # GD
 #. :GBR:826:
@@ -506,7 +507,7 @@ msgstr "Кина"
 #. :GHA:288:
 #: zypp/CountryCode.cc:239
 msgid "Gibraltar"
-msgstr ""
+msgstr "Гибралтар"
 
 # GL
 # fuzzy
@@ -525,17 +526,17 @@ msgstr "Јамајка"
 #. :GMB:270:
 #: zypp/CountryCode.cc:242
 msgid "Guinea"
-msgstr ""
+msgstr "Гвинеја"
 
 #. :GIN:324:
 #: zypp/CountryCode.cc:243
 msgid "Guadeloupe"
-msgstr ""
+msgstr "Гваделуп"
 
 #. :GLP:312:
 #: zypp/CountryCode.cc:244
 msgid "Equatorial Guinea"
-msgstr ""
+msgstr "Екваторска Гвинеја"
 
 # GR
 #. :GNQ:226:
@@ -546,7 +547,7 @@ msgstr "Грција"
 #. :GRC:300:
 #: zypp/CountryCode.cc:246
 msgid "South Georgia and the South Sandwich Islands"
-msgstr ""
+msgstr "Јужна Џорџија и Јужни Сендвички Острови"
 
 # GT
 #. :SGS:239:
@@ -564,17 +565,17 @@ msgstr "Гватемала"
 #. :GUM:316:
 #: zypp/CountryCode.cc:249
 msgid "Guinea-Bissau"
-msgstr ""
+msgstr "Гвинеја-Бисао"
 
 #. :GNB:624:
 #: zypp/CountryCode.cc:250
 msgid "Guyana"
-msgstr ""
+msgstr "Гвајана"
 
 #. :GUY:328:
 #: zypp/CountryCode.cc:251
 msgid "Hong Kong"
-msgstr ""
+msgstr "Хонгконг"
 
 #. :HKG:344:
 #: zypp/CountryCode.cc:252
@@ -596,7 +597,7 @@ msgstr "Хрватска"
 #. :HRV:191:
 #: zypp/CountryCode.cc:255
 msgid "Haiti"
-msgstr ""
+msgstr "Хаити"
 
 # HU
 #. :HTI:332:
@@ -626,7 +627,7 @@ msgstr "Израел"
 #. :ISR:376:
 #: zypp/CountryCode.cc:260
 msgid "Isle of Man"
-msgstr ""
+msgstr "Островот Ман"
 
 # IN
 # fuzzy
@@ -637,7 +638,7 @@ msgstr "Икони"
 #. :IND:356:
 #: zypp/CountryCode.cc:262
 msgid "British Indian Ocean Territory"
-msgstr ""
+msgstr "Британска Индоокеанска Територија"
 
 # IQ
 # fuzzy
@@ -649,7 +650,7 @@ msgstr "Израел"
 #. :IRQ:368:
 #: zypp/CountryCode.cc:264
 msgid "Iran"
-msgstr ""
+msgstr "Иран"
 
 # IS
 #. :IRN:364:
@@ -666,7 +667,7 @@ msgstr "Италија"
 #. :ITA:380:
 #: zypp/CountryCode.cc:267
 msgid "Jersey"
-msgstr ""
+msgstr "Џерси"
 
 # JM
 # fuzzy
@@ -690,7 +691,7 @@ msgstr "Јапонија"
 #. :JPN:392:
 #: zypp/CountryCode.cc:271
 msgid "Kenya"
-msgstr ""
+msgstr "Кенија"
 
 # KZ
 # fuzzy
@@ -710,7 +711,7 @@ msgstr "Колумбија"
 #. :KHM:116:
 #: zypp/CountryCode.cc:274
 msgid "Kiribati"
-msgstr ""
+msgstr "Кирибати"
 
 #. :KIR:296:
 #: zypp/CountryCode.cc:275
@@ -1423,7 +1424,7 @@ msgstr "Финска"
 #. :VGB:092:
 #: zypp/CountryCode.cc:394
 msgid "Virgin Islands, U.S."
-msgstr "ФинÑ\81ка"
+msgstr "Ð\90меÑ\80иканÑ\81ки Ð\94евÑ\81Ñ\82вени Ð\9eÑ\81Ñ\82Ñ\80ови"
 
 #. :VIR:850:
 #: zypp/CountryCode.cc:395
@@ -4102,9 +4103,9 @@ msgstr ""
 #. TranslatorExplanation '%s' is a pathname
 #: zypp/RepoManager.cc:321 zypp/RepoManager.cc:784 zypp/RepoManager.cc:1565
 #: zypp/repo/PluginServices.cc:49
-#, fuzzy, c-format, boost-format
+#, boost-format, c-format
 msgid "Failed to read directory '%s'"
-msgstr "Failed to parse: %s."
+msgstr "Неможеше да се прочита директориумот '%s'"
 
 #: zypp/RepoManager.cc:331
 #, boost-format
@@ -4142,9 +4143,9 @@ msgstr[0] ""
 msgstr[1] ""
 
 #: zypp/RepoManager.cc:1172 zypp/RepoManager.cc:1285 zypp/RepoManager.cc:1341
-#, fuzzy, c-format, boost-format
+#, boost-format, c-format
 msgid "Can't create %s"
-msgstr "Couldn't open file: %s."
+msgstr "Неможеше да се створи %s"
 
 #: zypp/RepoManager.cc:1180
 msgid "Can't create metadata cache directory."
@@ -4161,9 +4162,9 @@ msgid "Can't create cache at %s - no writing permissions."
 msgstr ""
 
 #: zypp/RepoManager.cc:1408
-#, fuzzy, c-format, boost-format
+#, boost-format, c-format
 msgid "Failed to cache repo (%d)."
-msgstr "Failed to parse: %s."
+msgstr "Неможеше да се кешира складиштето (%d)."
 
 #: zypp/RepoManager.cc:1419
 msgid "Unhandled repository type"
@@ -4208,9 +4209,9 @@ msgstr ""
 
 #. TranslatorExplanation '%s' is a filename
 #: zypp/RepoManager.cc:1809 zypp/RepoManager.cc:2011
-#, fuzzy, c-format, boost-format
+#, boost-format, c-format
 msgid "Can't delete '%s'"
-msgstr "Couldn't open file: %s."
+msgstr "Неможеше да се избрише '%s'"
 
 #: zypp/RepoManager.cc:1999 zypp/RepoManager.cc:2449
 msgid "Can't figure out where the service is stored."
@@ -4830,9 +4831,8 @@ msgid " executed"
 msgstr ""
 
 #: zypp/target/TargetImpl.cc:441
-#, fuzzy
 msgid " execution failed"
-msgstr "DBI Execution failed: %s"
+msgstr " егзекуцијата не успеа"
 
 #. translators: We may find the same script content in files with different names.
 #. Only the first occurence is executed, subsequent ones are skipped. It's a one-line
@@ -5122,9 +5122,9 @@ msgid "Can't chroot to '%s' (%s)."
 msgstr ""
 
 #: zypp-core/zyppng/io/forkspawnengine.cc:282
-#, fuzzy, c-format, boost-format
+#, boost-format, c-format
 msgid "Can't chdir to '%s' (%s)."
-msgstr "Couldn't open file: %s."
+msgstr "Неможеше да се chdir-а во '%s' (%s)."
 
 #: zypp-core/zyppng/io/forkspawnengine.cc:283
 #, c-format, boost-format
@@ -5164,14 +5164,14 @@ msgid "Can't exec '%s', unexpected error."
 msgstr ""
 
 #: zypp-media/mediaexception.cc:33
-#, fuzzy, c-format, boost-format
+#, boost-format, c-format
 msgid "Failed to mount %s on %s"
-msgstr "Failed to parse: %s."
+msgstr "Неможеше да се монтира %s во %s"
 
 #: zypp-media/mediaexception.cc:43
-#, fuzzy, c-format, boost-format
+#, boost-format, c-format
 msgid "Failed to unmount %s"
-msgstr "Failed to parse: %s."
+msgstr "Неможеше да се демонтира %s"
 
 #: zypp-media/mediaexception.cc:48
 #, c-format, boost-format
index fab74da..139b4e4 100644 (file)
--- a/po/nb.po
+++ b/po/nb.po
@@ -13,8 +13,8 @@ msgstr ""
 "Project-Id-Version: zypp\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2022-03-14 15:21+0100\n"
-"PO-Revision-Date: 2020-09-15 11:48+0000\n"
-"Last-Translator: Alexander Johansen <alej0hio2007@gmail.com>\n"
+"PO-Revision-Date: 2022-05-29 21:13+0000\n"
+"Last-Translator: Karl Ove Hufthammer <karl@huftis.org>\n"
 "Language-Team: Norwegian Bokmål <https://l10n.opensuse.org/projects/libzypp/"
 "master/nb/>\n"
 "Language: nb\n"
@@ -22,7 +22,7 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 3.6.1\n"
+"X-Generator: Weblate 4.9.1\n"
 
 #: zypp/CountryCode.cc:50
 msgid "Unknown country: "
@@ -219,7 +219,7 @@ msgstr "Botswana"
 #. :BWA:072:
 #: zypp/CountryCode.cc:192
 msgid "Belarus"
-msgstr "Hviterussland"
+msgstr "Belarus"
 
 # BZ
 # fuzzy
@@ -1651,7 +1651,7 @@ msgstr "Beja"
 #. language code: bel be
 #: zypp/LanguageCode.cc:259
 msgid "Belarusian"
-msgstr "Hviterussisk"
+msgstr "Belarusisk"
 
 #. language code: bem
 #: zypp/LanguageCode.cc:261
index a4ff8d3..3123b3e 100644 (file)
--- a/po/nn.po
+++ b/po/nn.po
@@ -7,7 +7,7 @@ msgstr ""
 "Project-Id-Version: @PACKAGE@\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2022-03-14 15:21+0100\n"
-"PO-Revision-Date: 2018-03-09 22:04+0000\n"
+"PO-Revision-Date: 2022-05-29 21:13+0000\n"
 "Last-Translator: Karl Ove Hufthammer <karl@huftis.org>\n"
 "Language-Team: Norwegian Nynorsk <https://l10n.opensuse.org/projects/libzypp/"
 "master/nn/>\n"
@@ -16,7 +16,7 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 2.18\n"
+"X-Generator: Weblate 4.9.1\n"
 
 #: zypp/CountryCode.cc:50
 msgid "Unknown country: "
@@ -200,7 +200,7 @@ msgstr "Botswana"
 #. :BWA:072:
 #: zypp/CountryCode.cc:192
 msgid "Belarus"
-msgstr "Kviterussland"
+msgstr "Belarus"
 
 #. :BLR:112:
 #: zypp/CountryCode.cc:193
@@ -1542,7 +1542,7 @@ msgstr ""
 #. language code: bel be
 #: zypp/LanguageCode.cc:259
 msgid "Belarusian"
-msgstr "Kviterussisk"
+msgstr "Belarusisk"
 
 #. language code: bem
 #: zypp/LanguageCode.cc:261
index ab08f38..7518a36 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "Project-Id-Version: zypp\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2022-03-14 15:21+0100\n"
-"PO-Revision-Date: 2022-02-27 17:12+0000\n"
-"Last-Translator: Rodrigo Macedo <rmsolucoeseminformatic4@gmail.com>\n"
+"PO-Revision-Date: 2022-04-02 00:12+0000\n"
+"Last-Translator: Luiz Fernando Ranghetti <elchevive68@gmail.com>\n"
 "Language-Team: Portuguese (Brazil) <https://l10n.opensuse.org/projects/"
 "libzypp/master/pt_BR/>\n"
 "Language: pt_BR\n"
@@ -4614,11 +4614,11 @@ msgstr "Falha ao remover chave pública %1%"
 
 #: zypp/target/rpm/RpmDb.cc:1271
 msgid "Package header is not signed!"
-msgstr ""
+msgstr "O cabeçalho do pacote não está assinado!"
 
 #: zypp/target/rpm/RpmDb.cc:1273
 msgid "Package payload is not signed!"
-msgstr ""
+msgstr "A carga útil do pacote não está assinada!"
 
 #. Translator: %s = name of an rpm package. A list of diffs follows
 #. this message.
index e911da1..36faf5d 100644 (file)
@@ -220,6 +220,16 @@ namespace zypp
     /** \overload std::exception_ptr */
     void remember( std::exception_ptr old_r );
 
+    /** Remembering a plain string is most probably not wanted - we \ref addHistory.
+     * It would discards the old history and replace it with this string.
+     * If that's actually your intent, explicitly wrap it into an \ref Exception.
+     */
+    void remember( const std::string & msg_r )
+    { addHistory( msg_r ); }
+    /** \overload moving */
+    void remember( std::string && msg_r )
+    { addHistory( std::move(msg_r) ); }
+
     /** Add some message text to the history. */
     void addHistory( const std::string & msg_r );
     /** \overload moving */
index 9cf6028..977e3a5 100644 (file)
@@ -56,11 +56,11 @@ namespace zypp
       WatchFile( const Pathname & path_r = Pathname(),
                  Initial mode            = INIT )
       : _path( path_r )
-      {
-        PathInfo pi( mode == INIT ? path_r : Pathname() );
-        _size  = pi.size();
-        _mtime = pi.mtime();
-      }
+      { ctorInit( mode ); }
+
+      WatchFile( Pathname && path_r, Initial mode = INIT )
+      : _path( std::move(path_r) )
+      { ctorInit( mode ); }
 
       const Pathname & path() const
       { return _path; }
@@ -90,6 +90,14 @@ namespace zypp
       }
 
     private:
+      void ctorInit( Initial mode )
+      {
+        PathInfo pi( mode == INIT ? _path : Pathname() );
+        _size  = pi.size();
+        _mtime = pi.mtime();
+      }
+
+    private:
       Pathname _path;
       off_t  _size;
       time_t _mtime;
index f5030b3..948309e 100644 (file)
@@ -612,6 +612,7 @@ SET( zypp_repo_SRCS
   repo/Downloader.cc
   repo/RepoVariables.cc
   repo/RepoInfoBase.cc
+  repo/PluginRepoverification.cc
   repo/PluginServices.cc
   repo/ServiceRepos.cc
 )
@@ -632,6 +633,7 @@ SET( zypp_repo_HEADERS
   repo/Downloader.h
   repo/RepoVariables.h
   repo/RepoInfoBase.h
+  repo/PluginRepoverification.h
   repo/PluginServices.h
   repo/ServiceRepos.h
 )
index ba9cde9..ff73e1d 100644 (file)
@@ -391,11 +391,11 @@ namespace zypp
     }
     catch ( const FileCheckException &e )
     {
-      ZYPP_RETHROW(e);
+      throw;  // let known exceptions bypass  silently
     }
     catch ( const Exception &e )
     {
-      ZYPP_RETHROW(e);
+      throw; // slet known exceptions bypass  silently
     }
     catch (...)
     {
index d44a2a6..9bf61fe 100644 (file)
@@ -46,6 +46,7 @@
 #include <zypp/repo/yum/Downloader.h>
 #include <zypp/repo/susetags/Downloader.h>
 #include <zypp/repo/PluginServices.h>
+#include <zypp/repo/PluginRepoverification.h>
 
 #include <zypp/Target.h> // for Target::targetDistribution() for repo index services
 #include <zypp/ZYppFactory.h> // to get the Target from ZYpp instance
@@ -518,11 +519,12 @@ namespace zypp
   /// \brief RepoManager implementation.
   ///
   ///////////////////////////////////////////////////////////////////
-  struct RepoManager::Impl
+  struct ZYPP_LOCAL RepoManager::Impl
   {
   public:
     Impl( const RepoManagerOptions &opt )
       : _options(opt)
+      , _pluginRepoverification( _options.pluginsPath/"repoverification", _options.rootDir )
     {
       init_knownServices();
       init_knownRepositories();
@@ -709,6 +711,8 @@ namespace zypp
 
     DefaultIntegral<bool,false> _reposDirty;
 
+    PluginRepoverification _pluginRepoverification;
+
   private:
     friend Impl * rwcowClone<Impl>( const Impl * rhs );
     /** clone for RWCOW_pointer */
@@ -1189,8 +1193,11 @@ namespace zypp
 
           MIL << "Creating downloader for [ " << info.alias() << " ]" << endl;
 
-          if ( repokind.toEnum() == RepoType::RPMMD_e )
-            downloader_ptr.reset(new yum::Downloader(info, mediarootpath));
+          if ( repokind.toEnum() == RepoType::RPMMD_e ) {
+            downloader_ptr.reset(new yum::Downloader(info, mediarootpath ));
+            if ( _pluginRepoverification.checkIfNeeded() )
+              downloader_ptr->setPluginRepoverification( _pluginRepoverification ); // susetags is dead so we apply just to yum
+          }
           else
             downloader_ptr.reset( new susetags::Downloader(info, mediarootpath) );
 
index 73bb917..098f7be 100644 (file)
@@ -62,8 +62,8 @@ namespace zypp
         , JobReport::UserData( "cmdout" ) );
       }
       return ret;
-#endif // SINGLE_RPMTRANS_AS_DEFAULT_FOR_ZYPPER
     })();
+#endif // SINGLE_RPMTRANS_AS_DEFAULT_FOR_ZYPPER
     return singleTrans;
   }
 
index 6572a72..7a61c79 100644 (file)
@@ -116,12 +116,6 @@ namespace internal {
       _timeRcv = now;
       _dnlNow = dlnow;
     }
-    else if ( !_dnlNow && !_dnlTotal )
-    {
-      // Start time counting as soon as first data arrives.
-      // Skip the connection / redirection time at begin.
-      return;
-    }
 
     // init or reset if time jumps back
     if ( !_timeStart || _timeStart > now )
index 1449d8f..ef387b7 100644 (file)
@@ -140,11 +140,10 @@ void Downloader::download( MediaSetAccess &media,
 
 void Downloader::defaultDownloadMasterIndex( MediaSetAccess & media_r, const Pathname & destdir_r, const Pathname & masterIndex_r )
 {
+  // always download them, even if repoGpgCheck is disabled
   Pathname sigpath = masterIndex_r.extend( ".asc" );
   Pathname keypath = masterIndex_r.extend( ".key" );
 
-  // always download them, even if repoGpgCheck is disabled
-
   //enable precache for next start() call
   setMediaSetAccess( media_r );
   enqueue( OnMediaLocation( sigpath, 1 ).setOptional( true ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ) );
@@ -152,21 +151,29 @@ void Downloader::defaultDownloadMasterIndex( MediaSetAccess & media_r, const Pat
   start( destdir_r );
   reset();
 
-  FileChecker checker; // set to sigchecker if appropriate, else Null.
-  ExtraSignatureFileChecker sigchecker;
-  bool isSigned = PathInfo(destdir_r / sigpath).isExist();
+  // The local files are in destdir_r, if they were present on the server
+  Pathname sigpathLocal { destdir_r/sigpath };
+  Pathname keypathLocal { destdir_r/keypath };
 
+
+  CompositeFileChecker checkers;
+
+  if ( _pluginRepoverification && _pluginRepoverification->isNeeded() )
+    checkers.add( _pluginRepoverification->getChecker( sigpathLocal, keypathLocal, repoInfo() ) );
+
+  ExtraSignatureFileChecker sigchecker;
+  bool isSigned = PathInfo(sigpathLocal).isExist();
   if ( repoInfo().repoGpgCheck() )
   {
     if ( isSigned || repoInfo().repoGpgCheckIsMandatory() )
     {
       // only add the signature if it exists
       if ( isSigned )
-        sigchecker.signature( destdir_r / sigpath );
+        sigchecker.signature( sigpathLocal );
 
       // only add the key if it exists
-      if ( PathInfo(destdir_r / keypath).isExist() )
-        sigchecker.addPublicKey( destdir_r / keypath );
+      if ( PathInfo(keypathLocal).isExist() )
+        sigchecker.addPublicKey( keypathLocal );
 
       // set the checker context even if the key is not known
       // (unsigned repo, key file missing; bnc #495977)
@@ -187,7 +194,7 @@ void Downloader::defaultDownloadMasterIndex( MediaSetAccess & media_r, const Pat
           { INT << "Oops!" << endl; }
         });
       }
-      checker = FileChecker( ref(sigchecker) );        // ref() to the local sigchecker is important as we want back fileValidated!
+      checkers.add( ref(sigchecker) ); // ref() to the local sigchecker is important as we want back fileValidated!
     }
     else
     {
@@ -199,7 +206,7 @@ void Downloader::defaultDownloadMasterIndex( MediaSetAccess & media_r, const Pat
     WAR << "Signature checking disabled in config of repository " << repoInfo().alias() << endl;
   }
 
-  enqueue( OnMediaLocation( masterIndex_r, 1 ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ), checker ? checker : FileChecker(NullFileChecker()) );
+  enqueue( OnMediaLocation( masterIndex_r, 1 ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ), checkers );
   start( destdir_r, media_r );
   reset();
 
index 29e8acd..23e108f 100644 (file)
@@ -10,6 +10,8 @@
 #ifndef ZYPP_REPO_DOWNLOADER
 #define ZYPP_REPO_DOWNLOADER
 
+#include <optional>
+
 #include <zypp/Url.h>
 #include <zypp/Pathname.h>
 #include <zypp-core/ui/ProgressData>
 #include <zypp/MediaSetAccess.h>
 #include <zypp/Fetcher.h>
 #include <zypp/RepoInfo.h>
+#include <zypp/repo/PluginRepoverification.h>
 
 namespace zypp
 {
   namespace repo
   {
+    using zypp_private::repo::PluginRepoverification;
+
     /**
       * \short Downloader base class
       *
@@ -57,12 +62,20 @@ namespace zypp
 
       const RepoInfo & repoInfo() const { return _repoinfo; }
 
+
+      void setPluginRepoverification( std::optional<PluginRepoverification> pluginRepoverification_r )
+      { _pluginRepoverification = std::move(pluginRepoverification_r); }
+
+      void setNoPluginRepoverification()
+      { setPluginRepoverification( std::nullopt ); }
+
       protected:
         /** Common workflow downloading a (signed) master index file */
         void defaultDownloadMasterIndex( MediaSetAccess & media_r, const Pathname & destdir_r, const Pathname & masterIndex_r );
 
       private:
         RepoInfo _repoinfo;
+        std::optional<PluginRepoverification> _pluginRepoverification;  ///< \see \ref plugin-repoverification
     };
   } // ns repo
 } // ns zypp
diff --git a/zypp/repo/PluginRepoverification.cc b/zypp/repo/PluginRepoverification.cc
new file mode 100644 (file)
index 0000000..dd3f257
--- /dev/null
@@ -0,0 +1,222 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/repo/PluginRepoverification.cc
+ */
+#include <iostream>
+#include <sstream>
+
+#include "PluginRepoverification.h"
+
+#include <zypp/Globals.h>
+#include <zypp/PathInfo.h>
+#include <zypp/ExternalProgram.h>
+#include <zypp/base/LogTools.h>
+#include <zypp/base/WatchFile.h>
+
+using std::endl;
+
+///////////////////////////////////////////////////////////////////
+namespace zypp_private
+{
+  using namespace zypp;
+  ///////////////////////////////////////////////////////////////////
+  namespace repo
+  {
+    ///////////////////////////////////////////////////////////////////
+    /// \class PluginRepoverification::Checker::Impl
+    /// \brief PluginRepoverification::Checker data storage.
+    ///////////////////////////////////////////////////////////////////
+    class PluginRepoverification::Checker::Impl
+    {
+    public:
+      Impl( RW_pointer<PluginRepoverification::Impl> parent_r,
+            Pathname sigpathLocal_r, Pathname keypathLocal_r, const RepoInfo & repo_r )
+      : _parent { parent_r }
+      , _sigpathLocal { std::move(sigpathLocal_r) }
+      , _keypathLocal { std::move(keypathLocal_r) }
+      , _repoinfo { repo_r }
+      {}
+
+      RW_pointer<PluginRepoverification::Impl> _parent;
+      Pathname _sigpathLocal;
+      Pathname _keypathLocal;
+      RepoInfo _repoinfo;
+    };
+
+    ///////////////////////////////////////////////////////////////////
+    /// \class PluginRepoverification::Impl
+    /// \brief PluginRepoverification implementation.
+    ///////////////////////////////////////////////////////////////////
+    class PluginRepoverification::Impl
+    {
+      friend std::ostream & operator<<( std::ostream & str, const Impl & obj );
+      friend std::ostream & dumpOn( std::ostream & str, const Impl & obj );
+
+    public:
+      Impl()
+      {}
+
+      Impl( Pathname plugindir_r, Pathname chroot_r )
+      : _watchPlugindir { std::move(plugindir_r), WatchFile::NO_INIT }
+      , _chroot { std::move(chroot_r) }
+      {}
+
+      ~Impl()
+      {}
+
+      bool isNeeded() const
+      { return _isNeeded; }
+
+      bool checkIfNeeded()
+      {
+        if ( _watchPlugindir.hasChanged() ) {
+          _isNeeded = false;
+          // check for at least one executable plugin inside..
+          filesystem::dirForEach( plugindir(),
+                                  [this]( const Pathname & dir_r, const char *const name_r ) -> bool {
+                                    PathInfo pi ( dir_r/name_r );
+                                    if ( pi.isFile() && pi.userMayRX() ) {
+                                      this->_isNeeded = true;
+                                      return false;
+                                    }
+                                    return true;
+                                  } );
+        }
+        return _isNeeded;
+      }
+
+      void verifyWorkflow( const Pathname & file_r, RW_pointer<PluginRepoverification::Checker::Impl> datap_r ) const
+      {
+        // Execute the plugins. They will throw if something is wrong...
+        filesystem::dirForEach( plugindir(),
+                                [&,this]( const Pathname & dir_r, const char *const name_r ) -> bool {
+                                  PathInfo pi ( dir_r/name_r );
+                                  if ( pi.isFile() && pi.userMayRX() )
+                                    this->pluginVerify( name_r, file_r, *datap_r );
+                                  return true;
+                                } );
+      }
+
+    private:
+      void pluginVerify( std::string plugin_r, const Pathname & file_r, const PluginRepoverification::Checker::Impl & data_r ) const
+      {
+        Pathname pluginPath { plugindir()/plugin_r };
+        if ( not _chroot.emptyOrRoot() ) {
+          pluginPath = Pathname::stripprefix( _chroot, pluginPath );
+          // we need to make sure the files are available inside the chroot
+          INT << "chroot PluginRepoverification does not yet work." << endl;
+          return;
+        }
+
+        ExternalProgram::Arguments args;
+        args.push_back( pluginPath.asString() );
+        /// NOTE: Update plugin-repoverification page if new args are supplied
+        args.push_back( "--file" );
+        args.push_back( file_r.asString() );
+        args.push_back( "--fsig" );
+        args.push_back( data_r._sigpathLocal.asString() );
+        args.push_back( "--fkey" );
+        args.push_back( data_r._keypathLocal.asString() );
+        args.push_back( "--ralias" );
+        args.push_back( data_r._repoinfo.alias() );
+        ExternalProgram cmd { args, ExternalProgram::Stderr_To_Stdout, false, -1, false, _chroot };
+
+        std::ostringstream buffer;
+        cmd >> buffer;
+
+        int ret = cmd.close();
+        if ( ret ) {
+          const std::string & msg { str::Format( "Metadata rejected by '%1%' plugin (returned %2%)" ) % plugin_r % ret };
+//           ERR << buffer.str() << endl;
+//           ERR << msg << endl;
+
+          ExceptionType excp { msg };
+          excp.addHistory( buffer.str() );
+          excp.addHistory( str::Format( "%1%%2% returned %3%" ) % (_chroot.emptyOrRoot()?"":"("+_chroot.asString()+")") % pluginPath % ret );
+
+          ZYPP_THROW( std::move(excp) );
+        }
+      }
+
+      const Pathname & plugindir() const
+      { return _watchPlugindir.path(); }
+
+    private:
+      WatchFile _watchPlugindir;
+      Pathname  _chroot;
+      bool _isNeeded = false;
+    };
+
+    /** \relates PluginRepoverification::Impl Stream output */
+    inline std::ostream & operator<<( std::ostream & str, const PluginRepoverification::Impl & obj )
+    { return str << "PluginRepoverification::Impl"; }
+
+    /** \relates PluginRepoverification::Impl Verbose stream output */
+    inline std::ostream & dumpOn( std::ostream & str, const PluginRepoverification::Impl & obj )
+    { return str << obj; }
+
+
+    ///////////////////////////////////////////////////////////////////
+    //
+    // CLASS NAME : PluginRepoverification
+    //
+    ///////////////////////////////////////////////////////////////////
+
+    PluginRepoverification::PluginRepoverification()
+    : _pimpl( new Impl )
+    {}
+
+    PluginRepoverification::PluginRepoverification( Pathname plugindir_r, Pathname chroot_r )
+    : _pimpl( new Impl( std::move(plugindir_r), std::move(chroot_r) ) )
+    {}
+
+    PluginRepoverification::~PluginRepoverification()
+    {}
+
+
+    bool PluginRepoverification::isNeeded() const
+    { return _pimpl->isNeeded(); }
+
+    bool PluginRepoverification::checkIfNeeded()
+    { return _pimpl->checkIfNeeded(); }
+
+    PluginRepoverification::Checker PluginRepoverification::getChecker( const Pathname & sigpathLocal_r, const Pathname & keypathLocal_r,
+                                                                        const RepoInfo & repo_r ) const
+    { return Checker( new Checker::Impl( _pimpl, sigpathLocal_r, keypathLocal_r, repo_r ) ); }
+
+
+    std::ostream & operator<<( std::ostream & str, const PluginRepoverification & obj )
+    { return str << *obj._pimpl; }
+
+    std::ostream & dumpOn( std::ostream & str, const PluginRepoverification & obj )
+    { return dumpOn( str, *obj._pimpl ); }
+
+    bool operator==( const PluginRepoverification & lhs, const PluginRepoverification & rhs )
+    { return lhs._pimpl == rhs._pimpl; }
+
+    ///////////////////////////////////////////////////////////////////
+    //
+    // CLASS NAME : PluginRepoverification::Checker
+    //
+    ///////////////////////////////////////////////////////////////////
+    PluginRepoverification::Checker::Checker( Impl* pimpl_r )
+    : _pimpl { pimpl_r }
+    {}
+
+    PluginRepoverification::Checker::~Checker()
+    {}
+
+    void PluginRepoverification::Checker::operator()( const Pathname & file_r ) const
+    { _pimpl->_parent->verifyWorkflow( file_r, _pimpl ); }
+
+
+  } // namespace repo
+  ///////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
diff --git a/zypp/repo/PluginRepoverification.h b/zypp/repo/PluginRepoverification.h
new file mode 100644 (file)
index 0000000..2957bd4
--- /dev/null
@@ -0,0 +1,128 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/repo/PluginRepoverification.h
+ */
+#ifndef ZYPP_REPO_PLUGINREPOVERIFICATION_H
+#define ZYPP_REPO_PLUGINREPOVERIFICATION_H
+
+#include <iosfwd>
+
+#include <zypp/Globals.h>
+#include <zypp/RepoInfo.h>
+#include <zypp/FileChecker.h>
+#include <zypp/base/PtrTypes.h>
+
+///////////////////////////////////////////////////////////////////
+namespace zypp_private
+{
+  using namespace zypp;
+  ///////////////////////////////////////////////////////////////////
+  namespace repo
+  {
+    ///////////////////////////////////////////////////////////////////
+    /// \class PluginRepoverificationCheckException
+    /// \brief Exceptiontype thrown if a plugins verification fails.
+    ///////////////////////////////////////////////////////////////////
+    class PluginRepoverificationCheckException : public FileCheckException
+    {
+    public:
+      PluginRepoverificationCheckException( const std::string &msg )
+      : FileCheckException(msg)
+      {}
+    };
+
+    ///////////////////////////////////////////////////////////////////
+    /// \class PluginRepoverification
+    /// \brief Repository metadata verification beyond GPG.
+    ///
+    /// Implements the repoverification plugin setup and workflow. Also
+    /// serves as factory for a file \ref FileChecker that can be passed
+    /// to e.g. \ref repo::Downloader when fetching the repos master index file.
+    ///
+    /// If a root dir is defined, plugin scripts will be  executed chrooted.
+    ///
+    /// \see \ref plugin-repoverification for more details.
+    ///////////////////////////////////////////////////////////////////
+    class PluginRepoverification
+    {
+      friend std::ostream & operator<<( std::ostream & str, const PluginRepoverification & obj );
+      friend std::ostream & dumpOn( std::ostream & str, const PluginRepoverification & obj );
+      friend bool operator==( const PluginRepoverification & lhs, const PluginRepoverification & rhs );
+
+      using ExceptionType = PluginRepoverificationCheckException;
+
+    public:
+      /** Default ctor, do nothing */
+      PluginRepoverification();
+
+      /** Ctor monitoring a \a plugindir_r and optional chroot for plugin execution */
+      PluginRepoverification( Pathname plugindir_r, Pathname chroot_r = Pathname() );
+
+      /** Dtor */
+      ~PluginRepoverification();
+
+    public:
+      /** Whether the last \ref checkIfNeeded found plugins to execute at all. */
+      bool isNeeded() const;
+
+      /** Checks whether there are plugins to execute at all. */
+      bool checkIfNeeded();
+
+    public:
+      ///////////////////////////////////////////////////////////////////
+      /// \class Checker
+      /// \brief \ref FileChecker checking all repoverification plugins.
+      ///////////////////////////////////////////////////////////////////
+      class Checker
+      {
+      public:
+        ~Checker();
+
+        /** Check the downloaded master index file.
+         * \throws PluginRepoverificationCheckException If a plugins verification fails.
+         */
+        void operator()( const Pathname & file_r ) const;
+
+      public:
+        class Impl;                 ///< Implementation class.
+      private:
+        friend class PluginRepoverification;  ///< Factory for \ref Checker
+        Checker( Impl* pimpl );
+      private:
+        RW_pointer<Impl> _pimpl;    ///< Pointer to implementation (ref).
+      };
+      ///////////////////////////////////////////////////////////////////
+
+      /** \ref FileChecker factory remembering the location of the master index files GPG signature and key. */
+      Checker getChecker( const Pathname & sigpathLocal_r, const Pathname & keypathLocal_r, const RepoInfo & repo_r ) const;
+
+    public:
+      class Impl;                 ///< Implementation class.
+    private:
+      RW_pointer<Impl> _pimpl;    ///< Pointer to implementation (ref).
+    };
+
+    /** \relates PluginRepoverification Stream output */
+    std::ostream & operator<<( std::ostream & str, const PluginRepoverification & obj );
+
+    /** \relates PluginRepoverification Verbose stream output */
+    std::ostream & dumOn( std::ostream & str, const PluginRepoverification & obj );
+
+    /** \relates PluginRepoverification */
+    bool operator==( const PluginRepoverification & lhs, const PluginRepoverification & rhs );
+
+    /** \relates PluginRepoverification */
+    inline bool operator!=( const PluginRepoverification & lhs, const PluginRepoverification & rhs )
+    { return !( lhs == rhs ); }
+
+  } // namespace repo
+  ///////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
+#endif // ZYPP_REPO_PLUGINREPOVERIFICATION_H
index beef8e3..0c0a45f 100644 (file)
@@ -501,10 +501,11 @@ namespace zypp
     namespace detail
     {
       ///////////////////////////////////////////////////////////////////
-      //
-      //       CLASS NAME : SolvableIterator
-      //
-      /** */
+      /// \class SolvableIterator
+      /// \brief Iterate over valid Solvables in the pool.
+      /// If the Solvable passed to the ctor is not valid, advance
+      /// to the next valid solvable (or Solvable::noSolvable if the
+      /// end is reached,
       class SolvableIterator : public boost::iterator_adaptor<
           SolvableIterator                   // Derived
           , CSolvable*                       // Base
@@ -515,16 +516,16 @@ namespace zypp
       {
         public:
           SolvableIterator()
-          : SolvableIterator::iterator_adaptor_( 0 )
+          : SolvableIterator::iterator_adaptor_( nullptr )
           {}
 
           explicit SolvableIterator( const Solvable & val_r )
-          : SolvableIterator::iterator_adaptor_( 0 )
-          { assignVal( val_r ); }
+          : SolvableIterator::iterator_adaptor_( nullptr )
+          { initialAssignVal( val_r ); }
 
           explicit SolvableIterator( SolvableIdType id_r )
-          : SolvableIterator::iterator_adaptor_( 0 )
-          { assignVal( Solvable( id_r ) ); }
+          : SolvableIterator::iterator_adaptor_( nullptr )
+          { initialAssignVal( Solvable(id_r) ); }
 
         private:
           friend class boost::iterator_core_access;
@@ -536,6 +537,9 @@ namespace zypp
           { assignVal( _val.nextInPool() ); }
 
         private:
+          void initialAssignVal( const Solvable & val_r )
+          { assignVal( val_r ? val_r : val_r.nextInPool() ); }
+
           void assignVal( const Solvable & val_r )
           { _val = val_r; base_reference() = _val.get(); }
 
index 9f3c308..4a64a5b 100644 (file)
@@ -1483,20 +1483,24 @@ namespace zypp
         }
         else
         {
-          // single trans mode does a test install via rpm
-          if ( policy_r.singleTransModeEnabled() ) {
-            commitInSingleTransaction( policy_r, packageCache, result );
-          } else {
-            if ( ! policy_r.dryRun() )
-            {
+          if ( ! policy_r.dryRun() )
+          {
+            if ( policy_r.singleTransModeEnabled() ) {
+              commitInSingleTransaction( policy_r, packageCache, result );
+            } else {
               // if cache is preloaded, check for file conflicts
               commitFindFileConflicts( policy_r, result );
               commit( policy_r, packageCache, result );
             }
-            else
-            {
-              DBG << "dryRun/downloadOnly: Not installing/deleting anything." << endl;
-              if ( explicitDryRun ) {
+          }
+          else
+          {
+            DBG << "dryRun/downloadOnly: Not installing/deleting anything." << endl;
+            if ( explicitDryRun ) {
+              if ( policy_r.singleTransModeEnabled() ) {
+                // single trans mode does a test install via rpm
+                commitInSingleTransaction( policy_r, packageCache, result );
+              } else {
                 // if cache is preloaded, check for file conflicts
                 commitFindFileConflicts( policy_r, result );
               }