From b0f4b486e6850c5f98520ccf19da71d0ed748ae4 Mon Sep 17 00:00:00 2001
From: Michael Vogt <mvo@debian.org>
Date: Sun, 21 Sep 2014 10:18:03 +0200
Subject: generalize Acquire::GzipIndex

---
 cmdline/apt-get.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc
index 845d67d2b..2e283da5a 100644
--- a/cmdline/apt-get.cc
+++ b/cmdline/apt-get.cc
@@ -665,7 +665,7 @@ static bool DoDownload(CommandLine &CmdL)
    {
       pkgAcquire::UriIterator I = Fetcher.UriBegin();
       for (; I != Fetcher.UriEnd(); ++I)
-	 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
+	 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile)  << ' ' <<
 	       I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
       return true;
    }
-- 
cgit v1.2.3


From a3a91fd7bab34983a008854728baf26034d4033e Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Fri, 20 Jun 2014 20:28:54 +0200
Subject: count strings more accurately for stats

So far, only the few strings stored in stringitems were counted, but
many more strings are directly inserted into the cache. We account for
this now by identifying all these different strings and measure their
length. We are still not at the correct size of the cache in 'stats'
this way, but we are now again a bit closer.

Git-Dch: Ignore
---
 cmdline/apt-cache.cc | 53 ++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 39 insertions(+), 14 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc
index 1447feb81..4030ce4e6 100644
--- a/cmdline/apt-cache.cc
+++ b/cmdline/apt-cache.cc
@@ -375,31 +375,56 @@ static bool Stats(CommandLine &)
       SizeToStr(Cache->Head().DescFileCount*Cache->Head().DescFileSz) << ')' << endl;
    cout << _("Total Provides mappings: ") << Cache->Head().ProvidesCount << " (" <<
       SizeToStr(Cache->Head().ProvidesCount*Cache->Head().ProvidesSz) << ')' << endl;
-   
-   // String list stats
-   unsigned long Size = 0;
-   unsigned long Count = 0;
-   for (pkgCache::StringItem *I = Cache->StringItemP + Cache->Head().StringList;
-        I!= Cache->StringItemP; I = Cache->StringItemP + I->NextItem)
-   {
-      Count++;
-      Size += strlen(Cache->StrP + I->String) + 1;
-   }
-   cout << _("Total globbed strings: ") << Count << " (" << SizeToStr(Size) << ')' << endl;
 
-   unsigned long DepVerSize = 0;
+   // String list stats
+   std::set<map_stringitem_t> stritems;
+   for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
+      stritems.insert(G->Name);
    for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
    {
+      stritems.insert(P->Arch);
       for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
       {
+	 if (V->VerStr != 0)
+	    stritems.insert(V->VerStr);
+	 if (V->Section != 0)
+	    stritems.insert(V->Section);
 	 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ++D)
 	 {
 	    if (D->Version != 0)
-	       DepVerSize += strlen(D.TargetVer()) + 1;
+	       stritems.insert(D->Version);
+	 }
+	 for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; ++D)
+	 {
+	    stritems.insert(D->md5sum);
+	    stritems.insert(D->language_code);
 	 }
       }
+      for (pkgCache::PrvIterator Prv = P.ProvidesList(); Prv.end() == false; ++Prv)
+      {
+	 if (Prv->ProvideVersion != 0)
+	    stritems.insert(Prv->ProvideVersion);
+      }
    }
-   cout << _("Total dependency version space: ") << SizeToStr(DepVerSize) << endl;
+   for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F)
+   {
+      stritems.insert(F->FileName);
+      stritems.insert(F->Archive);
+      stritems.insert(F->Codename);
+      stritems.insert(F->Component);
+      stritems.insert(F->Version);
+      stritems.insert(F->Origin);
+      stritems.insert(F->Label);
+      stritems.insert(F->Architecture);
+      stritems.insert(F->Site);
+      stritems.insert(F->IndexType);
+   }
+   unsigned long Size = 0;
+   for (std::set<map_stringitem_t>::const_iterator i = stritems.begin(); i != stritems.end(); ++i)
+      Size += strlen(Cache->StrP + *i) + 1;
+
+   cout << _("Total globbed strings: ") << stritems.size() << " (" << SizeToStr(Size) << ')' << endl;
+   stritems.clear();
 
    unsigned long Slack = 0;
    for (int I = 0; I != 7; I++)
-- 
cgit v1.2.3


From 67caa2e6538f13ff7a0d77e98ad6c58af998376d Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Sun, 17 Aug 2014 13:27:59 +0200
Subject: mark pkg(All|Dist)Upgrade as deprecated

The comment above their definition marks them already as such, so this
is only a formalisation of the deprecation and fixes the occurances we
have in our own code together with removing a magic number.

Git-Dch: Ignore
---
 cmdline/apt-get.cc             | 2 +-
 cmdline/apt-internal-solver.cc | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc
index d6cd94f72..aed1beb4d 100644
--- a/cmdline/apt-get.cc
+++ b/cmdline/apt-get.cc
@@ -540,7 +540,7 @@ static bool DoDSelectUpgrade(CommandLine &)
    }
 
    // Now upgrade everything
-   if (pkgAllUpgrade(Cache) == false)
+   if (APT::Upgrade::Upgrade(Cache, APT::Upgrade::FORBID_REMOVE_PACKAGES | APT::Upgrade::FORBID_INSTALL_NEW_PACKAGES) == false)
    {
       ShowBroken(c1out,Cache,false);
       return _error->Error(_("Internal error, problem resolver broke stuff"));
diff --git a/cmdline/apt-internal-solver.cc b/cmdline/apt-internal-solver.cc
index c24a96cdf..0f2ec6283 100644
--- a/cmdline/apt-internal-solver.cc
+++ b/cmdline/apt-internal-solver.cc
@@ -175,10 +175,10 @@ int main(int argc,const char *argv[])					/*{{{*/
 
 	std::string failure;
 	if (upgrade == true) {
-		if (pkgAllUpgrade(CacheFile) == false)
+		if (APT::Upgrade::Upgrade(CacheFile, APT::Upgrade::FORBID_REMOVE_PACKAGES | APT::Upgrade::FORBID_INSTALL_NEW_PACKAGES) == false)
 			failure = "ERR_UNSOLVABLE_UPGRADE";
 	} else if (distUpgrade == true) {
-		if (pkgDistUpgrade(CacheFile) == false)
+		if (APT::Upgrade::Upgrade(CacheFile, APT::Upgrade::ALLOW_EVERYTHING) == false)
 			failure = "ERR_UNSOLVABLE_DIST_UPGRADE";
 	} else if (Fix.Resolve() == false)
 		failure = "ERR_UNSOLVABLE";
-- 
cgit v1.2.3


From fdba4d53d6b9b594531c34792798f4044a25157e Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Wed, 3 Sep 2014 18:16:16 +0200
Subject: rework cachesets API to allow future extension
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The introduction of Fnmatch showed that each new selector would require
multiple new virtual methods in the CacheSetHelper to work correctly,
which isn't that great. We now flip to a single virtual method which
handles all cases separated by an enum – as new enum values can be added
without an ABI break.

Great care was taken to make old code work with the new way of organisation,
which means in return that you might be bombarded with deprecation
warnings now if you don't adapt, but code should still compile and work
as before as can be seen in apt itself with this commit.

Git-Dch: Ignore
---
 cmdline/apt-cache.cc | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc
index 4030ce4e6..bd10a41ef 100644
--- a/cmdline/apt-cache.cc
+++ b/cmdline/apt-cache.cc
@@ -838,9 +838,9 @@ static bool XVcg(CommandLine &CmdL)
 
    // Load the list of packages from the command line into the show list
    APT::CacheSetHelper helper(true, GlobalError::NOTICE);
-   std::list<APT::PackageSet::Modifier> mods;
-   mods.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
-   mods.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
+   std::list<APT::CacheSetHelper::PkgModifier> mods;
+   mods.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
+   mods.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
    std::map<unsigned short, APT::PackageSet> pkgsets =
 		APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
 
@@ -1050,9 +1050,9 @@ static bool Dotty(CommandLine &CmdL)
 
    // Load the list of packages from the command line into the show list
    APT::CacheSetHelper helper(true, GlobalError::NOTICE);
-   std::list<APT::PackageSet::Modifier> mods;
-   mods.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
-   mods.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
+   std::list<APT::CacheSetHelper::PkgModifier> mods;
+   mods.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
+   mods.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
    std::map<unsigned short, APT::PackageSet> pkgsets =
 		APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
 
-- 
cgit v1.2.3


From e6f0c9bca4b052d20a2e48ce9715b89e187b671a Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Wed, 3 Sep 2014 19:02:05 +0200
Subject: adapt to the new CacheSetHelper API

Git-Dch: Ignore
---
 cmdline/apt-cache.cc | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc
index bd10a41ef..5a5dde088 100644
--- a/cmdline/apt-cache.cc
+++ b/cmdline/apt-cache.cc
@@ -191,7 +191,7 @@ static bool UnMet(CommandLine &CmdL)
    {
       CacheSetHelperVirtuals helper(true, GlobalError::NOTICE);
       APT::VersionList verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1,
-				APT::VersionList::CANDIDATE, helper);
+				APT::CacheSetHelper::CANDIDATE, helper);
       for (APT::VersionList::iterator V = verset.begin(); V != verset.end(); ++V)
 	 if (ShowUnMet(V, Important) == false)
 	    return false;
@@ -656,7 +656,7 @@ static bool ShowDepends(CommandLine &CmdL, bool const RevDepends)
       return false;
 
    CacheSetHelperVirtuals helper(false);
-   APT::VersionList verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, APT::VersionList::CANDIDATE, helper);
+   APT::VersionList verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, APT::CacheSetHelper::CANDIDATE, helper);
    if (verset.empty() == true && helper.virtualPkgs.empty() == true)
       return _error->Error(_("No packages found"));
    std::vector<bool> Shown(Cache->Head().PackageCount);
@@ -724,7 +724,7 @@ static bool ShowDepends(CommandLine &CmdL, bool const RevDepends)
 		if (Recurse == true && Shown[Trg->ID] == false)
 		{
 		  Shown[Trg->ID] = true;
-		  verset.insert(APT::VersionSet::FromPackage(CacheFile, Trg, APT::VersionSet::CANDIDATE, helper));
+		  verset.insert(APT::VersionSet::FromPackage(CacheFile, Trg, APT::CacheSetHelper::CANDIDATE, helper));
 		}
 
 	      }
@@ -743,7 +743,7 @@ static bool ShowDepends(CommandLine &CmdL, bool const RevDepends)
 		if (Recurse == true && Shown[V.ParentPkg()->ID] == false)
 		{
 		  Shown[V.ParentPkg()->ID] = true;
-		  verset.insert(APT::VersionSet::FromPackage(CacheFile, V.ParentPkg(), APT::VersionSet::CANDIDATE, helper));
+		  verset.insert(APT::VersionSet::FromPackage(CacheFile, V.ParentPkg(), APT::CacheSetHelper::CANDIDATE, helper));
 		}
 	    }
 
@@ -1506,8 +1506,8 @@ static bool ShowPackage(CommandLine &CmdL)
 {
    pkgCacheFile CacheFile;
    CacheSetHelperVirtuals helper(true, GlobalError::NOTICE);
-   APT::VersionList::Version const select = _config->FindB("APT::Cache::AllVersions", true) ?
-			APT::VersionList::ALL : APT::VersionList::CANDIDATE;
+   APT::CacheSetHelper::VerSelector const select = _config->FindB("APT::Cache::AllVersions", true) ?
+			APT::CacheSetHelper::ALL : APT::CacheSetHelper::CANDIDATE;
    APT::VersionList const verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, select, helper);
    for (APT::VersionList::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver)
       if (DisplayRecord(CacheFile, Ver) == false)
-- 
cgit v1.2.3


From 3e032cda2d3558c076a559697e664546da56c243 Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Fri, 24 Jan 2014 15:02:39 +0100
Subject: remove leftover debug output from multikey softlink

Git-Dch: Ignore
---
 cmdline/apt-key.in | 1 -
 1 file changed, 1 deletion(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index 0774cf4b7..59b69b89c 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -198,7 +198,6 @@ remove_key_from_keyring() {
 	REALTARGET="$(readlink -f "$1")"
 	mv -f "$1" "${1}.dpkg-tmp"
 	cp -a "$REALTARGET" "$1"
-	ls "$(dirname $1)"
     fi
     # delete the key from the keyring
     $GPG --batch --delete-key --yes "$2"
-- 
cgit v1.2.3


From 3d0def059874a6e63566ce13579de296ccd26932 Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Fri, 24 Jan 2014 16:43:19 +0100
Subject: add a (hidden) --quiet option for apt-key

---
 cmdline/apt-key.in | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index 59b69b89c..d50ad40ac 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -39,6 +39,8 @@ ARCHIVE_KEYRING_URI='&keyring-uri;'
 eval $(apt-config shell ARCHIVE_KEYRING_URI APT::Key::ArchiveKeyringURI)
 TMP_KEYRING=${APT_DIR}/var/lib/apt/keyrings/maybe-import-keyring.gpg
 
+aptkey_echo() { echo "$@"; }
+
 requires_root() {
 	if [ "$(id -u)" -ne 0 ]; then
 		echo >&1 "ERROR: This command can only be used by root."
@@ -142,7 +144,7 @@ net_update() {
     fi
     new_mtime=$(stat -c %Y $keyring)
     if [ $new_mtime -ne $old_mtime ]; then
-	echo "Checking for new archive signing keys now"
+	aptkey_echo "Checking for new archive signing keys now"
 	add_keys_with_verify_against_master_keyring $keyring $MASTER_KEYRING
     fi
 }
@@ -227,7 +229,7 @@ remove_key() {
 	    done
 	fi
     fi
-    echo "OK"
+    aptkey_echo "OK"
 }
 
 
@@ -267,6 +269,10 @@ while [ -n "$1" ]; do
 	 requires_root() { true; }
 	 shift
 	 ;;
+      --quiet)
+	 aptkey_echo() { true; }
+	 shift
+	 ;;
       --*)
 	 echo >&2 "Unknown option: $1"
 	 usage
@@ -316,7 +322,7 @@ case "$command" in
         requires_root
         init_keyring "$TRUSTEDFILE"
         $GPG --quiet --batch --import "$1"
-        echo "OK"
+        aptkey_echo "OK"
         ;;
     del|rm|remove)
         init_keyring "$TRUSTEDFILE"
@@ -348,7 +354,7 @@ case "$command" in
         ;;
     adv*)
         init_keyring "$TRUSTEDFILE"
-        echo "Executing: $GPG $*"
+        aptkey_echo "Executing: $GPG $*"
         $GPG $*
         ;;
     help)
-- 
cgit v1.2.3


From 84b286f65c55e21b4734a17474f1cba464cbbd9c Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Fri, 24 Jan 2014 16:44:49 +0100
Subject: all errors should be printed to stderr

Git-Dch: Ignore
---
 cmdline/apt-key.in | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index d50ad40ac..e592925d6 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -43,7 +43,7 @@ aptkey_echo() { echo "$@"; }
 
 requires_root() {
 	if [ "$(id -u)" -ne 0 ]; then
-		echo >&1 "ERROR: This command can only be used by root."
+		echo >&2 "ERROR: This command can only be used by root."
 		exit 1
 	fi
 }
@@ -63,11 +63,11 @@ add_keys_with_verify_against_master_keyring() {
     MASTER=$2
 
     if [ ! -f "$ADD_KEYRING" ]; then
-	echo "ERROR: '$ADD_KEYRING' not found"
+	echo >&2 "ERROR: '$ADD_KEYRING' not found"
 	return
-    fi 
+    fi
     if [ ! -f "$MASTER" ]; then
-	echo "ERROR: '$MASTER' not found"
+	echo >&2 "ERROR: '$MASTER' not found"
 	return
     fi
 
@@ -175,7 +175,7 @@ update() {
 	    fi
 	done
     else
-	echo "Warning: removed keys keyring  $REMOVED_KEYS missing or not readable" >&2
+	echo >&2 "Warning: removed keys keyring  $REMOVED_KEYS missing or not readable"
     fi
 }
 
-- 
cgit v1.2.3


From 9fda3be1ae000e81e15dc8840271946e140765c9 Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Fri, 24 Jan 2014 17:14:52 +0100
Subject: only create new trusted.gpg if directory is writeable

---
 cmdline/apt-key.in | 37 ++++++++++++++-----------------------
 1 file changed, 14 insertions(+), 23 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index e592925d6..66e26ef0c 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -48,16 +48,6 @@ requires_root() {
 	fi
 }
 
-# gpg defaults to mode 0600 for new keyrings. Create one with 0644 instead.
-init_keyring() {
-    for path; do
-        if ! [ -e "$path" ]; then
-            touch -- "$path"
-            chmod 0644 -- "$path"
-        fi
-    done
-}
-
 add_keys_with_verify_against_master_keyring() {
     ADD_KEYRING=$1
     MASTER=$2
@@ -311,49 +301,50 @@ if [ -z "$command" ]; then
 fi
 shift
 
-if [ "$command" != "help" ] && ! which gpg >/dev/null 2>&1; then
-    echo >&2 "Warning: gnupg does not seem to be installed."
-    echo >&2 "Warning: apt-key requires gnupg for most operations."
-    echo >&2
+if [ "$command" != "help" ]; then
+    if ! which gpg >/dev/null 2>&1; then
+	echo >&2 "Warning: gnupg does not seem to be installed."
+	echo >&2 "Warning: apt-key requires gnupg for most operations."
+	echo >&2
+    fi
+
+    # gpg defaults to mode 0600 for new keyrings. Create one with 0644 instead.
+    if ! [ -e "$TRUSTEDFILE" ]; then
+	if [ -w "$(dirname "$TRUSTEDFILE")" ]; then
+	   touch -- "$TRUSTEDFILE"
+	   chmod 0644 -- "$TRUSTEDFILE"
+	fi
+    fi
 fi
 
 case "$command" in
     add)
         requires_root
-        init_keyring "$TRUSTEDFILE"
         $GPG --quiet --batch --import "$1"
         aptkey_echo "OK"
         ;;
     del|rm|remove)
-        init_keyring "$TRUSTEDFILE"
 	remove_key "$1"
         ;;
     update)
-        init_keyring "$TRUSTEDFILE"
 	update
 	;;
     net-update)
-        init_keyring "$TRUSTEDFILE"
 	net_update
 	;;
     list)
-        init_keyring "$TRUSTEDFILE"
         $GPG --batch --list-keys
         ;;
     finger*)
-        init_keyring "$TRUSTEDFILE"
         $GPG --batch --fingerprint
         ;;
     export)
-        init_keyring "$TRUSTEDFILE"
         $GPG --armor --export "$1"
         ;;
     exportall)
-        init_keyring "$TRUSTEDFILE"
         $GPG --armor --export
         ;;
     adv*)
-        init_keyring "$TRUSTEDFILE"
         aptkey_echo "Executing: $GPG $*"
         $GPG $*
         ;;
-- 
cgit v1.2.3


From 4f51a496d56807c73586220dd736173d7783c8b3 Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Fri, 24 Jan 2014 17:24:56 +0100
Subject: support (multiple) arguments properly in apt-key

---
 cmdline/apt-key.in | 54 +++++++++++++++++++++++++++---------------------------
 1 file changed, 27 insertions(+), 27 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index 66e26ef0c..ab62d4c8f 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -202,24 +202,27 @@ remove_key_from_keyring() {
 remove_key() {
     requires_root
 
-    # if a --keyring was given, just remove from there
-    if [ -n "$FORCED_KEYRING" ]; then
-	remove_key_from_keyring "$FORCED_KEYRING" "$1"
-    else
-	# otherwise all known keyrings are up for inspection
-	local TRUSTEDFILE="/etc/apt/trusted.gpg"
-	eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring)
-	eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f)
-	remove_key_from_keyring "$TRUSTEDFILE" "$1"
-	TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
-	eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)
-	if [ -d "$TRUSTEDPARTS" ]; then
-	    for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do
-		remove_key_from_keyring "$trusted" "$1"
-	    done
+    while [ -n "$1" ]; do
+	# if a --keyring was given, just remove from there
+	if [ -n "$FORCED_KEYRING" ]; then
+	    remove_key_from_keyring "$FORCED_KEYRING" "$1"
+	else
+	    # otherwise all known keyrings are up for inspection
+	    local TRUSTEDFILE="/etc/apt/trusted.gpg"
+	    eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring)
+	    eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f)
+	    remove_key_from_keyring "$TRUSTEDFILE" "$1"
+	    TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
+	    eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)
+	    if [ -d "$TRUSTEDPARTS" ]; then
+		for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do
+		    remove_key_from_keyring "$trusted" "$1"
+		done
+	    fi
 	fi
-    fi
-    aptkey_echo "OK"
+	aptkey_echo "OK"
+	shift
+    done
 }
 
 
@@ -320,11 +323,11 @@ fi
 case "$command" in
     add)
         requires_root
-        $GPG --quiet --batch --import "$1"
+        $GPG --quiet --batch --import "$@"
         aptkey_echo "OK"
         ;;
     del|rm|remove)
-	remove_key "$1"
+	remove_key "$@"
         ;;
     update)
 	update
@@ -333,20 +336,17 @@ case "$command" in
 	net_update
 	;;
     list)
-        $GPG --batch --list-keys
+        $GPG --batch --list-keys "$@"
         ;;
     finger*)
-        $GPG --batch --fingerprint
-        ;;
-    export)
-        $GPG --armor --export "$1"
+        $GPG --batch --fingerprint "$@"
         ;;
-    exportall)
-        $GPG --armor --export
+    export|exportall)
+        $GPG --armor --export "$@"
         ;;
     adv*)
         aptkey_echo "Executing: $GPG $*"
-        $GPG $*
+        $GPG "$@"
         ;;
     help)
         usage
-- 
cgit v1.2.3


From 08cfcd73f517e909823c100143c4938b9997343e Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Fri, 24 Jan 2014 17:41:35 +0100
Subject: set a primary-keyring only if we have access to it

---
 cmdline/apt-key.in | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index ab62d4c8f..9da5fceb8 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -281,8 +281,8 @@ if [ -z "$TRUSTEDFILE" ]; then
    eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f)
    if [ -r "$TRUSTEDFILE" ]; then
       GPG="$GPG --keyring $TRUSTEDFILE"
+      GPG="$GPG --primary-keyring $TRUSTEDFILE"
    fi
-   GPG="$GPG --primary-keyring $TRUSTEDFILE"
    TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
    eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)
    if [ -d "$TRUSTEDPARTS" ]; then
@@ -316,6 +316,8 @@ if [ "$command" != "help" ]; then
 	if [ -w "$(dirname "$TRUSTEDFILE")" ]; then
 	   touch -- "$TRUSTEDFILE"
 	   chmod 0644 -- "$TRUSTEDFILE"
+	   GPG="$GPG --keyring $TRUSTEDFILE"
+	   GPG="$GPG --primary-keyring $TRUSTEDFILE"
 	fi
     fi
 fi
-- 
cgit v1.2.3


From 4b30c1dc053278a6b9bdb50f0d91b3f934e8613d Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Fri, 24 Jan 2014 18:24:43 +0100
Subject: refactor key removal code to reuse it in next step

Git-Dch: Ignore
---
 cmdline/apt-key.in | 103 ++++++++++++++++++++++++++++-------------------------
 1 file changed, 55 insertions(+), 48 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index 9da5fceb8..9adbd6443 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -170,62 +170,69 @@ update() {
 }
 
 remove_key_from_keyring() {
-    local GPG="$GPG_CMD --keyring $1"
-    # check if the key is in this keyring: the key id is in the 5 column at the end
-    if ! $GPG --with-colons --list-keys 2>&1 | grep -q "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+$2:"; then
-	return
-    fi
-    if [ ! -w "$1" ]; then
-	echo >&2 "Key ${2} is in keyring ${1}, but can't be removed as it is read only."
-	return
-    fi
-    # check if it is the only key in the keyring and if so remove the keyring altogether
-    if [ '1' = "$($GPG --with-colons --list-keys | grep "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+:" | wc -l)" ]; then
-	mv -f "$1" "${1}~" # behave like gpg
-	return
-    fi
-    # we can't just modify pointed to files as these might be in /usr or something
-    local REALTARGET
-    if [ -L "$1" ]; then
-	REALTARGET="$(readlink -f "$1")"
-	mv -f "$1" "${1}.dpkg-tmp"
-	cp -a "$REALTARGET" "$1"
-    fi
-    # delete the key from the keyring
-    $GPG --batch --delete-key --yes "$2"
-    if [ -n "$REALTARGET" ]; then
-	# the real backup is the old link, not the copy we made
-	mv -f "${1}.dpkg-tmp" "${1}~"
-    fi
+    local KEYRINGFILE="$1"
+    shift
+    local GPG="$GPG_CMD --keyring $KEYRINGFILE"
+    while [ -n "$1" ]; do
+       local KEY="$1"
+       shift
+	# check if the key is in this keyring: the key id is in the 5 column at the end
+	if ! $GPG --with-colons --list-keys 2>&1 | grep -q "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+${KEY}:"; then
+	    continue
+	fi
+	if [ ! -w "$KEYRINGFILE" ]; then
+	    echo >&2 "Key ${KEY} is in keyring ${KEYRINGFILE}, but can't be removed as it is read only."
+	    continue
+	fi
+	# check if it is the only key in the keyring and if so remove the keyring altogether
+	if [ '1' = "$($GPG --with-colons --list-keys | grep "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+:" | wc -l)" ]; then
+	    mv -f "$KEYRINGFILE" "${KEYRINGFILE}~" # behave like gpg
+	    return
+	fi
+	# we can't just modify pointed to files as these might be in /usr or something
+	local REALTARGET
+	if [ -L "$KEYRINGFILE" ]; then
+	    REALTARGET="$(readlink -f "$KEYRINGFILE")"
+	    mv -f "$KEYRINGFILE" "${KEYRINGFILE}.dpkg-tmp"
+	    cp -a "$REALTARGET" "$KEYRINGFILE"
+	fi
+	# delete the key from the keyring
+	$GPG --batch --delete-key --yes "$KEY"
+	if [ -n "$REALTARGET" ]; then
+	    # the real backup is the old link, not the copy we made
+	    mv -f "${KEYRINGFILE}.dpkg-tmp" "${KEYRINGFILE}~"
+	fi
+    done
 }
 
 remove_key() {
     requires_root
+    foreach_keyring_do 'remove_key_from_keyring' "$@"
+    aptkey_echo "OK"
+ }
 
-    while [ -n "$1" ]; do
-	# if a --keyring was given, just remove from there
-	if [ -n "$FORCED_KEYRING" ]; then
-	    remove_key_from_keyring "$FORCED_KEYRING" "$1"
-	else
-	    # otherwise all known keyrings are up for inspection
-	    local TRUSTEDFILE="/etc/apt/trusted.gpg"
-	    eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring)
-	    eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f)
-	    remove_key_from_keyring "$TRUSTEDFILE" "$1"
-	    TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
-	    eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)
-	    if [ -d "$TRUSTEDPARTS" ]; then
-		for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do
-		    remove_key_from_keyring "$trusted" "$1"
-		done
-	    fi
+foreach_keyring_do() {
+   local ACTION="$1"
+   shift
+   # if a --keyring was given, just remove from there
+   if [ -n "$FORCED_KEYRING" ]; then
+	$ACTION "$FORCED_KEYRING" "$@"
+   else
+	# otherwise all known keyrings are up for inspection
+	local TRUSTEDFILE="/etc/apt/trusted.gpg"
+	eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring)
+	eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f)
+	$ACTION "$TRUSTEDFILE" "$@"
+	local TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
+	eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)
+	if [ -d "$TRUSTEDPARTS" ]; then
+	    for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do
+		$ACTION "$trusted" "$@"
+	    done
 	fi
-	aptkey_echo "OK"
-	shift
-    done
+   fi
 }
 
-
 usage() {
     echo "Usage: apt-key [--keyring file] [command] [arguments]"
     echo
-- 
cgit v1.2.3


From 5beb682d2de2003e1c022cb298d6c2ec0cf91c0d Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Fri, 24 Jan 2014 22:40:52 +0100
Subject: merge fragment keyrings in apt-key to avoid hitting gpg limits

gnupg has a hardlimit of 40 (at the moment) keyrings per invocation,
which can be exceeded with (many) repositories. That is rather
misfortune as the longrun goal was to drop gnupg dependency at some
point in the future, but this can now be considered missed and dropped.

It also means that 'apt-key adv' commands might not have the behaviour
one would expect it to have as it mainly operates on a big temporary
keyring, so commands modifying keys will break. Doing this was never a
good idea anyway through, so lets just hope nothing break too badly.

Closes: 733028
---
 cmdline/apt-key.in | 134 ++++++++++++++++++++++++++++++-----------------------
 1 file changed, 77 insertions(+), 57 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index 9adbd6443..9d8e60ec0 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -23,7 +23,6 @@ GPG_CMD="$GPG_CMD --homedir $GPGHOMEDIR"
 $GPG_CMD --quiet --check-trustdb --keyring $SECRETKEYRING >/dev/null 2>&1
 # tell gpg that it shouldn't try to maintain a trustdb file
 GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always"
-
 GPG="$GPG_CMD"
 
 APT_DIR="/"
@@ -113,7 +112,6 @@ net_update() {
 	echo >&2 "ERROR: Your distribution is not supported in net-update as no uri for the archive-keyring is set"
 	exit 1
     fi
-    requires_root
     # in theory we would need to depend on wget for this, but this feature
     # isn't useable in debian anyway as we have no keyring uri nor a master key
     if ! which wget >/dev/null 2>&1; then
@@ -145,7 +143,6 @@ update() {
 	echo >&2 "Is the &keyring-package; package installed?"
 	exit 1
     fi
-    requires_root
 
     # add new keys from the package;
 
@@ -158,11 +155,8 @@ update() {
 
     if [ -r "$REMOVED_KEYS" ]; then
 	# remove no-longer supported/used keys
-	keys=`$GPG_CMD --keyring $REMOVED_KEYS --with-colons --list-keys | grep ^pub | cut -d: -f5`
-	for key in $keys; do
-	    if $GPG --list-keys --with-colons | grep ^pub | cut -d: -f5 | grep -q $key; then
-		$GPG --quiet --batch --delete-key --yes ${key}
-	    fi
+	$GPG_CMD --keyring $REMOVED_KEYS --with-colons --list-keys | grep ^pub | cut -d: -f5 | while read key; do
+	    foreach_keyring_do 'remove_key_from_keyring' "$key"
 	done
     else
 	echo >&2 "Warning: removed keys keyring  $REMOVED_KEYS missing or not readable"
@@ -172,12 +166,17 @@ update() {
 remove_key_from_keyring() {
     local KEYRINGFILE="$1"
     shift
+    # non-existent keyrings have by definition no keys
+    if [ ! -e "$KEYRINGFILE" ]; then
+       return
+    fi
+
     local GPG="$GPG_CMD --keyring $KEYRINGFILE"
     while [ -n "$1" ]; do
        local KEY="$1"
        shift
 	# check if the key is in this keyring: the key id is in the 5 column at the end
-	if ! $GPG --with-colons --list-keys 2>&1 | grep -q "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+${KEY}:"; then
+	if ! $GPG --with-colons --list-keys 2>&1 | grep -q "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]*${KEY}:"; then
 	    continue
 	fi
 	if [ ! -w "$KEYRINGFILE" ]; then
@@ -205,12 +204,6 @@ remove_key_from_keyring() {
     done
 }
 
-remove_key() {
-    requires_root
-    foreach_keyring_do 'remove_key_from_keyring' "$@"
-    aptkey_echo "OK"
- }
-
 foreach_keyring_do() {
    local ACTION="$1"
    shift
@@ -219,20 +212,62 @@ foreach_keyring_do() {
 	$ACTION "$FORCED_KEYRING" "$@"
    else
 	# otherwise all known keyrings are up for inspection
-	local TRUSTEDFILE="/etc/apt/trusted.gpg"
-	eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring)
-	eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f)
-	$ACTION "$TRUSTEDFILE" "$@"
+	if [ -s "$TRUSTEDFILE" ]; then
+	    $ACTION "$TRUSTEDFILE" "$@"
+	fi
 	local TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
 	eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)
 	if [ -d "$TRUSTEDPARTS" ]; then
+	    # strip / suffix as gpg will double-slash in that case (#665411)
+	    local STRIPPED_TRUSTEDPARTS="${TRUSTEDPARTS%/}"
+	    if [ "${STRIPPED_TRUSTEDPARTS}/" = "$TRUSTEDPARTS" ]; then
+		TRUSTEDPARTS="$STRIPPED_TRUSTEDPARTS"
+	    fi
 	    for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do
-		$ACTION "$trusted" "$@"
+		if [ -s "$trusted" ]; then
+		    $ACTION "$trusted" "$@"
+		fi
 	    done
 	fi
    fi
 }
 
+list_keys_from_keyring() {
+    local KEYRINGFILE="$1"
+    shift
+    # don't show the error message if this keyring doesn't include the key
+    $GPG_CMD --keyring "$KEYRINGFILE" --batch --list-keys "$@" 2>/dev/null || true
+}
+
+fingerprint_keys_from_keyring() {
+    local KEYRINGFILE="$1"
+    shift
+    # don't show the error message if this keyring doesn't include the fingerprint
+    $GPG_CMD --keyring "$KEYRINGFILE" --batch --fingerprint "$@" 2>/dev/null || true
+}
+
+import_keys_from_keyring() {
+    local IMPORT="$1"
+    local KEYRINGFILE="$2"
+    $GPG_CMD --keyring "$KEYRINGFILE" --batch --import "$IMPORT" >/dev/null 2>&1
+}
+
+setup_merged_keyring() {
+    local TRUSTEDFILE_BAK="$TRUSTEDFILE"
+    TRUSTEDFILE='/dev/null'
+    foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/trusted.gpg"
+    TRUSTEDFILE="$TRUSTEDFILE_BAK"
+    # mark it as non-writeable so users get errors if gnupg tries to modify it
+    if [ -s "${GPGHOMEDIR}/trusted.gpg" ]; then
+	chmod -w "${GPGHOMEDIR}/trusted.gpg"
+	GPG="$GPG --keyring ${GPGHOMEDIR}/trusted.gpg"
+    fi
+    if [ -r "$TRUSTEDFILE" ]; then
+	GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE"
+    fi
+}
+
+
 usage() {
     echo "Usage: apt-key [--keyring file] [command] [arguments]"
     echo
@@ -257,12 +292,6 @@ while [ -n "$1" ]; do
 	 shift
 	 TRUSTEDFILE="$1"
 	 FORCED_KEYRING="$1"
-	 if [ -r "$TRUSTEDFILE" ] || [ "$2" = 'add' ] || [ "$2" = 'adv' ]; then
-	    GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE"
-	 else
-	    echo >&2 "Error: The specified keyring »$TRUSTEDFILE« is missing or not readable"
-	    exit 1
-	 fi
 	 shift
 	 ;;
       --fakeroot)
@@ -286,22 +315,6 @@ if [ -z "$TRUSTEDFILE" ]; then
    TRUSTEDFILE="/etc/apt/trusted.gpg"
    eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring)
    eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f)
-   if [ -r "$TRUSTEDFILE" ]; then
-      GPG="$GPG --keyring $TRUSTEDFILE"
-      GPG="$GPG --primary-keyring $TRUSTEDFILE"
-   fi
-   TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
-   eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)
-   if [ -d "$TRUSTEDPARTS" ]; then
-      # strip / suffix as gpg will double-slash in that case (#665411)
-      STRIPPED_TRUSTEDPARTS="${TRUSTEDPARTS%/}"
-      if [ "${STRIPPED_TRUSTEDPARTS}/" = "$TRUSTEDPARTS" ]; then
-	 TRUSTEDPARTS="$STRIPPED_TRUSTEDPARTS"
-      fi
-      for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do
-	 GPG="$GPG --keyring $trusted"
-      done
-   fi
 fi
 
 command="$1"
@@ -323,40 +336,47 @@ if [ "$command" != "help" ]; then
 	if [ -w "$(dirname "$TRUSTEDFILE")" ]; then
 	   touch -- "$TRUSTEDFILE"
 	   chmod 0644 -- "$TRUSTEDFILE"
-	   GPG="$GPG --keyring $TRUSTEDFILE"
-	   GPG="$GPG --primary-keyring $TRUSTEDFILE"
 	fi
     fi
 fi
 
 case "$command" in
     add)
-        requires_root
-        $GPG --quiet --batch --import "$@"
-        aptkey_echo "OK"
+	requires_root
+	setup_merged_keyring
+	$GPG --quiet --batch --import "$@"
+	aptkey_echo "OK"
         ;;
     del|rm|remove)
-	remove_key "$@"
+	requires_root
+	foreach_keyring_do 'remove_key_from_keyring' "$@"
+	aptkey_echo "OK"
         ;;
     update)
+	requires_root
+	setup_merged_keyring
 	update
 	;;
     net-update)
+	requires_root
+	setup_merged_keyring
 	net_update
 	;;
     list)
-        $GPG --batch --list-keys "$@"
-        ;;
+	foreach_keyring_do 'list_keys_from_keyring' "$@"
+	;;
     finger*)
-        $GPG --batch --fingerprint "$@"
-        ;;
+	foreach_keyring_do 'fingerprint_keys_from_keyring' "$@"
+	;;
     export|exportall)
-        $GPG --armor --export "$@"
-        ;;
+	foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/trusted.gpg"
+	$GPG_CMD --keyring "${GPGHOMEDIR}/trusted.gpg" --armor --export "$@"
+	;;
     adv*)
-        aptkey_echo "Executing: $GPG $*"
-        $GPG "$@"
-        ;;
+	setup_merged_keyring
+	aptkey_echo "Executing: $GPG $*"
+	$GPG "$@"
+	;;
     help)
         usage
         ;;
-- 
cgit v1.2.3


From 059911800900a42c4246f1e209b51656055215b2 Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Sun, 26 Jan 2014 17:37:00 +0100
Subject: delay gnupg setup in apt-key until it is needed

'apt-key help' and incorrect usage do not need a functioning gnupg
setup, as well as we shouldn't try to setup gnupg before we actually
test if it is available (and print a message if it is not).
---
 cmdline/apt-key.in | 44 ++++++++++++++++++++++----------------------
 1 file changed, 22 insertions(+), 22 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index 9d8e60ec0..b8fdfe121 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -3,28 +3,6 @@
 set -e
 unset GREP_OPTIONS
 
-GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring"
-
-# gpg needs (in different versions more or less) files to function correctly,
-# so we give it its own homedir and generate some valid content for it
-GPGHOMEDIR="$(mktemp -d)"
-CURRENTTRAP="${CURRENTTRAP} rm -rf '${GPGHOMEDIR}';"
-trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
-chmod 700 "$GPGHOMEDIR"
-# We don't use a secret keyring, of course, but gpg panics and
-# implodes if there isn't one available - and writeable for imports
-SECRETKEYRING="${GPGHOMEDIR}/secring.gpg"
-touch $SECRETKEYRING
-GPG_CMD="$GPG_CMD --homedir $GPGHOMEDIR"
-# create the trustdb with an (empty) dummy keyring
-# older gpgs required it, newer gpgs even warn that it isn't needed,
-# but require it nonetheless for some commands, so we just play safe
-# here for the foreseeable future and create a dummy one
-$GPG_CMD --quiet --check-trustdb --keyring $SECRETKEYRING >/dev/null 2>&1
-# tell gpg that it shouldn't try to maintain a trustdb file
-GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always"
-GPG="$GPG_CMD"
-
 APT_DIR="/"
 eval $(apt-config shell APT_DIR Dir)
 
@@ -331,6 +309,28 @@ if [ "$command" != "help" ]; then
 	echo >&2
     fi
 
+    GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring"
+
+    # gpg needs (in different versions more or less) files to function correctly,
+    # so we give it its own homedir and generate some valid content for it
+    GPGHOMEDIR="$(mktemp -d)"
+    CURRENTTRAP="${CURRENTTRAP} rm -rf '${GPGHOMEDIR}';"
+    trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
+    chmod 700 "$GPGHOMEDIR"
+    # We don't use a secret keyring, of course, but gpg panics and
+    # implodes if there isn't one available - and writeable for imports
+    SECRETKEYRING="${GPGHOMEDIR}/secring.gpg"
+    touch $SECRETKEYRING
+    GPG_CMD="$GPG_CMD --homedir $GPGHOMEDIR"
+    # create the trustdb with an (empty) dummy keyring
+    # older gpgs required it, newer gpgs even warn that it isn't needed,
+    # but require it nonetheless for some commands, so we just play safe
+    # here for the foreseeable future and create a dummy one
+    $GPG_CMD --quiet --check-trustdb --keyring $SECRETKEYRING >/dev/null 2>&1
+    # tell gpg that it shouldn't try to maintain a trustdb file
+    GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always"
+    GPG="$GPG_CMD"
+
     # gpg defaults to mode 0600 for new keyrings. Create one with 0644 instead.
     if ! [ -e "$TRUSTEDFILE" ]; then
 	if [ -w "$(dirname "$TRUSTEDFILE")" ]; then
-- 
cgit v1.2.3


From 93d0d08cdd6854f9bfb779c13b5b78cd6ed263aa Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Sun, 26 Jan 2014 18:28:50 +0100
Subject: support gnupg2 as drop-in replacement for gnupg

If both are available APT will still prefer gpg over gpg2 as it is a bit
more lightweight, but it shouldn't be a problem to use one or the other
(at least at the moment, who knows what will happen in the future).
---
 cmdline/apt-key.in | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index b8fdfe121..12aee9750 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -303,13 +303,22 @@ fi
 shift
 
 if [ "$command" != "help" ]; then
-    if ! which gpg >/dev/null 2>&1; then
-	echo >&2 "Warning: gnupg does not seem to be installed."
-	echo >&2 "Warning: apt-key requires gnupg for most operations."
+    eval $(apt-config shell GPG_EXE Apt::Key::gpgcommand)
+
+    if [ -n "$GPG_EXE" ] && which "$GPG_EXE" >/dev/null 2>&1; then
+	true
+    elif which gpg >/dev/null 2>&1; then
+	GPG_EXE="gpg"
+    elif which gpg2 >/dev/null 2>&1; then
+	GPG_EXE="gpg2"
+    else
+	echo >&2 "Error: gnupg or gnupg2 do not seem to be installed,"
+	echo >&2 "Error: but apt-key requires gnupg or gnupg2 for operation."
 	echo >&2
+	exit 255
     fi
 
-    GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring"
+    GPG_CMD="$GPG_EXE --ignore-time-conflict --no-options --no-default-keyring"
 
     # gpg needs (in different versions more or less) files to function correctly,
     # so we give it its own homedir and generate some valid content for it
-- 
cgit v1.2.3


From 0740a31033739ba30e7cb6754111f968167cbbf5 Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Sun, 26 Jan 2014 19:14:13 +0100
Subject: respect --keyring also in merged keyring commands

Git-Dch: Ignore
---
 cmdline/apt-key.in | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index 12aee9750..c54b608e1 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -231,14 +231,16 @@ import_keys_from_keyring() {
 }
 
 setup_merged_keyring() {
-    local TRUSTEDFILE_BAK="$TRUSTEDFILE"
-    TRUSTEDFILE='/dev/null'
-    foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/trusted.gpg"
-    TRUSTEDFILE="$TRUSTEDFILE_BAK"
-    # mark it as non-writeable so users get errors if gnupg tries to modify it
-    if [ -s "${GPGHOMEDIR}/trusted.gpg" ]; then
-	chmod -w "${GPGHOMEDIR}/trusted.gpg"
-	GPG="$GPG --keyring ${GPGHOMEDIR}/trusted.gpg"
+    if [ -z "$FORCED_KEYRING" ]; then
+	local TRUSTEDFILE_BAK="$TRUSTEDFILE"
+	TRUSTEDFILE='/dev/null'
+	foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/pubring.gpg"
+	TRUSTEDFILE="$TRUSTEDFILE_BAK"
+	# mark it as non-writeable so users get errors if gnupg tries to modify it
+	if [ -s "${GPGHOMEDIR}/pubring.gpg" ]; then
+	    chmod -w "${GPGHOMEDIR}/pubring.gpg"
+	    GPG="$GPG --keyring ${GPGHOMEDIR}/pubring.gpg"
+	fi
     fi
     if [ -r "$TRUSTEDFILE" ]; then
 	GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE"
-- 
cgit v1.2.3


From 38005d8b24bb81f4862d2c2a228e4a49a2af4ccd Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Mon, 27 Jan 2014 16:59:46 +0100
Subject: add a test for apt-key export{,all}

Git-Dch: Ignore
---
 cmdline/apt-key.in | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index c54b608e1..a3f8dde3a 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -380,8 +380,8 @@ case "$command" in
 	foreach_keyring_do 'fingerprint_keys_from_keyring' "$@"
 	;;
     export|exportall)
-	foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/trusted.gpg"
-	$GPG_CMD --keyring "${GPGHOMEDIR}/trusted.gpg" --armor --export "$@"
+	foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/pubring.gpg"
+	$GPG_CMD --keyring "${GPGHOMEDIR}/pubring.gpg" --armor --export "$@"
 	;;
     adv*)
 	setup_merged_keyring
-- 
cgit v1.2.3


From ba72845c07b2682f251dc7661869d20095260f8f Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Mon, 27 Jan 2014 17:04:53 +0100
Subject: allow to specify fingerprints in 'apt-key del'

---
 cmdline/apt-key.in | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index a3f8dde3a..74ca4d135 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -25,6 +25,19 @@ requires_root() {
 	fi
 }
 
+get_fingerprints_of_keyring() {
+    $GPG_CMD --keyring "$1" --with-colons --fingerprint | while read publine; do
+	# search for a public key
+	if [ "${publine%%:*}" != 'pub' ]; then continue; fi
+	# search for the associated fingerprint (should be the very next line)
+	while read fprline; do
+	   if [ "${fprline%%:*}" = 'sub' ]; then break; # should never happen
+	   elif [ "${fprline%%:*}" != 'fpr' ]; then continue; fi
+	   echo "$fprline" | cut -d':' -f 10
+	done
+    done
+}
+
 add_keys_with_verify_against_master_keyring() {
     ADD_KEYRING=$1
     MASTER=$2
@@ -42,7 +55,7 @@ add_keys_with_verify_against_master_keyring() {
     # is honored. so:
     #   all keys that are exported must have a valid signature
     #   from a key in the $distro-master-keyring
-    add_keys=`$GPG_CMD --keyring $ADD_KEYRING --with-colons --list-keys | grep ^pub | cut -d: -f5`
+    add_keys="$(get_fingerprints_of_keyring "$ADD_KEYRING")"
     all_add_keys=`$GPG_CMD --keyring $ADD_KEYRING --with-colons --list-keys | grep ^[ps]ub | cut -d: -f5`
     master_keys=`$GPG_CMD --keyring $MASTER --with-colons --list-keys | grep ^pub | cut -d: -f5`
 
@@ -133,7 +146,7 @@ update() {
 
     if [ -r "$REMOVED_KEYS" ]; then
 	# remove no-longer supported/used keys
-	$GPG_CMD --keyring $REMOVED_KEYS --with-colons --list-keys | grep ^pub | cut -d: -f5 | while read key; do
+	get_fingerprints_of_keyring "$REMOVED_KEYS" | while read key; do
 	    foreach_keyring_do 'remove_key_from_keyring' "$key"
 	done
     else
@@ -154,7 +167,7 @@ remove_key_from_keyring() {
        local KEY="$1"
        shift
 	# check if the key is in this keyring: the key id is in the 5 column at the end
-	if ! $GPG --with-colons --list-keys 2>&1 | grep -q "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]*${KEY}:"; then
+	if ! get_fingerprints_of_keyring "$KEYRINGFILE" | grep -q "^[0-9A-F]*${KEY}$"; then
 	    continue
 	fi
 	if [ ! -w "$KEYRINGFILE" ]; then
@@ -162,7 +175,7 @@ remove_key_from_keyring() {
 	    continue
 	fi
 	# check if it is the only key in the keyring and if so remove the keyring altogether
-	if [ '1' = "$($GPG --with-colons --list-keys | grep "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+:" | wc -l)" ]; then
+	if [ '1' = "$(get_fingerprints_of_keyring "$KEYRINGFILE" | wc -l)" ]; then
 	    mv -f "$KEYRINGFILE" "${KEYRINGFILE}~" # behave like gpg
 	    return
 	fi
-- 
cgit v1.2.3


From bd7fb5aa31f58917e8630f2981e78d190d465198 Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Mon, 27 Jan 2014 18:26:44 +0100
Subject: add --secret-keyring option for apt-key

For some advanced usecases it might be handy to specify the secret
keyring to be used (e.g. as it is used in the testcases), but specifying
it via a normal option for gnupg might not be available forever:
http://lists.gnupg.org/pipermail/gnupg-users/2013-August/047180.html

Git-Dch: Ignore
---
 cmdline/apt-key.in | 11 +++++++++++
 1 file changed, 11 insertions(+)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index 74ca4d135..36824b6ec 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -287,6 +287,11 @@ while [ -n "$1" ]; do
 	 FORCED_KEYRING="$1"
 	 shift
 	 ;;
+      --secret-keyring)
+	 shift
+	 FORCED_SECRET_KEYRING="$1"
+	 shift
+	 ;;
       --fakeroot)
 	 requires_root() { true; }
 	 shift
@@ -355,6 +360,12 @@ if [ "$command" != "help" ]; then
     GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always"
     GPG="$GPG_CMD"
 
+    # for advanced operations, we might really need a secret keyring after all
+    if [ -n "$FORCED_SECRET_KEYRING" ] && [ -r "$FORCED_SECRET_KEYRING" ]; then
+	rm -f "$SECRETKEYRING"
+	cp -a "$FORCED_SECRET_KEYRING" "$SECRETKEYRING"
+    fi
+
     # gpg defaults to mode 0600 for new keyrings. Create one with 0644 instead.
     if ! [ -e "$TRUSTEDFILE" ]; then
 	if [ -w "$(dirname "$TRUSTEDFILE")" ]; then
-- 
cgit v1.2.3


From 0dae96a2b5e8ecd80a1b6e44961f1692ad4aec15 Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Mon, 27 Jan 2014 22:07:16 +0100
Subject: use only one --keyring in gpg interactions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

We were down to at most two keyrings before, but gnupg upstream plans
dropping support for multiple keyrings in the longrun, so with a
single keyring we hope to be future proof – and 'apt-key adv' isn't a
problem anymore as every change to the keys is merged back, so we have
now the same behavior as before, but support an unlimited amount of
trusted.gpg.d keyrings.
---
 cmdline/apt-key.in | 105 +++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 77 insertions(+), 28 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index 36824b6ec..9259fac0d 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -14,7 +14,6 @@ REMOVED_KEYS='&keyring-removed-filename;'
 eval $(apt-config shell REMOVED_KEYS APT::Key::RemovedKeys)
 ARCHIVE_KEYRING_URI='&keyring-uri;'
 eval $(apt-config shell ARCHIVE_KEYRING_URI APT::Key::ArchiveKeyringURI)
-TMP_KEYRING=${APT_DIR}/var/lib/apt/keyrings/maybe-import-keyring.gpg
 
 aptkey_echo() { echo "$@"; }
 
@@ -68,24 +67,28 @@ add_keys_with_verify_against_master_keyring() {
             fi
         done
     done
-    
+
     for add_key in $add_keys; do
         # export the add keyring one-by-one
-        rm -f $TMP_KEYRING
-        $GPG_CMD --keyring $ADD_KEYRING --output $TMP_KEYRING --export $add_key 
-        # check if signed with the master key and only add in this case
-        ADDED=0
+	local TMP_KEYRING="${GPGHOMEDIR}/tmp-keyring.gpg"
+	$GPG_CMD --batch --yes --keyring "$ADD_KEYRING" --output "$TMP_KEYRING" --export "$add_key"
+	if ! $GPG_CMD --batch --yes --keyring "$TMP_KEYRING" --import "$MASTER" > "${GPGHOMEDIR}/gpgoutput.log" 2>&1; then
+	    cat "${GPGHOMEDIR}/gpgoutput.log"
+	    false
+	fi
+	# check if signed with the master key and only add in this case
+	ADDED=0
 	for master_key in $master_keys; do
-	    if $GPG_CMD --keyring $MASTER --keyring $TMP_KEYRING --check-sigs --with-colons $add_key | grep '^sig:!:' | cut -d: -f5 | grep -q $master_key; then
-		$GPG --import $TMP_KEYRING
+	    if $GPG_CMD --keyring $TMP_KEYRING --check-sigs --with-colons $add_key | grep '^sig:!:' | cut -d: -f5 | grep -q $master_key; then
+		$GPG_CMD --batch --yes --keyring "$ADD_KEYRING" --export "$add_key" | $GPG --batch --yes --import
 		ADDED=1
 	    fi
 	done
 	if [ $ADDED = 0 ]; then
 	    echo >&2 "Key '$add_key' not added. It is not signed with a master key"
 	fi
+	rm -f "${TMP_KEYRING}"
     done
-    rm -f $TMP_KEYRING
 }
 
 # update the current archive signing keyring from a network URI
@@ -240,26 +243,75 @@ fingerprint_keys_from_keyring() {
 import_keys_from_keyring() {
     local IMPORT="$1"
     local KEYRINGFILE="$2"
-    $GPG_CMD --keyring "$KEYRINGFILE" --batch --import "$IMPORT" >/dev/null 2>&1
+    if ! $GPG_CMD --keyring "$KEYRINGFILE" --batch --import "$IMPORT" > "${GPGHOMEDIR}/gpgoutput.log" 2>&1; then
+	cat "${GPGHOMEDIR}/gpgoutput.log"
+	false
+    fi
+}
+
+merge_keys_into_keyrings() {
+    local KEYRINGFILE="$1"
+    local IMPORT="$2"
+    if ! $GPG_CMD --keyring "$KEYRINGFILE" --batch --import --import-options 'merge-only' "$IMPORT" > "${GPGHOMEDIR}/gpgoutput.log" 2>&1; then
+	cat "${GPGHOMEDIR}/gpgoutput.log"
+	false
+    fi
+}
+
+merge_back_changes() {
+    if [ -n "$FORCED_KEYRING" ]; then
+	# if the keyring was forced merge is already done
+	return
+    fi
+    if [ -s "${GPGHOMEDIR}/pubring.gpg" ]; then
+	# merge all updated keys
+	foreach_keyring_do 'merge_keys_into_keyrings' "${GPGHOMEDIR}/pubring.gpg"
+    fi
+    # no look for keys which were added or removed
+    get_fingerprints_of_keyring "${GPGHOMEDIR}/pubring.orig.gpg" > "${GPGHOMEDIR}/pubring.orig.keylst"
+    get_fingerprints_of_keyring "${GPGHOMEDIR}/pubring.gpg" > "${GPGHOMEDIR}/pubring.keylst"
+    #echo >&2 "MERGE BACK"
+    sort "${GPGHOMEDIR}/pubring.keylst" "${GPGHOMEDIR}/pubring.orig.keylst" | uniq --unique | while read key; do
+	if grep -q "^${key}$" "${GPGHOMEDIR}/pubring.orig.keylst"; then
+	    # key isn't part of new keyring, so remove
+	    foreach_keyring_do 'remove_key_from_keyring' "$key"
+	elif grep -q "^${key}$" "${GPGHOMEDIR}/pubring.keylst"; then
+	    # key is part of new keyring, so we need to import it
+	    create_new_keyring "$TRUSTEDFILE"
+	    if ! $GPG --batch --yes --export "$key" | $GPG_CMD --keyring "$TRUSTEDFILE" --batch --yes --import > "${GPGHOMEDIR}/gpgoutput.log" 2>&1; then
+	       cat "${GPGHOMEDIR}/gpgoutput.log"
+	       false
+	    fi
+	else
+	    echo >&2 "Errror: Key ${key} (dis)appeared out of nowhere"
+	fi
+    done
 }
 
 setup_merged_keyring() {
     if [ -z "$FORCED_KEYRING" ]; then
-	local TRUSTEDFILE_BAK="$TRUSTEDFILE"
-	TRUSTEDFILE='/dev/null'
 	foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/pubring.gpg"
-	TRUSTEDFILE="$TRUSTEDFILE_BAK"
-	# mark it as non-writeable so users get errors if gnupg tries to modify it
-	if [ -s "${GPGHOMEDIR}/pubring.gpg" ]; then
-	    chmod -w "${GPGHOMEDIR}/pubring.gpg"
-	    GPG="$GPG --keyring ${GPGHOMEDIR}/pubring.gpg"
+	if [ -r "${GPGHOMEDIR}/pubring.gpg" ]; then
+	    cp -a "${GPGHOMEDIR}/pubring.gpg" "${GPGHOMEDIR}/pubring.orig.gpg"
+	else
+	   touch "${GPGHOMEDIR}/pubring.gpg" "${GPGHOMEDIR}/pubring.orig.gpg"
 	fi
-    fi
-    if [ -r "$TRUSTEDFILE" ]; then
-	GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE"
+	GPG="$GPG --keyring ${GPGHOMEDIR}/pubring.gpg"
+    else
+	GPG="$GPG --keyring $TRUSTEDFILE"
+	create_new_keyring "$TRUSTEDFILE"
     fi
 }
 
+create_new_keyring() {
+    # gpg defaults to mode 0600 for new keyrings. Create one with 0644 instead.
+    if ! [ -e "$TRUSTEDFILE" ]; then
+	if [ -w "$(dirname "$TRUSTEDFILE")" ]; then
+	    touch -- "$TRUSTEDFILE"
+	    chmod 0644 -- "$TRUSTEDFILE"
+	fi
+    fi
+}
 
 usage() {
     echo "Usage: apt-key [--keyring file] [command] [arguments]"
@@ -365,14 +417,6 @@ if [ "$command" != "help" ]; then
 	rm -f "$SECRETKEYRING"
 	cp -a "$FORCED_SECRET_KEYRING" "$SECRETKEYRING"
     fi
-
-    # gpg defaults to mode 0600 for new keyrings. Create one with 0644 instead.
-    if ! [ -e "$TRUSTEDFILE" ]; then
-	if [ -w "$(dirname "$TRUSTEDFILE")" ]; then
-	   touch -- "$TRUSTEDFILE"
-	   chmod 0644 -- "$TRUSTEDFILE"
-	fi
-    fi
 fi
 
 case "$command" in
@@ -380,22 +424,26 @@ case "$command" in
 	requires_root
 	setup_merged_keyring
 	$GPG --quiet --batch --import "$@"
+	merge_back_changes
 	aptkey_echo "OK"
         ;;
     del|rm|remove)
 	requires_root
 	foreach_keyring_do 'remove_key_from_keyring' "$@"
+	merge_back_changes
 	aptkey_echo "OK"
         ;;
     update)
 	requires_root
 	setup_merged_keyring
 	update
+	merge_back_changes
 	;;
     net-update)
 	requires_root
 	setup_merged_keyring
 	net_update
+	merge_back_changes
 	;;
     list)
 	foreach_keyring_do 'list_keys_from_keyring' "$@"
@@ -411,6 +459,7 @@ case "$command" in
 	setup_merged_keyring
 	aptkey_echo "Executing: $GPG $*"
 	$GPG "$@"
+	merge_back_changes
 	;;
     help)
         usage
-- 
cgit v1.2.3


From 33a2267214eed2a11281c9f93b8cf10b4c436d94 Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Thu, 6 Feb 2014 17:56:28 +0100
Subject: add --readonly option for apt-key adv

Some advanced commands can be executed without the keyring being
modified like --verify, so this adds an option to disable the mergeback
and uses it for our gpg calling code.

Git-Dch: Ignore
---
 cmdline/apt-key.in | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index 9259fac0d..21d692631 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -337,20 +337,19 @@ while [ -n "$1" ]; do
 	 shift
 	 TRUSTEDFILE="$1"
 	 FORCED_KEYRING="$1"
-	 shift
 	 ;;
       --secret-keyring)
 	 shift
 	 FORCED_SECRET_KEYRING="$1"
-	 shift
+	 ;;
+      --readonly)
+	 merge_back_changes() { true; }
 	 ;;
       --fakeroot)
 	 requires_root() { true; }
-	 shift
 	 ;;
       --quiet)
 	 aptkey_echo() { true; }
-	 shift
 	 ;;
       --*)
 	 echo >&2 "Unknown option: $1"
@@ -359,6 +358,7 @@ while [ -n "$1" ]; do
       *)
 	 break;;
    esac
+   shift
 done
 
 if [ -z "$TRUSTEDFILE" ]; then
@@ -430,7 +430,6 @@ case "$command" in
     del|rm|remove)
 	requires_root
 	foreach_keyring_do 'remove_key_from_keyring' "$@"
-	merge_back_changes
 	aptkey_echo "OK"
         ;;
     update)
-- 
cgit v1.2.3


From 0b94a7bc2ebb42453d9e22dc58dde76b9261de50 Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Thu, 6 Feb 2014 18:43:55 +0100
Subject: miscellaneous small cleanups in apt-key

Git-Dch: Ignore
---
 cmdline/apt-key.in | 24 +++++++-----------------
 1 file changed, 7 insertions(+), 17 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index 21d692631..a9a729cce 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -166,9 +166,7 @@ remove_key_from_keyring() {
     fi
 
     local GPG="$GPG_CMD --keyring $KEYRINGFILE"
-    while [ -n "$1" ]; do
-       local KEY="$1"
-       shift
+    for KEY in "$@"; do
 	# check if the key is in this keyring: the key id is in the 5 column at the end
 	if ! get_fingerprints_of_keyring "$KEYRINGFILE" | grep -q "^[0-9A-F]*${KEY}$"; then
 	    continue
@@ -226,18 +224,11 @@ foreach_keyring_do() {
    fi
 }
 
-list_keys_from_keyring() {
+run_cmd_on_keyring() {
     local KEYRINGFILE="$1"
     shift
-    # don't show the error message if this keyring doesn't include the key
-    $GPG_CMD --keyring "$KEYRINGFILE" --batch --list-keys "$@" 2>/dev/null || true
-}
-
-fingerprint_keys_from_keyring() {
-    local KEYRINGFILE="$1"
-    shift
-    # don't show the error message if this keyring doesn't include the fingerprint
-    $GPG_CMD --keyring "$KEYRINGFILE" --batch --fingerprint "$@" 2>/dev/null || true
+    # fingerprint and co will fail if key isn't in this keyring
+    $GPG_CMD --keyring "$KEYRINGFILE" --batch "$@" 2>/dev/null || true
 }
 
 import_keys_from_keyring() {
@@ -267,10 +258,9 @@ merge_back_changes() {
 	# merge all updated keys
 	foreach_keyring_do 'merge_keys_into_keyrings' "${GPGHOMEDIR}/pubring.gpg"
     fi
-    # no look for keys which were added or removed
+    # look for keys which were added or removed
     get_fingerprints_of_keyring "${GPGHOMEDIR}/pubring.orig.gpg" > "${GPGHOMEDIR}/pubring.orig.keylst"
     get_fingerprints_of_keyring "${GPGHOMEDIR}/pubring.gpg" > "${GPGHOMEDIR}/pubring.keylst"
-    #echo >&2 "MERGE BACK"
     sort "${GPGHOMEDIR}/pubring.keylst" "${GPGHOMEDIR}/pubring.orig.keylst" | uniq --unique | while read key; do
 	if grep -q "^${key}$" "${GPGHOMEDIR}/pubring.orig.keylst"; then
 	    # key isn't part of new keyring, so remove
@@ -445,10 +435,10 @@ case "$command" in
 	merge_back_changes
 	;;
     list)
-	foreach_keyring_do 'list_keys_from_keyring' "$@"
+	foreach_keyring_do 'run_cmd_on_keyring' --list-keys "$@"
 	;;
     finger*)
-	foreach_keyring_do 'fingerprint_keys_from_keyring' "$@"
+	foreach_keyring_do 'run_cmd_on_keyring' --fingerprint "$@"
 	;;
     export|exportall)
 	foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/pubring.gpg"
-- 
cgit v1.2.3


From c46a36adaf51fc28464ea1a0e826c754ee60672b Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Mon, 14 Apr 2014 18:24:17 +0200
Subject: add and use 'apt-key verify' which prefers gpgv over gpg

gnupg/gnupg2 can do verify just fine of course, so we don't need to use
gpgv here, but it is what we always used in the past, so there might be
scripts expecting a certain output and more importantly the output of
apt-cdrom contains messages from gpg and even with all the settings we
activate to prevent it, it still shows (in some versions) a quiet scary:
"gpg: WARNING: Using untrusted key!" message. Keeping the use of gpgv is
the simplest way to prevent it.

We are increasing also the "Breaks: apt" version from libapt as it
requires a newer apt-key than might be installed in partial upgrades.
---
 cmdline/apt-key.in | 8 ++++++++
 1 file changed, 8 insertions(+)

(limited to 'cmdline')

diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index a9a729cce..83a7a31b9 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -450,6 +450,14 @@ case "$command" in
 	$GPG "$@"
 	merge_back_changes
 	;;
+    verify)
+	setup_merged_keyring
+	if which gpgv >/dev/null 2>&1; then
+	    gpgv --homedir "${GPGHOMEDIR}" --keyring "${GPGHOMEDIR}/pubring.gpg" --ignore-time-conflict "$@"
+	else
+	    $GPG --verify "$@"
+	fi
+	;;
     help)
         usage
         ;;
-- 
cgit v1.2.3


From a221efc331693f8905da870141756c892911c433 Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Fri, 20 Jun 2014 19:34:40 +0200
Subject: store source name and version in binary cache

Accessing the package records to acquire this information is pretty
costly, so that information wasn't used so far in many places. The most
noticeable user by far is EDSP at the moment, but there are ideas to
change that which this commit tries to enable.
---
 cmdline/apt-cache.cc |  2 ++
 cmdline/apt-get.cc   | 64 ++++++++++++++++++----------------------------------
 2 files changed, 24 insertions(+), 42 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc
index 5a5dde088..0f4f7e1ce 100644
--- a/cmdline/apt-cache.cc
+++ b/cmdline/apt-cache.cc
@@ -389,6 +389,8 @@ static bool Stats(CommandLine &)
 	    stritems.insert(V->VerStr);
 	 if (V->Section != 0)
 	    stritems.insert(V->Section);
+	 stritems.insert(V->SourcePkgName);
+	 stritems.insert(V->SourceVerStr);
 	 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ++D)
 	 {
 	    if (D->Version != 0)
diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc
index aed1beb4d..a5cafc39d 100644
--- a/cmdline/apt-get.cc
+++ b/cmdline/apt-get.cc
@@ -195,7 +195,7 @@ static std::string GetReleaseForSourceRecord(pkgSourceList *SrcList,
 // FindSrc - Find a source record					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-static pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
+static pkgSrcRecords::Parser *FindSrc(const char *Name,
 			       pkgSrcRecords &SrcRecs,string &Src,
 			       CacheFile &CacheFile)
 {
@@ -303,16 +303,10 @@ static pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
 		  (VF.File().Archive() != 0 && VF.File().Archive() == RelTag) ||
 		  (VF.File().Codename() != 0 && VF.File().Codename() == RelTag)) 
 	       {
-		  pkgRecords::Parser &Parse = Recs.Lookup(VF);
-		  Src = Parse.SourcePkg();
-		  // no SourcePkg name, so it is the "binary" name
-		  if (Src.empty() == true)
-		     Src = TmpSrc;
+		  Src = Ver.SourcePkgName();
 		  // the Version we have is possibly fuzzy or includes binUploads,
-		  // so we use the Version of the SourcePkg (empty if same as package)
-		  VerTag = Parse.SourceVer();
-		  if (VerTag.empty() == true)
-		     VerTag = Ver.VerStr();
+		  // so we use the Version of the SourcePkg
+		  VerTag = Ver.SourceVerStr();
 		  break;
 	       }
 	    }
@@ -343,10 +337,10 @@ static pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
 	 pkgCache::VerIterator Ver = Cache->GetCandidateVer(Pkg);
 	 if (Ver.end() == false) 
 	 {
-	    pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
-	    Src = Parse.SourcePkg();
-	    if (VerTag.empty() == true)
-	       VerTag = Parse.SourceVer();
+	    if (strcmp(Ver.SourcePkgName(),Ver.ParentPkg().Name()) != 0)
+	       Src = Ver.SourcePkgName();
+	    if (VerTag.empty() == true && strcmp(Ver.SourceVerStr(),Ver.VerStr()) != 0)
+	       VerTag = Ver.SourceVerStr();
 	 }
       }
    }
@@ -731,7 +725,6 @@ static bool DoSource(CommandLine &CmdL)
    pkgSourceList *List = Cache.GetSourceList();
    
    // Create the text record parsers
-   pkgRecords Recs(Cache);
    pkgSrcRecords SrcRecs(*List);
    if (_error->PendingError() == true)
       return false;
@@ -760,7 +753,7 @@ static bool DoSource(CommandLine &CmdL)
    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
    {
       string Src;
-      pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,Cache);
+      pkgSrcRecords::Parser *Last = FindSrc(*I,SrcRecs,Src,Cache);
       
       if (Last == 0) {
 	 return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
@@ -1037,7 +1030,6 @@ static bool DoBuildDep(CommandLine &CmdL)
    pkgSourceList *List = Cache.GetSourceList();
    
    // Create the text record parsers
-   pkgRecords Recs(Cache);
    pkgSrcRecords SrcRecs(*List);
    if (_error->PendingError() == true)
       return false;
@@ -1090,7 +1082,7 @@ static bool DoBuildDep(CommandLine &CmdL)
             Last = Type->CreateSrcPkgParser(*I);
       } else {
          // normal case, search the cache for the source file
-         Last = FindSrc(*I,Recs,SrcRecs,Src,Cache);
+         Last = FindSrc(*I,SrcRecs,Src,Cache);
       }
 
       if (Last == 0)
@@ -1441,21 +1433,15 @@ static bool DoBuildDep(CommandLine &CmdL)
  * pool/ next to the deb itself)
  * Example return: "pool/main/a/apt/apt_0.8.8ubuntu3" 
  */
-static string GetChangelogPath(CacheFile &Cache, 
-                        pkgCache::PkgIterator Pkg,
+static string GetChangelogPath(CacheFile &Cache,
                         pkgCache::VerIterator Ver)
 {
-   string path;
-
    pkgRecords Recs(Cache);
    pkgRecords::Parser &rec=Recs.Lookup(Ver.FileList());
-   string srcpkg = rec.SourcePkg().empty() ? Pkg.Name() : rec.SourcePkg();
-   string ver = Ver.VerStr();
-   // if there is a source version it always wins
-   if (rec.SourceVer() != "")
-      ver = rec.SourceVer();
-   path = flNotFile(rec.FileName());
-   path += srcpkg + "_" + StripEpoch(ver);
+   string path = flNotFile(rec.FileName());
+   path.append(Ver.SourcePkgName());
+   path.append("_");
+   path.append(StripEpoch(Ver.SourceVerStr()));
    return path;
 }
 									/*}}}*/
@@ -1469,7 +1455,6 @@ static string GetChangelogPath(CacheFile &Cache,
  *  http://packages.medibuntu.org/pool/non-free/m/mplayer/mplayer_1.0~rc4~try1.dsfg1-1ubuntu1+medibuntu1.changelog
  */
 static bool GuessThirdPartyChangelogUri(CacheFile &Cache, 
-                                 pkgCache::PkgIterator Pkg,
                                  pkgCache::VerIterator Ver,
                                  string &out_uri)
 {
@@ -1484,7 +1469,7 @@ static bool GuessThirdPartyChangelogUri(CacheFile &Cache,
       return false;
 
    // get archive uri for the binary deb
-   string path_without_dot_changelog = GetChangelogPath(Cache, Pkg, Ver);
+   string path_without_dot_changelog = GetChangelogPath(Cache, Ver);
    out_uri = index->ArchiveURI(path_without_dot_changelog + ".changelog");
 
    // now strip away the filename and add srcpkg_srcver.changelog
@@ -1502,25 +1487,20 @@ static bool DownloadChangelog(CacheFile &CacheFile, pkgAcquire &Fetcher,
  * GuessThirdPartyChangelogUri for details how)
  */
 {
-   string path;
-   string descr;
-   string server;
-   string changelog_uri;
-
-   // data structures we need
-   pkgCache::PkgIterator Pkg = Ver.ParentPkg();
-
    // make the server root configurable
-   server = _config->Find("Apt::Changelogs::Server",
+   string const server = _config->Find("Apt::Changelogs::Server",
                           "http://packages.debian.org/changelogs");
-   path = GetChangelogPath(CacheFile, Pkg, Ver);
+   string const path = GetChangelogPath(CacheFile, Ver);
+   string changelog_uri;
    strprintf(changelog_uri, "%s/%s/changelog", server.c_str(), path.c_str());
    if (_config->FindB("APT::Get::Print-URIs", false) == true)
    {
       std::cout << '\'' << changelog_uri << '\'' << std::endl;
       return true;
    }
+   pkgCache::PkgIterator const Pkg = Ver.ParentPkg();
 
+   string descr;
    strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), changelog_uri.c_str());
    // queue it
    new pkgAcqFile(&Fetcher, changelog_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile);
@@ -1531,7 +1511,7 @@ static bool DownloadChangelog(CacheFile &CacheFile, pkgAcquire &Fetcher,
    if (!FileExists(targetfile))
    {
       string third_party_uri;
-      if (GuessThirdPartyChangelogUri(CacheFile, Pkg, Ver, third_party_uri))
+      if (GuessThirdPartyChangelogUri(CacheFile, Ver, third_party_uri))
       {
          strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), third_party_uri.c_str());
          new pkgAcqFile(&Fetcher, third_party_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile);
-- 
cgit v1.2.3


From 43acd01979039b248cb7f033b82e36d778d0ebec Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Sat, 27 Sep 2014 19:45:30 +0200
Subject: allow fetcher setup without directory creation

apt-get download and changelog as well as apt-helper reuse the acquire
system for their own proposes without requiring the directories the
fetcher wants to create, which is a problem if you run them as non-root
and the directories do not exist as it greets you with:
E: Archives directory /var/cache/apt/archives/partial is missing. -
Acquire (13: Permission denied)

Closes: 762898
---
 cmdline/apt-get.cc    | 9 +++++----
 cmdline/apt-helper.cc | 3 ++-
 2 files changed, 7 insertions(+), 5 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc
index a5cafc39d..6d03c7eec 100644
--- a/cmdline/apt-get.cc
+++ b/cmdline/apt-get.cc
@@ -626,14 +626,14 @@ static bool DoDownload(CommandLine &CmdL)
 
    APT::CacheSetHelper helper(c0out);
    APT::VersionSet verset = APT::VersionSet::FromCommandLine(Cache,
-		CmdL.FileList + 1, APT::VersionSet::CANDIDATE, helper);
+		CmdL.FileList + 1, APT::CacheSetHelper::CANDIDATE, helper);
 
    if (verset.empty() == true)
       return false;
 
    AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet", 0));
    pkgAcquire Fetcher;
-   if (Fetcher.Setup(&Stat) == false)
+   if (Fetcher.Setup(&Stat, "", false) == false)
       return false;
 
    pkgRecords Recs(Cache);
@@ -1536,7 +1536,7 @@ static bool DoChangelog(CommandLine &CmdL)
    
    APT::CacheSetHelper helper(c0out);
    APT::VersionList verset = APT::VersionList::FromCommandLine(Cache,
-		CmdL.FileList + 1, APT::VersionList::CANDIDATE, helper);
+		CmdL.FileList + 1, APT::CacheSetHelper::CANDIDATE, helper);
    if (verset.empty() == true)
       return false;
    pkgAcquire Fetcher;
@@ -1551,7 +1551,8 @@ static bool DoChangelog(CommandLine &CmdL)
    }
 
    AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0));
-   Fetcher.Setup(&Stat);
+   if (Fetcher.Setup(&Stat, "",false) == false)
+      return false;
 
    bool const downOnly = _config->FindB("APT::Get::Download-Only", false);
 
diff --git a/cmdline/apt-helper.cc b/cmdline/apt-helper.cc
index dd43ea1bc..b89df61d6 100644
--- a/cmdline/apt-helper.cc
+++ b/cmdline/apt-helper.cc
@@ -51,7 +51,8 @@ static bool DoDownloadFile(CommandLine &CmdL)
 
    pkgAcquire Fetcher;
    AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0));
-   Fetcher.Setup(&Stat);
+   if (Fetcher.Setup(&Stat, "", false) == false)
+      return false;
    std::string download_uri = CmdL.FileList[1];
    std::string targetfile = CmdL.FileList[2];
    std::string hash;
-- 
cgit v1.2.3


From 20e6965ad6388b964b59b89c31ff8b81cbcb8f8c Mon Sep 17 00:00:00 2001
From: David Kalnischkies <david@kalnischkies.de>
Date: Sat, 27 Sep 2014 20:09:44 +0200
Subject: cleanup partial directory of lists in apt-get clean

Not really the intended usecase for apt-get clean, but users expect it
to help them in recovery and it can't really hurt as this directory
should be empty if everything was fine and proper anyway.

Closes: #762889
---
 cmdline/apt-get.cc | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

(limited to 'cmdline')

diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc
index 6d03c7eec..c8c3ca56b 100644
--- a/cmdline/apt-get.cc
+++ b/cmdline/apt-get.cc
@@ -549,30 +549,44 @@ static bool DoDSelectUpgrade(CommandLine &)
 static bool DoClean(CommandLine &)
 {
    std::string const archivedir = _config->FindDir("Dir::Cache::archives");
-   std::string const pkgcache = _config->FindFile("Dir::cache::pkgcache");
-   std::string const srcpkgcache = _config->FindFile("Dir::cache::srcpkgcache");
+   std::string const listsdir = _config->FindDir("Dir::state::lists");
 
    if (_config->FindB("APT::Get::Simulate") == true)
    {
+      std::string const pkgcache = _config->FindFile("Dir::cache::pkgcache");
+      std::string const srcpkgcache = _config->FindFile("Dir::cache::srcpkgcache");
       cout << "Del " << archivedir << "* " << archivedir << "partial/*"<< endl
+	   << "Del " << listsdir << "partial/*" << endl
 	   << "Del " << pkgcache << " " << srcpkgcache << endl;
       return true;
    }
-   
+
+   bool const NoLocking = _config->FindB("Debug::NoLocking",false);
    // Lock the archive directory
    FileFd Lock;
-   if (_config->FindB("Debug::NoLocking",false) == false)
+   if (NoLocking == false)
    {
       int lock_fd = GetLock(archivedir + "lock");
       if (lock_fd < 0)
-	 return _error->Error(_("Unable to lock the download directory"));
+	 return _error->Error(_("Unable to lock directory %s"), archivedir.c_str());
       Lock.Fd(lock_fd);
    }
-   
+
    pkgAcquire Fetcher;
    Fetcher.Clean(archivedir);
    Fetcher.Clean(archivedir + "partial/");
 
+   if (NoLocking == false)
+   {
+      Lock.Close();
+      int lock_fd = GetLock(listsdir + "lock");
+      if (lock_fd < 0)
+	 return _error->Error(_("Unable to lock directory %s"), listsdir.c_str());
+      Lock.Fd(lock_fd);
+   }
+
+   Fetcher.Clean(listsdir + "partial/");
+
    pkgCacheFile::RemoveCaches();
 
    return true;
-- 
cgit v1.2.3