From 5b63d2a9a2e088bb7df7c703e9452af7efc88210 Mon Sep 17 00:00:00 2001
From: Michael Vogt
Date: Wed, 8 May 2013 17:50:15 +0200
Subject: merged patch from Daniel Hartwig to fix URI and proxy releated issues
---
.../test-bug-595691-empty-and-broken-archive-files | 14 +++++++-------
test/integration/test-releasefile-verification | 4 ++--
test/libapt/uri_test.cc | 8 ++++++++
3 files changed, 17 insertions(+), 9 deletions(-)
(limited to 'test')
diff --git a/test/integration/test-bug-595691-empty-and-broken-archive-files b/test/integration/test-bug-595691-empty-and-broken-archive-files
index 4611b8b8e..a05ed5fa6 100755
--- a/test/integration/test-bug-595691-empty-and-broken-archive-files
+++ b/test/integration/test-bug-595691-empty-and-broken-archive-files
@@ -103,23 +103,23 @@ testoverhttp() {
setupcompressor "$1"
createemptyfile 'en'
- testaptgetupdate "Get: http://localhost Packages []
-Get: http://localhost Translation-en
+ testaptgetupdate "Get: http://localhost:8080 Packages []
+Get: http://localhost:8080 Translation-en
Reading package lists..." "empty file en.$COMPRESS over http"
createemptyarchive 'en'
- testaptgetupdate "Get: http://localhost Packages []
-Get: http://localhost Translation-en []
+ testaptgetupdate "Get: http://localhost:8080 Packages []
+Get: http://localhost:8080 Translation-en []
Reading package lists..." "empty archive en.$COMPRESS over http"
createemptyarchive 'Packages'
- testaptgetupdate "Get: http://localhost Packages []
+ testaptgetupdate "Get: http://localhost:8080 Packages []
Reading package lists..." "empty archive Packages.$COMPRESS over http"
createemptyfile 'Packages'
#FIXME: we should response with a good error message instead
- testaptgetupdate "Get: http://localhost Packages
-Err http://localhost Packages
+ testaptgetupdate "Get: http://localhost:8080 Packages
+Err http://localhost:8080 Packages
Empty files can't be valid archives
W: Failed to fetch ${COMPRESSOR}:$(readlink -f rootdir/var/lib/apt/lists/partial/localhost:8080_Packages) Empty files can't be valid archives
diff --git a/test/integration/test-releasefile-verification b/test/integration/test-releasefile-verification
index 01fb2e529..fba7ab290 100755
--- a/test/integration/test-releasefile-verification
+++ b/test/integration/test-releasefile-verification
@@ -37,7 +37,7 @@ The following NEW packages will be installed:
apt
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
After this operation, 5370 kB of additional disk space will be used.
-Get:1 http://localhost/ apt 0.7.25.3
+Get:1 http://localhost:8080/ apt 0.7.25.3
Download complete and in download only mode' aptget install apt -dy
}
@@ -50,7 +50,7 @@ The following NEW packages will be installed:
apt
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
After this operation, 5808 kB of additional disk space will be used.
-Get:1 http://localhost/ apt 0.8.0~pre1
+Get:1 http://localhost:8080/ apt 0.8.0~pre1
Download complete and in download only mode' aptget install apt -dy
}
diff --git a/test/libapt/uri_test.cc b/test/libapt/uri_test.cc
index 99bb3067e..16fde503f 100644
--- a/test/libapt/uri_test.cc
+++ b/test/libapt/uri_test.cc
@@ -108,5 +108,13 @@ int main() {
equals("/debian/", U.Path);
}
+ // Percent-encoding.
+ {
+ URI U("ftp://foo:b%40r@example.org");
+ equals("foo", U.User);
+ equals("b@r", U.Password);
+ equals("ftp://foo:b%40r@example.org", (std::string) U);
+ }
+
return 0;
}
--
cgit v1.2.3-70-g09d2
From c2994dd971919a4337ea00a7aed522ccc82877c1 Mon Sep 17 00:00:00 2001
From: Michael Vogt
Date: Wed, 8 May 2013 18:58:10 +0200
Subject: fix uri test
---
test/libapt/uri_test.cc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'test')
diff --git a/test/libapt/uri_test.cc b/test/libapt/uri_test.cc
index 16fde503f..8216ade71 100644
--- a/test/libapt/uri_test.cc
+++ b/test/libapt/uri_test.cc
@@ -113,7 +113,7 @@ int main() {
URI U("ftp://foo:b%40r@example.org");
equals("foo", U.User);
equals("b@r", U.Password);
- equals("ftp://foo:b%40r@example.org", (std::string) U);
+ equals("ftp://foo:b%40r@example.org/", (std::string) U);
}
return 0;
--
cgit v1.2.3-70-g09d2
From 69335858269845904635c592268cf9519e75c1a9 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Tue, 21 May 2013 18:06:17 +0200
Subject: fix priority sorting by prefering higher in MarkInstall
Used to work until a certain (here unnamed) person came along and used
the wrong operator causing low-priority packages to be sorted above
high-priority packages while choosing a provider in commit
2b5c35c7bb915dbd46fefd7c79f05364ba22f93b from Nov 2011
---
apt-pkg/depcache.cc | 2 +-
debian/changelog | 1 +
.../test-prefer-higher-priority-providers | 36 ++++++++++++++++++++++
3 files changed, 38 insertions(+), 1 deletion(-)
create mode 100755 test/integration/test-prefer-higher-priority-providers
(limited to 'test')
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index 6a3e9bfc4..5ca0c2ea5 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -1004,7 +1004,7 @@ struct CompareProviders {
}
// higher priority seems like a good idea
if (AV->Priority != BV->Priority)
- return AV->Priority < BV->Priority;
+ return AV->Priority > BV->Priority;
// prefer native architecture
if (strcmp(A.Arch(), B.Arch()) != 0)
{
diff --git a/debian/changelog b/debian/changelog
index f57a8334f..af606453d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -6,6 +6,7 @@ apt (0.9.8.3) UNRELEASED; urgency=low
* rewrite pkgOrderList::DepRemove to stop incorrect immediate setting
(Closes: 645713)
* prefer Essentials over Removals in ordering score
+ * fix priority sorting by prefering higher in MarkInstall
-- David Kalnischkies Sun, 09 Jun 2013 15:06:24 +0200
diff --git a/test/integration/test-prefer-higher-priority-providers b/test/integration/test-prefer-higher-priority-providers
new file mode 100755
index 000000000..66458bee0
--- /dev/null
+++ b/test/integration/test-prefer-higher-priority-providers
@@ -0,0 +1,36 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'native'
+
+insertpackage 'unstable' 'foo' 'all' '1' 'Provides: stuff' 'important'
+insertpackage 'unstable' 'bar' 'all' '1' 'Provides: stuff' 'optional'
+insertpackage 'unstable' 'baz' 'all' '1' 'Provides: stuff' 'extra'
+insertpackage 'unstable' 'awesome' 'all' '1' 'Depends: stuff'
+
+setupaptarchive
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following extra packages will be installed:
+ foo
+The following NEW packages will be installed:
+ awesome foo
+0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
+Inst foo (1 unstable [all])
+Inst awesome (1 unstable [all])
+Conf foo (1 unstable [all])
+Conf awesome (1 unstable [all])' aptget install awesome -s
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+ awesome foo
+0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
+Inst foo (1 unstable [all])
+Inst awesome (1 unstable [all])
+Conf foo (1 unstable [all])
+Conf awesome (1 unstable [all])' aptget install awesome foo -s
--
cgit v1.2.3-70-g09d2
From 66706285737a895d0baf64c2387c58d5211be4f9 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Tue, 21 May 2013 21:50:30 +0200
Subject: try all providers in order if uninstallable in MarkInstall
---
apt-pkg/depcache.cc | 18 ++++--
debian/changelog | 1 +
.../test-prefer-higher-priority-providers | 70 ++++++++++++++++++++++
3 files changed, 84 insertions(+), 5 deletions(-)
(limited to 'test')
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index 5ca0c2ea5..5bed10d95 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -1200,16 +1200,23 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
verlist.insert(Cand);
}
CompareProviders comp(Start);
- APT::VersionList::iterator InstVer = std::max_element(verlist.begin(), verlist.end(), comp);
- if (InstVer != verlist.end())
- {
+ do {
+ APT::VersionList::iterator InstVer = std::max_element(verlist.begin(), verlist.end(), comp);
+
+ if (InstVer == verlist.end())
+ break;
+
pkgCache::PkgIterator InstPkg = InstVer.ParentPkg();
if(DebugAutoInstall == true)
std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.Name()
<< " as " << Start.DepType() << " of " << Pkg.Name()
<< std::endl;
- MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps);
+ if (MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps) == false)
+ {
+ verlist.erase(InstVer);
+ continue;
+ }
// now check if we should consider it a automatic dependency or not
if(InstPkg->CurrentVer == 0 && Pkg->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section()))
{
@@ -1218,7 +1225,8 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
<< Start.DepType() << " of pkg in APT::Never-MarkAuto-Sections)" << std::endl;
MarkAuto(InstPkg, false);
}
- }
+ break;
+ } while(true);
continue;
}
/* Negative dependencies have no or-group
diff --git a/debian/changelog b/debian/changelog
index af606453d..b64a57bef 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -7,6 +7,7 @@ apt (0.9.8.3) UNRELEASED; urgency=low
(Closes: 645713)
* prefer Essentials over Removals in ordering score
* fix priority sorting by prefering higher in MarkInstall
+ * try all providers in order if uninstallable in MarkInstall
-- David Kalnischkies Sun, 09 Jun 2013 15:06:24 +0200
diff --git a/test/integration/test-prefer-higher-priority-providers b/test/integration/test-prefer-higher-priority-providers
index 66458bee0..64b901dd0 100755
--- a/test/integration/test-prefer-higher-priority-providers
+++ b/test/integration/test-prefer-higher-priority-providers
@@ -34,3 +34,73 @@ Inst foo (1 unstable [all])
Inst awesome (1 unstable [all])
Conf foo (1 unstable [all])
Conf awesome (1 unstable [all])' aptget install awesome foo -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'bar' is not installed, so not removed
+Package 'baz' is not installed, so not removed
+The following extra packages will be installed:
+ foo
+The following NEW packages will be installed:
+ awesome foo
+0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
+Inst foo (1 unstable [all])
+Inst awesome (1 unstable [all])
+Conf foo (1 unstable [all])
+Conf awesome (1 unstable [all])" aptget install awesome bar- baz- -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'foo' is not installed, so not removed
+The following extra packages will be installed:
+ bar
+The following NEW packages will be installed:
+ awesome bar
+0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
+Inst bar (1 unstable [all])
+Inst awesome (1 unstable [all])
+Conf bar (1 unstable [all])
+Conf awesome (1 unstable [all])" aptget install awesome foo- -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'foo' is not installed, so not removed
+Package 'baz' is not installed, so not removed
+The following extra packages will be installed:
+ bar
+The following NEW packages will be installed:
+ awesome bar
+0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
+Inst bar (1 unstable [all])
+Inst awesome (1 unstable [all])
+Conf bar (1 unstable [all])
+Conf awesome (1 unstable [all])" aptget install awesome foo- baz- -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'foo' is not installed, so not removed
+Package 'bar' is not installed, so not removed
+The following extra packages will be installed:
+ baz
+The following NEW packages will be installed:
+ awesome baz
+0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
+Inst baz (1 unstable [all])
+Inst awesome (1 unstable [all])
+Conf baz (1 unstable [all])
+Conf awesome (1 unstable [all])" aptget install awesome foo- bar- -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'foo' is not installed, so not removed
+Package 'bar' is not installed, so not removed
+Package 'baz' is not installed, so not removed
+Some packages could not be installed. This may mean that you have
+requested an impossible situation or if you are using the unstable
+distribution that some required packages have not yet been created
+or been moved out of Incoming.
+The following information may help to resolve the situation:
+
+The following packages have unmet dependencies:
+ awesome : Depends: stuff
+E: Unable to correct problems, you have held broken packages." aptget install awesome foo- bar- baz- -s
--
cgit v1.2.3-70-g09d2
From 42d51f333e8ef522fed02cdfc48663488d56c3a3 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Thu, 23 May 2013 12:14:56 +0200
Subject: do unpacks before configures in SmartConfigure
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Splits the big loop over dependencies in SmartConfigure which unpacks and
configures dependencies into two loops and reverse their order, so that all
dependencies which need to be unpacked are handled first and only after that
configures are issued for dependencies.
This is needed as otherwise the unpack of a (new) dependency will be issued
in between a configure call for two (or more) packages which form a loop,
which means the configure calls aren't part of the same dpkg call and
therefore dpkg bails out.
Such tight loops should really be avoided as they are usually wrong – and in
reality the dependencies in libreoffice were greatly simplified thanks to
Rene Engelhard so the problem is gone for the benefit of all.
Closes: 707578
---
apt-pkg/packagemanager.cc | 113 +++++++++++++--------
debian/changelog | 1 +
...ight-loop-configure-with-unpacking-new-packages | 46 +++++++++
3 files changed, 115 insertions(+), 45 deletions(-)
create mode 100755 test/integration/test-very-tight-loop-configure-with-unpacking-new-packages
(limited to 'test')
diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc
index e2d7dbf2a..b8932753d 100644
--- a/apt-pkg/packagemanager.cc
+++ b/apt-pkg/packagemanager.cc
@@ -340,6 +340,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
bool Bad = false, Changed = false;
const unsigned int max_loops = _config->FindI("APT::pkgPackageManager::MaxLoopCount", 500);
unsigned int i=0;
+ std::list needConfigure;
do
{
Changed = false;
@@ -353,7 +354,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
continue;
Bad = true;
- // Search for dependencies which are unpacked but aren't configured yet (maybe loops)
+ // Check for dependencies that have not been unpacked, probably due to loops.
for (DepIterator Cur = Start; true; ++Cur)
{
SPtrArray VList = Cur.AllTargets();
@@ -373,51 +374,63 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
}
// Check if the version that is going to be installed will satisfy the dependency
- if (Cache[DepPkg].InstallVer != *I)
+ if (Cache[DepPkg].InstallVer != *I || List->IsNow(DepPkg) == false)
continue;
- if (List->IsFlag(DepPkg,pkgOrderList::UnPacked))
+ if (PkgLoop == true)
{
- if (List->IsFlag(DepPkg,pkgOrderList::Loop) && PkgLoop)
- {
- // This dependency has already been dealt with by another SmartConfigure on Pkg
- Bad = false;
- break;
- }
- /* Check for a loop to prevent one forming
- If A depends on B and B depends on A, SmartConfigure will
- just hop between them if this is not checked. Dont remove the
- loop flag after finishing however as loop is already set.
- This means that there is another SmartConfigure call for this
- package and it will remove the loop flag */
+ if (Debug)
+ std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl;
+ Bad = false;
+ break;
+ }
+ else
+ {
+ if (Debug)
+ clog << OutputInDepth(Depth) << "Unpacking " << DepPkg.FullName() << " to avoid loop " << Cur << endl;
if (PkgLoop == false)
List->Flag(Pkg,pkgOrderList::Loop);
- if (SmartConfigure(DepPkg, Depth + 1) == true)
+ if (SmartUnPack(DepPkg, true, Depth + 1) == true)
{
Bad = false;
if (List->IsFlag(DepPkg,pkgOrderList::Loop) == false)
- Changed = true;
+ Changed = true;
}
if (PkgLoop == false)
- List->RmFlag(Pkg,pkgOrderList::Loop);
- // If SmartConfigure was succesfull, Bad is false, so break
+ List->RmFlag(Pkg,pkgOrderList::Loop);
if (Bad == false)
break;
}
- else if (List->IsFlag(DepPkg,pkgOrderList::Configured))
- {
- Bad = false;
- break;
- }
}
- if (Cur == End)
+
+ if (Cur == End || Bad == false)
break;
- }
+ }
if (Bad == false)
continue;
- // Check for dependencies that have not been unpacked, probably due to loops.
+ needConfigure.push_back(Start);
+ }
+ if (i++ > max_loops)
+ return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack (1) for %s, aborting", Pkg.FullName().c_str());
+ } while (Changed == true);
+
+ Bad = false, Changed = false, i = 0;
+ do
+ {
+ Changed = false;
+ for (std::list::iterator D = needConfigure.begin(); D != needConfigure.end(); ++D)
+ {
+ // Compute a single dependency element (glob or)
+ pkgCache::DepIterator Start, End;
+ D->GlobOr(Start,End);
+
+ if (End->Type != pkgCache::Dep::Depends)
+ continue;
+ Bad = true;
+
+ // Search for dependencies which are unpacked but aren't configured yet (maybe loops)
for (DepIterator Cur = Start; true; ++Cur)
{
SPtrArray VList = Cur.AllTargets();
@@ -428,44 +441,54 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
PkgIterator DepPkg = Ver.ParentPkg();
// Check if the version that is going to be installed will satisfy the dependency
- if (Cache[DepPkg].InstallVer != *I || List->IsNow(DepPkg) == false)
+ if (Cache[DepPkg].InstallVer != *I)
continue;
- if (PkgLoop == true)
- {
- if (Debug)
- std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl;
- Bad = false;
- break;
- }
- else
+ if (List->IsFlag(DepPkg,pkgOrderList::UnPacked))
{
- if (Debug)
- clog << OutputInDepth(Depth) << "Unpacking " << DepPkg.FullName() << " to avoid loop " << Cur << endl;
+ if (List->IsFlag(DepPkg,pkgOrderList::Loop) && PkgLoop)
+ {
+ // This dependency has already been dealt with by another SmartConfigure on Pkg
+ Bad = false;
+ break;
+ }
+ /* Check for a loop to prevent one forming
+ If A depends on B and B depends on A, SmartConfigure will
+ just hop between them if this is not checked. Dont remove the
+ loop flag after finishing however as loop is already set.
+ This means that there is another SmartConfigure call for this
+ package and it will remove the loop flag */
if (PkgLoop == false)
List->Flag(Pkg,pkgOrderList::Loop);
- if (SmartUnPack(DepPkg, true, Depth + 1) == true)
+ if (SmartConfigure(DepPkg, Depth + 1) == true)
{
Bad = false;
if (List->IsFlag(DepPkg,pkgOrderList::Loop) == false)
- Changed = true;
+ Changed = true;
}
if (PkgLoop == false)
- List->RmFlag(Pkg,pkgOrderList::Loop);
+ List->RmFlag(Pkg,pkgOrderList::Loop);
+ // If SmartConfigure was succesfull, Bad is false, so break
if (Bad == false)
break;
}
+ else if (List->IsFlag(DepPkg,pkgOrderList::Configured))
+ {
+ Bad = false;
+ break;
+ }
}
-
- if (Cur == End)
+ if (Cur == End || Bad == false)
break;
- }
+ }
+
+
if (Bad == true && Changed == false && Debug == true)
std::clog << OutputInDepth(Depth) << "Could not satisfy " << Start << std::endl;
}
if (i++ > max_loops)
- return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack for %s, aborting", Pkg.FullName().c_str());
+ return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack (2) for %s, aborting", Pkg.FullName().c_str());
} while (Changed == true);
if (Bad) {
diff --git a/debian/changelog b/debian/changelog
index b64a57bef..8a1194b1b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -8,6 +8,7 @@ apt (0.9.8.3) UNRELEASED; urgency=low
* prefer Essentials over Removals in ordering score
* fix priority sorting by prefering higher in MarkInstall
* try all providers in order if uninstallable in MarkInstall
+ * do unpacks before configures in SmartConfigure (Closes: #707578)
-- David Kalnischkies Sun, 09 Jun 2013 15:06:24 +0200
diff --git a/test/integration/test-very-tight-loop-configure-with-unpacking-new-packages b/test/integration/test-very-tight-loop-configure-with-unpacking-new-packages
new file mode 100755
index 000000000..7f3b05e59
--- /dev/null
+++ b/test/integration/test-very-tight-loop-configure-with-unpacking-new-packages
@@ -0,0 +1,46 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64'
+
+# the difference between version 3 and 4 is the new package 'ure' which
+# we have to unpack before we start configuring parts of the loop
+insertinstalledpackage 'libreoffice' 'amd64' '3' 'Depends: libreoffice-core (= 3)'
+insertinstalledpackage 'libreoffice-core' 'amd64' '3' 'Depends: libreoffice-common (>= 3)'
+insertinstalledpackage 'libreoffice-common' 'all' '3' 'Depends: libreoffice-style
+Breaks: libreoffice-core (>= 3+), libreoffice-core (<= 3~), libreoffice-style-galaxy (>= 3+), libreoffice-style-galaxy (<= 3~)'
+insertinstalledpackage 'libreoffice-style-galaxy' 'amd64' '3' 'Depends: libreoffice-core
+Provides: libreoffice-style'
+
+buildsimplenativepackage 'libreoffice' 'amd64' '4' 'sid' 'Depends: libreoffice-core (= 4)'
+buildsimplenativepackage 'libreoffice-core' 'amd64' '4' 'sid' 'Depends: libreoffice-common (>= 4)
+Breaks: libreoffice-common (<< 4), libreoffice-style-galaxy (<< 4)'
+buildsimplenativepackage 'libreoffice-common' 'all' '4' 'sid' 'Depends: libreoffice-style, ure
+Breaks: libreoffice-core (>= 4+), libreoffice-core (<= 4~), libreoffice-style-galaxy (>= 4+), libreoffice-style-galaxy (<= 4~)'
+buildsimplenativepackage 'libreoffice-style-galaxy' 'amd64' '4' 'sid' 'Depends: libreoffice-core
+Provides: libreoffice-style'
+
+buildsimplenativepackage 'ure' 'amd64' '4' 'sid'
+
+setupaptarchive
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+ ure
+The following packages will be upgraded:
+ libreoffice libreoffice-common libreoffice-core libreoffice-style-galaxy
+4 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst libreoffice [3] (4 sid [amd64]) []
+Inst libreoffice-style-galaxy [3] (4 sid [amd64]) [libreoffice-common:amd64 on libreoffice-style-galaxy:amd64] [libreoffice-common:amd64 ]
+Inst libreoffice-core [3] (4 sid [amd64]) [libreoffice-core:amd64 on libreoffice-common:amd64] [libreoffice-common:amd64 on libreoffice-core:amd64] [libreoffice-common:amd64 on libreoffice-style-galaxy:amd64] [libreoffice-common:amd64 ]
+Inst libreoffice-common [3] (4 sid [all]) []
+Inst ure (4 sid [amd64])
+Conf ure (4 sid [amd64])
+Conf libreoffice-style-galaxy (4 sid [amd64])
+Conf libreoffice-common (4 sid [all])
+Conf libreoffice-core (4 sid [amd64])
+Conf libreoffice (4 sid [amd64])' aptget dist-upgrade -s
--
cgit v1.2.3-70-g09d2
From 8ba17539a3ec33abc283ca382cca6e59876a0f07 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Sat, 25 May 2013 19:57:48 +0200
Subject: fix support for multiple patterns in apt-cache search
Patterns can appear in the name as well as in the description,
they don't have to match all in the name/description only.
Closes: 691453
---
cmdline/apt-cache.cc | 79 ++++++++++++++--------
debian/changelog | 6 +-
test/integration/framework | 12 +++-
.../test-bug-691453-apt-cache-search-multi-pattern | 33 +++++++++
4 files changed, 94 insertions(+), 36 deletions(-)
create mode 100755 test/integration/test-bug-691453-apt-cache-search-multi-pattern
(limited to 'test')
diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc
index de263a300..bda09a5a1 100644
--- a/cmdline/apt-cache.cc
+++ b/cmdline/apt-cache.cc
@@ -1203,7 +1203,7 @@ bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
struct ExDescFile
{
pkgCache::DescFile *Df;
- bool NameMatch;
+ map_ptrloc ID;
};
// Search - Perform a search /*{{{*/
@@ -1246,37 +1246,48 @@ bool Search(CommandLine &CmdL)
return false;
}
- ExDescFile *DFList = new ExDescFile[Cache->HeaderP->GroupCount+1];
- memset(DFList, 0, sizeof(*DFList) * (Cache->HeaderP->GroupCount + 1));
+ size_t const descCount = Cache->HeaderP->GroupCount + 1;
+ ExDescFile *DFList = new ExDescFile[descCount];
+ memset(DFList,0,sizeof(*DFList) * descCount);
+
+ bool PatternMatch[descCount * NumPatterns];
+ memset(PatternMatch,false,sizeof(PatternMatch));
// Map versions that we want to write out onto the VerList array.
for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
{
- if (DFList[G->ID].NameMatch == true)
- continue;
-
- DFList[G->ID].NameMatch = true;
- for (unsigned I = 0; I != NumPatterns; I++)
+ size_t const PatternOffset = G->ID * NumPatterns;
+ size_t unmatched = 0, matched = 0;
+ for (unsigned I = 0; I < NumPatterns; ++I)
{
- if (regexec(&Patterns[I],G.Name(),0,0,0) == 0)
- continue;
- DFList[G->ID].NameMatch = false;
- break;
+ if (PatternMatch[PatternOffset + I] == true)
+ ++matched;
+ else if (regexec(&Patterns[I],G.Name(),0,0,0) == 0)
+ PatternMatch[PatternOffset + I] = true;
+ else
+ ++unmatched;
}
-
- // Doing names only, drop any that dont match..
- if (NamesOnly == true && DFList[G->ID].NameMatch == false)
+
+ // already dealt with this package?
+ if (matched == NumPatterns)
continue;
-
+
+ // Doing names only, drop any that don't match..
+ if (NamesOnly == true && unmatched == NumPatterns)
+ continue;
+
// Find the proper version to use
pkgCache::PkgIterator P = G.FindPreferredPkg();
if (P.end() == true)
continue;
pkgCache::VerIterator V = Plcy->GetCandidateVer(P);
if (V.end() == false)
+ {
DFList[G->ID].Df = V.TranslatedDescription().FileList();
+ DFList[G->ID].ID = G->ID;
+ }
- if (DFList[G->ID].NameMatch == false)
+ if (unmatched == NumPatterns)
continue;
// Include all the packages that provide matching names too
@@ -1288,33 +1299,45 @@ bool Search(CommandLine &CmdL)
unsigned long id = Prv.OwnerPkg().Group()->ID;
DFList[id].Df = V.TranslatedDescription().FileList();
- DFList[id].NameMatch = true;
+ DFList[id].ID = id;
+
+ size_t const PrvPatternOffset = id * NumPatterns;
+ for (unsigned I = 0; I < NumPatterns; ++I)
+ PatternMatch[PrvPatternOffset + I] = PatternMatch[PatternOffset + I];
}
}
-
+
LocalitySort(&DFList->Df,Cache->HeaderP->GroupCount,sizeof(*DFList));
// Create the text record parser
pkgRecords Recs(*Cache);
// Iterate over all the version records and check them
- for (ExDescFile *J = DFList; J->Df != 0; J++)
+ for (ExDescFile *J = DFList; J->Df != 0; ++J)
{
pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(*Cache,J->Df));
+ size_t const PatternOffset = J->ID * NumPatterns;
- if (J->NameMatch == false && NamesOnly == false)
+ if (NamesOnly == false)
{
string const LongDesc = P.LongDesc();
- J->NameMatch = true;
- for (unsigned I = 0; I != NumPatterns; I++)
+ for (unsigned I = 0; I < NumPatterns; ++I)
{
- if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
+ if (PatternMatch[PatternOffset + I] == true)
continue;
- J->NameMatch = false;
- break;
+ else if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
+ PatternMatch[PatternOffset + I] = true;
}
}
-
- if (J->NameMatch == true)
+
+ bool matchedAll = true;
+ for (unsigned I = 0; I < NumPatterns; ++I)
+ if (PatternMatch[PatternOffset + I] == false)
+ {
+ matchedAll = false;
+ break;
+ }
+
+ if (matchedAll == true)
{
if (ShowFull == true)
{
diff --git a/debian/changelog b/debian/changelog
index 8a1194b1b..9f35441f9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -9,6 +9,7 @@ apt (0.9.8.3) UNRELEASED; urgency=low
* fix priority sorting by prefering higher in MarkInstall
* try all providers in order if uninstallable in MarkInstall
* do unpacks before configures in SmartConfigure (Closes: #707578)
+ * fix support for multiple patterns in apt-cache search (Closes: #691453)
-- David Kalnischkies Sun, 09 Jun 2013 15:06:24 +0200
@@ -31,11 +32,6 @@ apt (0.9.8.2) unstable; urgency=low
* Fix crash when the "mirror" method does not find any entry
(closes: #699303)
- [ Johan Kiviniemi ]
- * cmdline/apt-key:
- - Create new keyrings with mode 0644 instead of 0600.
- - Accept a nonexistent --keyring file with the adv subcommand as well.
-
-- Michael Vogt Thu, 06 Jun 2013 19:15:14 +0200
apt (0.9.8.1) unstable; urgency=low
diff --git a/test/integration/framework b/test/integration/framework
index 31b12e8bf..e3e868d45 100644
--- a/test/integration/framework
+++ b/test/integration/framework
@@ -483,6 +483,7 @@ insertpackage() {
local VERSION="$4"
local DEPENDENCIES="$5"
local PRIORITY="${6:-optional}"
+ local DESCRIPTION="${7}"
local ARCHS=""
for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do
if [ "$arch" = 'all' -o "$arch" = 'none' ]; then
@@ -504,11 +505,16 @@ Maintainer: Joe Sixpack " >> $FILE
echo "Version: $VERSION
Filename: pool/main/${NAME}/${NAME}_${VERSION}_${arch}.deb" >> $FILE
test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> $FILE
- echo "Description: an autogenerated dummy ${NAME}=${VERSION}/${RELEASE}
+ echo -n 'Description: ' >> $FILE
+ if [ -z "$DESCRIPTION" ]; then
+ echo "an autogenerated dummy ${NAME}=${VERSION}/${RELEASE}
If you find such a package installed on your system,
YOU did something horribly wrong! They are autogenerated
- und used only by testcases for APT and surf no other propose…
-" >> $FILE
+ und used only by testcases for APT and surf no other propose…" >> $FILE
+ else
+ echo "$DESCRIPTION" >> $FILE
+ fi
+ echo >> $FILE
done
done
}
diff --git a/test/integration/test-bug-691453-apt-cache-search-multi-pattern b/test/integration/test-bug-691453-apt-cache-search-multi-pattern
new file mode 100755
index 000000000..0367892fc
--- /dev/null
+++ b/test/integration/test-bug-691453-apt-cache-search-multi-pattern
@@ -0,0 +1,33 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'native'
+
+insertpackage 'unstable' 'foobar' 'native' '1' '' '' 'funky tool'
+insertpackage 'unstable' 'coolstuff' 'native' '1' '' '' 'funky tool just like foo and bar'
+insertpackage 'unstable' 'foo' 'native' '1' '' '' 'tool best used with bar'
+insertpackage 'unstable' 'bar' 'native' '1' '' '' 'tool best used with foo'
+insertpackage 'unstable' 'baz' 'native' '1' 'Provides: bar' '' 'alternative tool best used with foo'
+
+setupaptarchive
+
+# in this special case the following queries should be equal
+FOOBAR='foobar - funky tool
+coolstuff - funky tool just like foo and bar
+foo - tool best used with bar
+bar - tool best used with foo
+baz - alternative tool best used with foo'
+
+testequal "$FOOBAR" aptcache search foo
+testequal "$FOOBAR" aptcache search bar
+testequal "$FOOBAR" aptcache search foo bar
+
+testequal 'foobar - funky tool
+foo - tool best used with bar' aptcache search -n foo
+testequal 'foobar - funky tool
+bar - tool best used with foo
+baz - alternative tool best used with foo' aptcache search -n bar
+testequal 'foobar - funky tool' aptcache search -n foo bar
--
cgit v1.2.3-70-g09d2
From 8437b7d4a699c8a0bfa6c2c2bff66ffff2e36a22 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Tue, 28 May 2013 18:08:32 +0200
Subject: tests: trap-adding can be post- as well as prefix
For testcases it might sometimes be handy to add trap-actions
before the general cleanup, e.g. if it has set directories read-
only which rm doesn't want to remove even with --force applied
(its fine with files though)
Git-Dch: Ignore
---
test/integration/framework | 9 ++++++---
test/integration/test-apt-cdrom | 2 +-
2 files changed, 7 insertions(+), 4 deletions(-)
(limited to 'test')
diff --git a/test/integration/framework b/test/integration/framework
index e3e868d45..7c2aed592 100644
--- a/test/integration/framework
+++ b/test/integration/framework
@@ -125,7 +125,11 @@ exitwithstatus() {
}
addtrap() {
- CURRENTTRAP="$CURRENTTRAP $1"
+ if [ "$1" = 'prefix' ]; then
+ CURRENTTRAP="$2 $CURRENTTRAP"
+ else
+ CURRENTTRAP="$CURRENTTRAP $1"
+ fi
trap "$CURRENTTRAP exitwithstatus;" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
}
@@ -135,8 +139,7 @@ setupenvironment() {
msgninfo "Preparing environment for ${CCMD}$(basename $0)${CINFO} in ${TMPWORKINGDIRECTORY}… "
BUILDDIRECTORY="${TESTDIRECTORY}/../../build/bin"
test -x "${BUILDDIRECTORY}/apt-get" || msgdie "You need to build tree first"
- local OLDWORKINGDIRECTORY=$(pwd)
- addtrap "cd /; rm -rf $TMPWORKINGDIRECTORY; cd $OLDWORKINGDIRECTORY;"
+ addtrap "cd /; rm -rf $TMPWORKINGDIRECTORY;"
cd $TMPWORKINGDIRECTORY
mkdir rootdir aptarchive keys
cd rootdir
diff --git a/test/integration/test-apt-cdrom b/test/integration/test-apt-cdrom
index f1c4fd9d3..3394aa505 100755
--- a/test/integration/test-apt-cdrom
+++ b/test/integration/test-apt-cdrom
@@ -24,7 +24,7 @@ cat Translation-de | xz --format=lzma > Translation-de.lzma
cat Translation-de | xz > Translation-de.xz
rm Translation-en Translation-de
cd - > /dev/null
-addtrap "chmod -R +w $PWD/rootdir/media/cdrom/dists/;"
+addtrap 'prefix' "chmod -R +w $PWD/rootdir/media/cdrom/dists/;"
chmod -R -w rootdir/media/cdrom/dists
aptcdrom add -m -o quiet=1 > apt-cdrom.log 2>&1
--
cgit v1.2.3-70-g09d2
From 2842f3e6c42ac6c6512a290064326d55bfa62a40 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Tue, 28 May 2013 18:17:55 +0200
Subject: tests: add expected port for cve-2013-105 testcase
Git-Dch: Ignore
---
test/integration/test-cve-2013-1051-InRelease-parsing | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'test')
diff --git a/test/integration/test-cve-2013-1051-InRelease-parsing b/test/integration/test-cve-2013-1051-InRelease-parsing
index bd68fccf6..853da5ff6 100755
--- a/test/integration/test-cve-2013-1051-InRelease-parsing
+++ b/test/integration/test-cve-2013-1051-InRelease-parsing
@@ -12,7 +12,7 @@ insertpackage 'stable' 'good-pkg' 'all' '1.0'
setupaptarchive
changetowebserver
-ARCHIVE='http://localhost/'
+ARCHIVE='http://localhost:8080/'
msgtest 'Initial apt-get update should work with' 'InRelease'
aptget update -qq && msgpass || msgfail
--
cgit v1.2.3-70-g09d2
From 57da1b4bd21aceced30f658993fb811a5232cff7 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Fri, 31 May 2013 18:19:09 +0200
Subject: stop building l10n if strings are unchanged
The buildsystem tried to build l10n for test applications which never
produced the output it expected causing it to try building it all the
time.
---
buildlib/copy.mak | 2 +-
buildlib/podomain.mak | 7 ++++++-
doc/makefile | 2 +-
po/makefile | 15 +++++++++++----
test/interactive-helper/makefile | 1 +
test/libapt/makefile | 1 +
6 files changed, 21 insertions(+), 7 deletions(-)
(limited to 'test')
diff --git a/buildlib/copy.mak b/buildlib/copy.mak
index e8fe43deb..3ae11a7eb 100644
--- a/buildlib/copy.mak
+++ b/buildlib/copy.mak
@@ -21,7 +21,7 @@ veryclean: veryclean/$(LOCAL)
MKDIRS += $(dir $($(LOCAL)-LIST))
-$($(LOCAL)-LIST) : $(TO)/% : % dirs
+$($(LOCAL)-LIST) : $(TO)/% : %
echo Installing $< to $(@D)
cp $< $(@D)
diff --git a/buildlib/podomain.mak b/buildlib/podomain.mak
index cca7d55be..265359abc 100644
--- a/buildlib/podomain.mak
+++ b/buildlib/podomain.mak
@@ -4,6 +4,8 @@
# declared domain of the make file. It also arranges to set the DOMAIN
# CPPFLAG for the compilation.
+ifneq ($(APT_DOMAIN),none)
+
MY_DOMAIN := $(PACKAGE)
ifdef APT_DOMAIN
$($(LOCAL)-OBJS): CPPFLAGS := $(CPPFLAGS) -DAPT_DOMAIN='"$(APT_DOMAIN)"'
@@ -13,10 +15,13 @@ endif
MKDIRS += $(PO_DOMAINS)/$(MY_DOMAIN)
$(PO_DOMAINS)/$(MY_DOMAIN)/$(LOCAL).$(TYPE)list: SRC := $(addprefix $(SUBDIR)/,$(SOURCE))
$(PO_DOMAINS)/$(MY_DOMAIN)/$(LOCAL).$(TYPE)list: makefile dirs
- (echo $(SRC) | xargs -n1 echo) > $@
+ (echo $(SRC) | xargs -n1 echo) > $@.tmp
+ cmp --silent $@.tmp $@ || mv $@.tmp $@
startup binary program clean update-po: $(PO_DOMAINS)/$(MY_DOMAIN)/$(LOCAL).$(TYPE)list
veryclean: veryclean/$(LOCAL)
veryclean/po/$(LOCAL): LIST := $(PO_DOMAINS)/$(MY_DOMAIN)/$(LOCAL).$(TYPE)list
veryclean/po/$(LOCAL):
rm -f $(LIST)
+
+endif
diff --git a/doc/makefile b/doc/makefile
index 44a22a597..274fbc278 100644
--- a/doc/makefile
+++ b/doc/makefile
@@ -36,7 +36,7 @@ $(DOCDIRLIST) :: %/makefile : lang.makefile
test -d $(dir $@) || mkdir $(dir $@)
sed "s#@@LANG@@#$(subst /,,$(dir $@))#" $< > $@
-debiandoc/subdirs manpages/subdirs clean/subdirs veryclean/subdirs: dirs
+debiandoc/subdirs manpages/subdirs clean/subdirs veryclean/subdirs:
for dir in en $(dir $(DOCDIRLIST)); do \
$(MAKE) -C $$dir $(patsubst %/subdirs,%,$@); \
done
diff --git a/po/makefile b/po/makefile
index ebf6c06d0..5a3c7fb67 100644
--- a/po/makefile
+++ b/po/makefile
@@ -30,17 +30,23 @@ GETDOMAIN = $(word 1,$(subst /, ,$(1)))
# and produce the .pot file.
$(POTFILES) : $(PO)/%.pot :
echo "Generating POT file $@"
- echo $@ : $(wildcard $(PO)/domains/$*/*.*list) $(addprefix $(BASE)/,$(shell cat $(wildcard $(PO)/domains/$*/*.srclist))) > $@.d
+ echo $@ : $(wildcard $(PO)/domains/$*/*.*list) $(addprefix $(BASE)/,$(shell cat $(wildcard $(PO)/domains/$*/*.srclist))) > $@.d.tmp
+ cmp --silent $@.d.tmp $@.d || mv $@.d.tmp $@.d
# From sh source
- cat $(PO)/domains/$*/*.shlist 2> /dev/null | (cd $(BASE) && xargs -n1 bash --dump-po-strings) > $(PO)/domains/$*/sh.pot
+ cat $(PO)/domains/$*/*.shlist 2> /dev/null | (cd $(BASE) && xargs -n1 bash --dump-po-strings) > $(PO)/domains/$*/sh.pot.tmp
+ cmp --silent $(PO)/domains/$*/sh.pot.tmp $(PO)/domains/$*/sh.pot || \
+ mv $(PO)/domains/$*/sh.pot.tmp $(PO)/domains/$*/sh.pot
# From C/C++ source
cat $(PO)/domains/$*/*.srclist > $(PO)/POTFILES_$*.in
$(XGETTEXT) --default-domain=$* --directory=$(BASE) \
--add-comments --foreign --keyword=_ --keyword=N_ \
--keyword=P_:1,2 \
- --files-from=$(PO)/POTFILES_$*.in -o $(PO)/domains/$*/c.pot
+ --files-from=$(PO)/POTFILES_$*.in -o $(PO)/domains/$*/c.pot.tmp
+ cmp --silent $(PO)/domains/$*/c.pot.tmp $(PO)/domains/$*/c.pot || \
+ mv $(PO)/domains/$*/c.pot.tmp $(PO)/domains/$*/c.pot
rm -f $(PO)/POTFILES_$*.in
- $(MSGCOMM) --omit-header --more-than=0 $(PO)/domains/$*/c.pot $(PO)/domains/$*/sh.pot --output=$@
+ $(MSGCOMM) --omit-header --more-than=0 $(PO)/domains/$*/c.pot $(PO)/domains/$*/sh.pot --output=$@.tmp
+ cmp --silent $@ $@.tmp || mv $@.tmp $@
# copy into the domain dirs to make rosetta happy
rm -f $(PO)/domains/$*/*.pot
cp $@ $(PO)/domains/$*
@@ -93,4 +99,5 @@ ifneq ($(words $(The_DFiles)),0)
include $(The_DFiles)
endif
+# otherwise the output is completely screwed
.NOTPARALLEL:
diff --git a/test/interactive-helper/makefile b/test/interactive-helper/makefile
index 10d1e44ec..fa4f5fecb 100644
--- a/test/interactive-helper/makefile
+++ b/test/interactive-helper/makefile
@@ -1,6 +1,7 @@
# -*- make -*-
BASE=../..
SUBDIR=test/interactive-helper
+APT_DOMAIN=none
# Bring in the default rules
include ../../buildlib/defaults.mak
diff --git a/test/libapt/makefile b/test/libapt/makefile
index 953e455e0..1b67cba9d 100644
--- a/test/libapt/makefile
+++ b/test/libapt/makefile
@@ -2,6 +2,7 @@
BASE=../..
SUBDIR=test/libapt
BASENAME=_libapt_test
+APT_DOMAIN=none
# Bring in the default rules
include ../../buildlib/defaults.mak
--
cgit v1.2.3-70-g09d2
From b2ea1a47531266377abe4f12c6f21417ea96eea0 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Sun, 9 Jun 2013 18:58:34 +0200
Subject: ensure state-dir exists before coyping cdrom files
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We do the same in the acquire system which handles the 'normal'
downloads, so do it here as well even though its unlikely anyone
will ever notice (beside testcases of course …)
---
apt-pkg/cdrom.cc | 8 ++++++++
debian/changelog | 1 +
test/integration/framework | 8 +++++---
test/integration/test-apt-cdrom | 2 +-
4 files changed, 15 insertions(+), 4 deletions(-)
(limited to 'test')
diff --git a/apt-pkg/cdrom.cc b/apt-pkg/cdrom.cc
index 9a9a854bf..a5668a50a 100644
--- a/apt-pkg/cdrom.cc
+++ b/apt-pkg/cdrom.cc
@@ -829,6 +829,14 @@ bool pkgCdrom::Add(pkgCdromStatus *log) /*{{{*/
log->Update(msg.str());
log->Update(_("Copying package lists..."), STEP_COPY);
}
+
+ // check for existence and possibly create state directory for copying
+ string const listDir = _config->FindDir("Dir::State::lists");
+ string const partialListDir = listDir + "partial/";
+ if (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::State"), partialListDir) == false &&
+ CreateAPTDirectoryIfNeeded(listDir, partialListDir) == false)
+ return _error->Errno("cdrom", _("List directory %spartial is missing."), listDir.c_str());
+
// take care of the signatures and copy them if they are ok
// (we do this before PackageCopy as it modifies "List" and "SourceList")
SigVerify SignVerify;
diff --git a/debian/changelog b/debian/changelog
index cde0aba2f..7582b4f35 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -14,6 +14,7 @@ apt (0.9.8.3) UNRELEASED; urgency=low
* don't explicitly init ExtractTar InFd with invalid fd
* OpenDescriptor should autoclose fd always on error (Closes: #704608)
* fail in CopyFile if the FileFds have error flag set
+ * ensure state-dir exists before coyping cdrom files
-- David Kalnischkies Sun, 09 Jun 2013 15:06:24 +0200
diff --git a/test/integration/framework b/test/integration/framework
index 7c2aed592..5c50498a2 100644
--- a/test/integration/framework
+++ b/test/integration/framework
@@ -692,9 +692,11 @@ setupaptarchive() {
setupflataptarchive
fi
signreleasefiles
- msgninfo "\tSync APT's cache with the archive… "
- aptget update -qq
- msgdone "info"
+ if [ "$1" != '--no-update' ]; then
+ msgninfo "\tSync APT's cache with the archive… "
+ aptget update -qq
+ msgdone "info"
+ fi
}
signreleasefiles() {
diff --git a/test/integration/test-apt-cdrom b/test/integration/test-apt-cdrom
index 3394aa505..6e3533152 100755
--- a/test/integration/test-apt-cdrom
+++ b/test/integration/test-apt-cdrom
@@ -7,7 +7,7 @@ setupenvironment
configarchitecture 'amd64' 'i386'
buildsimplenativepackage 'testing' 'amd64,i386' '0.8.15' 'stable'
-setupaptarchive
+setupaptarchive --no-update
changetocdrom 'Debian APT Testdisk 0.8.15'
--
cgit v1.2.3-70-g09d2
From 8b8cc7bf85ac187bb9333f56c4c2c4dba27d3a7e Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Sun, 9 Jun 2013 22:13:20 +0200
Subject: tests: add an interactive 'test' with multiple cdroms
Can't be used as a test as is, but shows how to build multiple
CD-ROMs for tests and can be used to reproduce debbug #711456.
Git-Dch: Ignore
---
...kip-bug-711456-apt-cdrom-multiple-cds-multiarch | 47 ++++++++++++++++++++++
1 file changed, 47 insertions(+)
create mode 100755 test/integration/skip-bug-711456-apt-cdrom-multiple-cds-multiarch
(limited to 'test')
diff --git a/test/integration/skip-bug-711456-apt-cdrom-multiple-cds-multiarch b/test/integration/skip-bug-711456-apt-cdrom-multiple-cds-multiarch
new file mode 100755
index 000000000..9e683b5b9
--- /dev/null
+++ b/test/integration/skip-bug-711456-apt-cdrom-multiple-cds-multiarch
@@ -0,0 +1,47 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64' 'i386'
+
+buildsimplenativepackage 'testing' 'amd64,i386' '0.8.15' 'stable' 'Depends: libtest'
+buildsimplenativepackage 'libtest' 'amd64,i386' '0.8.15' 'stable' 'Multi-Arch: same'
+buildsimplenativepackage 'libtest' 'amd64,i386' '1' 'unstable' 'Multi-Arch: same'
+
+# needed by the ftparchive.conf
+cd aptarchive
+ln -s ../incoming pool
+createaptftparchiveconfig
+cd - >/dev/null
+# create an amd64 cdrom
+sed -i 's#Architectures .*$#Architectures "amd64 source";#' aptarchive/ftparchive.conf
+setupaptarchive --no-update
+changetocdrom 'Debian APT Testdisk amd64 0.8.15'
+mv rootdir/media/cdrom rootdir/media/cdrom-amd64
+addtrap 'prefix' "chmod -R +w $PWD/rootdir/media/cdrom-amd64/dists/;"
+chmod -R -w rootdir/media/cdrom-amd64/dists
+ln -s $PWD/rootdir/media/cdrom-amd64 $PWD/rootdir/media/cdrom
+aptcdrom add -m -o quiet=1
+rm $PWD/rootdir/media/cdrom
+# do it again to create a i386 cdrom
+sed -i 's#Architectures .*$#Architectures "i386 source";#' aptarchive/ftparchive.conf
+setupaptarchive --no-update
+changetocdrom 'Debian APT Testdisk i386 0.8.15'
+mv rootdir/media/cdrom rootdir/media/cdrom-i386
+addtrap 'prefix' "chmod -R +w $PWD/rootdir/media/cdrom-i386/dists/;"
+chmod -R -w rootdir/media/cdrom-i386/dists
+ln -s $PWD/rootdir/media/cdrom-i386 $PWD/rootdir/media/cdrom
+aptcdrom add -m -o quiet=1
+
+# play with the cdroms
+testdpkgnotinstalled testing
+aptget install testing -t stable -y #> /dev/null 2>&1
+testdpkginstalled testing
+
+testdpkgnotinstalled testing:i386
+aptget install testing:i386 -t stable -y #> /dev/null 2>&1
+testdpkginstalled testing:i386
+
+aptget dist-upgrade -y
--
cgit v1.2.3-70-g09d2
From 99359751efb1ad84e877219639030feb47fb28f7 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Sun, 16 Jun 2013 15:42:31 +0200
Subject: handle missing "Description" in apt-cache show
do not blindly assume that all packages stanzas have a "Description:"
field in 'apt-cache show' as well as in the cache creation itself.
We instead assume now that if the stanza has a Description, it will not
be the first field as we look out for "\nDescription" to take care of
MD5sum as well as (maybe ignored) translated Descriptions embedded in
the package stanza.
Closes: #712435
---
apt-pkg/deb/deblistparser.cc | 6 +-
apt-pkg/pkgcachegen.cc | 4 +-
cmdline/apt-cache.cc | 47 ++++++++----
debian/changelog | 1 +
.../test-bug-712435-missing-descriptions | 89 ++++++++++++++++++++++
5 files changed, 130 insertions(+), 17 deletions(-)
create mode 100755 test/integration/test-bug-712435-missing-descriptions
(limited to 'test')
diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc
index db86bd698..28857176b 100644
--- a/apt-pkg/deb/deblistparser.cc
+++ b/apt-pkg/deb/deblistparser.cc
@@ -219,8 +219,12 @@ MD5SumValue debListParser::Description_md5()
string const value = Section.FindS("Description-md5");
if (value.empty() == true)
{
+ std::string const desc = Description() + "\n";
+ if (desc == "\n")
+ return MD5SumValue();
+
MD5Summation md5;
- md5.Add((Description() + "\n").c_str());
+ md5.Add(desc.c_str());
return md5.Result();
}
else if (likely(value.size() == 32))
diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc
index 3f10b6c40..7ce7aba7b 100644
--- a/apt-pkg/pkgcachegen.cc
+++ b/apt-pkg/pkgcachegen.cc
@@ -296,6 +296,8 @@ bool pkgCacheGenerator::MergeListPackage(ListParser &List, pkgCache::PkgIterator
// Find the right version to write the description
MD5SumValue CurMd5 = List.Description_md5();
+ if (CurMd5.Value().empty() == true || List.Description().empty() == true)
+ return true;
std::string CurLang = List.DescriptionLanguage();
for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
@@ -480,7 +482,7 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
/* Record the Description (it is not translated) */
MD5SumValue CurMd5 = List.Description_md5();
- if (CurMd5.Value().empty() == true)
+ if (CurMd5.Value().empty() == true || List.Description().empty() == true)
return true;
std::string CurLang = List.DescriptionLanguage();
diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc
index bda09a5a1..fb4467c2c 100644
--- a/cmdline/apt-cache.cc
+++ b/cmdline/apt-cache.cc
@@ -1161,7 +1161,11 @@ bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
}
// Get a pointer to start of Description field
- const unsigned char *DescP = (unsigned char*)strstr((char*)Buffer, "Description:");
+ const unsigned char *DescP = (unsigned char*)strstr((char*)Buffer, "\nDescription");
+ if (DescP != NULL)
+ ++DescP;
+ else
+ DescP = Buffer + V.FileList()->Size;
// Write all but Description
if (fwrite(Buffer,1,DescP - Buffer,stdout) < (size_t)(DescP - Buffer))
@@ -1173,25 +1177,38 @@ bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
// Show the right description
pkgRecords Recs(*Cache);
pkgCache::DescIterator Desc = V.TranslatedDescription();
- pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
- cout << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc();
-
- // Find the first field after the description (if there is any)
- for(DescP++;DescP != &Buffer[V.FileList()->Size];DescP++)
+ if (Desc.end() == false)
{
- if(*DescP == '\n' && *(DescP+1) != ' ')
+ pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
+ cout << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc();
+ cout << std::endl << "Description-md5: " << Desc.md5() << std::endl;
+
+ // Find the first field after the description (if there is any)
+ while ((DescP = (unsigned char*)strchr((char*)DescP, '\n')) != NULL)
{
- // write the rest of the buffer
- const unsigned char *end=&Buffer[V.FileList()->Size];
- if (fwrite(DescP,1,end-DescP,stdout) < (size_t)(end-DescP))
- {
- delete [] Buffer;
- return false;
- }
+ if (DescP[1] == ' ')
+ DescP += 2;
+ else if (strncmp((char*)DescP, "\nDescription", strlen("\nDescription")) == 0)
+ DescP += strlen("\nDescription");
+ else
+ break;
+ }
+ if (DescP != NULL)
+ ++DescP;
+ }
+ // if we have no translation, we found a lonely Description-md5, so don't skip it
- break;
+ if (DescP != NULL)
+ {
+ // write the rest of the buffer
+ const unsigned char *end=&Buffer[V.FileList()->Size];
+ if (fwrite(DescP,1,end-DescP,stdout) < (size_t)(end-DescP))
+ {
+ delete [] Buffer;
+ return false;
}
}
+
// write a final newline (after the description)
cout< Sun, 09 Jun 2013 15:06:24 +0200
diff --git a/test/integration/test-bug-712435-missing-descriptions b/test/integration/test-bug-712435-missing-descriptions
new file mode 100755
index 000000000..9b3c2ee50
--- /dev/null
+++ b/test/integration/test-bug-712435-missing-descriptions
@@ -0,0 +1,89 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64'
+
+PACKAGESTANZA='Version: 0.9.7.8
+Installed-Size: 3270
+Maintainer: APT Development Team
+Architecture: amd64
+Filename: pool/main/a/apt/apt_0.9.7.8_amd64.deb
+MD5sum: 3a622acda41620df50aa22a9fac6f32e'
+
+DESCRIPTION='Description: commandline package manager
+ This APT has Super Cow Powers.'
+
+TRANSDESCRIPTION='Description-en: commandline package manager
+ This APT has translated Super Cow Powers.'
+
+echo "Package: apt-normal
+$PACKAGESTANZA
+$DESCRIPTION
+Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+
+Package: apt-both-below
+$PACKAGESTANZA
+$DESCRIPTION
+$TRANSDESCRIPTION
+Description-md5: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+
+Package: apt-both-middle
+$PACKAGESTANZA
+$DESCRIPTION
+Description-md5: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+$TRANSDESCRIPTION
+
+Package: apt-both-top
+$PACKAGESTANZA
+Description-md5: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+$DESCRIPTION
+$TRANSDESCRIPTION
+
+Package: apt-trans
+$PACKAGESTANZA
+$TRANSDESCRIPTION
+Description-md5: cccccccccccccccccccccccccccccccc
+
+Package: apt-md5
+$PACKAGESTANZA
+Description-md5: dddddddddddddddddddddddddddddddd
+
+Package: apt-none
+$PACKAGESTANZA" > aptarchive/Packages
+
+setupaptarchive
+
+testequal "Package: apt-normal
+$PACKAGESTANZA
+$DESCRIPTION
+Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+" aptcache show apt-normal
+
+# displaying the translated Description would be equally valid,
+# but we assume only one description is in a Packages file and
+# so we prefer "Description" over "Description-*" currently.
+for variant in 'below' 'middle' 'top'; do
+ testequal "Package: apt-both-$variant
+$PACKAGESTANZA
+$DESCRIPTION
+Description-md5: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+" aptcache show apt-both-$variant
+done
+
+testequal "Package: apt-trans
+$PACKAGESTANZA
+$TRANSDESCRIPTION
+Description-md5: cccccccccccccccccccccccccccccccc
+" aptcache show apt-trans
+
+testequal "Package: apt-md5
+$PACKAGESTANZA
+Description-md5: dddddddddddddddddddddddddddddddd
+" aptcache show apt-md5
+
+testequal "Package: apt-none
+$PACKAGESTANZA
+" aptcache show apt-none
--
cgit v1.2.3-70-g09d2
From fbd29dd60a195a5c252ba1d28366d52d60447560 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Sat, 15 Jun 2013 15:45:22 +0200
Subject: add a simple webserver for our testcases
APT needs to acquire data in a secure fashion over an inherently
unsecure way, known as the internet, while communicating with
unreliable partners, known as webservers and proxies.
For your integration tests we so far relied on 'normal' webservers,
but all of them have certain quirks and none is able to provide us
with all quirks which can be observed in the wild and we therefore
have to test with, so this webserver isn't trying to be fast, secure
or feature complete, but to provide all the quirks we need in a
consistent way.
This webserver also makes the APT project self-contained, as it is now
able to generate, serve as well as acquire package indexes. ;)
Git-Dch: Ignore
---
test/integration/framework | 19 +-
test/interactive-helper/aptwebserver.cc | 343 ++++++++++++++++++++++++++++++++
test/interactive-helper/makefile | 7 +
3 files changed, 363 insertions(+), 6 deletions(-)
create mode 100644 test/interactive-helper/aptwebserver.cc
(limited to 'test')
diff --git a/test/integration/framework b/test/integration/framework
index 5c50498a2..9db4a1017 100644
--- a/test/integration/framework
+++ b/test/integration/framework
@@ -718,12 +718,20 @@ signreleasefiles() {
}
changetowebserver() {
- if which weborf > /dev/null; then
- weborf -xb aptarchive/ 2>&1 > /dev/null &
+ local LOG='/dev/null'
+ if test -x ${BUILDDIRECTORY}/aptwebserver; then
+ cd aptarchive
+ LD_LIBRARY_PATH=${BUILDDIRECTORY} ${BUILDDIRECTORY}/aptwebserver "$@" >$LOG 2>&1 &
+ addtrap "kill $!;"
+ cd - > /dev/null
+ elif [ $# -gt 0 ]; then
+ msgdie 'Need the aptwebserver when passing arguments for the webserver'
+ elif which weborf > /dev/null; then
+ weborf -xb aptarchive/ >$LOG 2>&1 &
addtrap "kill $!;"
elif which gatling > /dev/null; then
cd aptarchive
- gatling -p 8080 -F -S 2>&1 > /dev/null &
+ gatling -p 8080 -F -S >$LOG 2>&1 &
addtrap "kill $!;"
cd - > /dev/null
elif which lighttpd > /dev/null; then
@@ -731,11 +739,10 @@ changetowebserver() {
server.port = 8080
server.stat-cache-engine = \"disable\"" > lighttpd.conf
lighttpd -t -f lighttpd.conf >/dev/null || msgdie 'Can not change to webserver: our lighttpd config is invalid'
- lighttpd -D -f lighttpd.conf 2>/dev/null >/dev/null &
+ lighttpd -D -f lighttpd.conf >$LOG 2>&1 &
addtrap "kill $!;"
else
- msgdie 'You have to install weborf or lighttpd first'
- return 1
+ msgdie 'You have to build aptwerbserver or install a webserver'
fi
local APTARCHIVE="file://$(readlink -f ./aptarchive)"
for LIST in $(find rootdir/etc/apt/sources.list.d/ -name 'apt-test-*.list'); do
diff --git a/test/interactive-helper/aptwebserver.cc b/test/interactive-helper/aptwebserver.cc
new file mode 100644
index 000000000..98bbde21b
--- /dev/null
+++ b/test/interactive-helper/aptwebserver.cc
@@ -0,0 +1,343 @@
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+char const * const httpcodeToStr(int const httpcode) /*{{{*/
+{
+ switch (httpcode)
+ {
+ // Informational 1xx
+ case 100: return "100 Continue";
+ case 101: return "101 Switching Protocols";
+ // Successful 2xx
+ case 200: return "200 OK";
+ case 201: return "201 Created";
+ case 202: return "202 Accepted";
+ case 203: return "203 Non-Authoritative Information";
+ case 204: return "204 No Content";
+ case 205: return "205 Reset Content";
+ case 206: return "206 Partial Content";
+ // Redirections 3xx
+ case 300: return "300 Multiple Choices";
+ case 301: return "301 Moved Permanently";
+ case 302: return "302 Found";
+ case 303: return "303 See Other";
+ case 304: return "304 Not Modified";
+ case 305: return "304 Use Proxy";
+ case 307: return "307 Temporary Redirect";
+ // Client errors 4xx
+ case 400: return "400 Bad Request";
+ case 401: return "401 Unauthorized";
+ case 402: return "402 Payment Required";
+ case 403: return "403 Forbidden";
+ case 404: return "404 Not Found";
+ case 405: return "405 Method Not Allowed";
+ case 406: return "406 Not Acceptable";
+ case 407: return "407 Proxy Authentication Required";
+ case 408: return "408 Request Time-out";
+ case 409: return "409 Conflict";
+ case 410: return "410 Gone";
+ case 411: return "411 Length Required";
+ case 412: return "412 Precondition Failed";
+ case 413: return "413 Request Entity Too Large";
+ case 414: return "414 Request-URI Too Large";
+ case 415: return "415 Unsupported Media Type";
+ case 416: return "416 Requested range not satisfiable";
+ case 417: return "417 Expectation Failed";
+ case 418: return "418 I'm a teapot";
+ // Server error 5xx
+ case 500: return "500 Internal Server Error";
+ case 501: return "501 Not Implemented";
+ case 502: return "502 Bad Gateway";
+ case 503: return "503 Service Unavailable";
+ case 504: return "504 Gateway Time-out";
+ case 505: return "505 HTTP Version not supported";
+ }
+ return NULL;
+}
+ /*}}}*/
+void addFileHeaders(std::list &headers, FileFd &data) /*{{{*/
+{
+ std::ostringstream contentlength;
+ contentlength << "Content-Length: " << data.FileSize();
+ headers.push_back(contentlength.str());
+
+ std::string lastmodified("Last-Modified: ");
+ lastmodified.append(TimeRFC1123(data.ModificationTime()));
+ headers.push_back(lastmodified);
+}
+ /*}}}*/
+void addDataHeaders(std::list &headers, std::string &data) /*{{{*/
+{
+ std::ostringstream contentlength;
+ contentlength << "Content-Length: " << data.size();
+ headers.push_back(contentlength.str());
+}
+ /*}}}*/
+bool sendHead(int const client, int const httpcode, std::list &headers)/*{{{*/
+{
+ std::string response("HTTP/1.1 ");
+ response.append(httpcodeToStr(httpcode));
+ headers.push_front(response);
+
+ headers.push_back("Server: APT webserver");
+
+ std::string date("Date: ");
+ date.append(TimeRFC1123(time(NULL)));
+ headers.push_back(date);
+
+ std::clog << ">>> RESPONSE >>>" << std::endl;
+ bool Success = true;
+ for (std::list::const_iterator h = headers.begin();
+ Success == true && h != headers.end(); ++h)
+ {
+ Success &= FileFd::Write(client, h->c_str(), h->size());
+ if (Success == true)
+ Success &= FileFd::Write(client, "\r\n", 2);
+ std::clog << *h << std::endl;
+ }
+ if (Success == true)
+ Success &= FileFd::Write(client, "\r\n", 2);
+ std::clog << "<<<<<<<<<<<<<<<<" << std::endl;
+ return Success;
+}
+ /*}}}*/
+bool sendFile(int const client, FileFd &data) /*{{{*/
+{
+ bool Success = true;
+ char buffer[500];
+ unsigned long long actual = 0;
+ while ((Success &= data.Read(buffer, sizeof(buffer), &actual)) == true)
+ {
+ if (actual == 0)
+ break;
+ if (Success == true)
+ Success &= FileFd::Write(client, buffer, actual);
+ }
+ if (Success == true)
+ Success &= FileFd::Write(client, "\r\n", 2);
+ return Success;
+}
+ /*}}}*/
+bool sendData(int const client, std::string const &data) /*{{{*/
+{
+ bool Success = true;
+ Success &= FileFd::Write(client, data.c_str(), data.size());
+ if (Success == true)
+ Success &= FileFd::Write(client, "\r\n", 2);
+ return Success;
+}
+ /*}}}*/
+void sendError(int const client, int const httpcode, std::string const &request,/*{{{*/
+ bool content, std::string const &error = "")
+{
+ std::list headers;
+ std::string response("");
+ response.append(httpcodeToStr(httpcode)).append("");
+ response.append("").append(httpcodeToStr(httpcode)).append("
");
+ if (error.empty() == false)
+ response.append("Error: ").append(error).append("
");
+ response.append("This error is a result of the request: ");
+ response.append(request).append("");
+ addDataHeaders(headers, response);
+ sendHead(client, httpcode, headers);
+ if (content == true)
+ sendData(client, response);
+}
+ /*}}}*/
+bool parseFirstLine(int const client, std::string const &request, /*{{{*/
+ std::string &filename, bool &sendContent,
+ bool &closeConnection)
+{
+ if (strncmp(request.c_str(), "HEAD ", 5) == 0)
+ sendContent = false;
+ if (strncmp(request.c_str(), "GET ", 4) != 0)
+ {
+ sendError(client, 501, request, true);
+ return false;
+ }
+
+ size_t const lineend = request.find('\n');
+ size_t filestart = request.find(' ');
+ for (; request[filestart] == ' '; ++filestart);
+ size_t fileend = request.rfind(' ', lineend);
+ if (lineend == std::string::npos || filestart == std::string::npos ||
+ fileend == std::string::npos || filestart == fileend)
+ {
+ sendError(client, 500, request, sendContent, "Filename can't be extracted");
+ return false;
+ }
+
+ size_t httpstart = fileend;
+ for (; request[httpstart] == ' '; ++httpstart);
+ if (strncmp(request.c_str() + httpstart, "HTTP/1.1\r", 9) == 0)
+ closeConnection = strcasecmp(LookupTag(request, "Connection", "Keep-Alive").c_str(), "Keep-Alive") != 0;
+ else if (strncmp(request.c_str() + httpstart, "HTTP/1.0\r", 9) == 0)
+ closeConnection = strcasecmp(LookupTag(request, "Connection", "Keep-Alive").c_str(), "close") == 0;
+ else
+ {
+ sendError(client, 500, request, sendContent, "Not a HTTP/1.{0,1} request");
+ return false;
+ }
+
+ filename = request.substr(filestart, fileend - filestart);
+ if (filename.find(' ') != std::string::npos)
+ {
+ sendError(client, 500, request, sendContent, "Filename contains an unencoded space");
+ return false;
+ }
+ filename = DeQuoteString(filename);
+
+ // this is not a secure server, but at least prevent the obvious …
+ if (filename.empty() == true || filename[0] != '/' ||
+ strncmp(filename.c_str(), "//", 2) == 0 ||
+ filename.find_first_of("\r\n\t\f\v") != std::string::npos ||
+ filename.find("/../") != std::string::npos)
+ {
+ sendError(client, 400, request, sendContent, "Filename contains illegal character (sequence)");
+ return false;
+ }
+
+ // nuke the first character which is a / as we assured above
+ filename.erase(0, 1);
+ if (filename.empty() == true)
+ filename = ".";
+ return true;
+}
+ /*}}}*/
+int main(int const argc, const char * argv[])
+{
+ CommandLine::Args Args[] = {
+ {0, "port", "aptwebserver::port", CommandLine::HasArg},
+ {'c',"config-file",0,CommandLine::ConfigFile},
+ {'o',"option",0,CommandLine::ArbItem},
+ {0,0,0,0}
+ };
+
+ CommandLine CmdL(Args, _config);
+ if(CmdL.Parse(argc,argv) == false)
+ {
+ _error->DumpErrors();
+ exit(1);
+ }
+
+ // create socket, bind and listen to it {{{
+ // ignore SIGPIPE, this can happen on write() if the socket closes connection
+ signal(SIGPIPE, SIG_IGN);
+ int sock = socket(AF_INET6, SOCK_STREAM, 0);
+ if(sock < 0)
+ {
+ _error->Errno("aptwerbserver", "Couldn't create socket");
+ _error->DumpErrors(std::cerr);
+ return 1;
+ }
+
+ int const port = _config->FindI("aptwebserver::port", 8080);
+
+ // ensure that we accept all connections: v4 or v6
+ int const iponly = 0;
+ setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &iponly, sizeof(iponly));
+ // to not linger on an address
+ int const enable = 1;
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
+
+ struct sockaddr_in6 locAddr;
+ memset(&locAddr, 0, sizeof(locAddr));
+ locAddr.sin6_family = AF_INET6;
+ locAddr.sin6_port = htons(port);
+ locAddr.sin6_addr = in6addr_any;
+
+ if (bind(sock, (struct sockaddr*) &locAddr, sizeof(locAddr)) < 0)
+ {
+ _error->Errno("aptwerbserver", "Couldn't bind");
+ _error->DumpErrors(std::cerr);
+ return 2;
+ }
+
+ std::clog << "Serving ANY file on port: " << port << std::endl;
+
+ listen(sock, 1);
+ /*}}}*/
+
+ std::vector messages;
+ int client;
+ while ((client = accept(sock, NULL, NULL)) != -1)
+ {
+ std::clog << "ACCEPT client " << client
+ << " on socket " << sock << std::endl;
+
+ while (ReadMessages(client, messages))
+ {
+ bool closeConnection = false;
+ for (std::vector::const_iterator m = messages.begin();
+ m != messages.end() && closeConnection == false; ++m) {
+ std::clog << ">>> REQUEST >>>>" << std::endl << *m
+ << std::endl << "<<<<<<<<<<<<<<<<" << std::endl;
+ std::list headers;
+ std::string filename;
+ bool sendContent = true;
+ if (parseFirstLine(client, *m, filename, sendContent, closeConnection) == false)
+ continue;
+
+ std::string host = LookupTag(*m, "Host", "");
+ if (host.empty() == true)
+ {
+ // RFC 2616 §14.23 requires Host
+ sendError(client, 400, *m, sendContent, "Host header is required");
+ continue;
+ }
+
+ if (RealFileExists(filename) == true)
+ {
+ FileFd data(filename, FileFd::ReadOnly);
+ std::string condition = LookupTag(*m, "If-Modified-Since", "");
+ if (condition.empty() == false)
+ {
+ time_t cache;
+ if (RFC1123StrToTime(condition.c_str(), cache) == true &&
+ cache >= data.ModificationTime())
+ {
+ sendHead(client, 304, headers);
+ continue;
+ }
+ }
+
+ addFileHeaders(headers, data);
+ sendHead(client, 200, headers);
+ if (sendContent == true)
+ sendFile(client, data);
+ }
+ else
+ sendError(client, 404, *m, sendContent);
+ }
+ _error->DumpErrors(std::cerr);
+ messages.clear();
+ if (closeConnection == true)
+ break;
+ }
+
+ std::clog << "CLOSE client " << client
+ << " on socket " << sock << std::endl;
+ close(client);
+ }
+ return 0;
+}
diff --git a/test/interactive-helper/makefile b/test/interactive-helper/makefile
index fa4f5fecb..f43df97e3 100644
--- a/test/interactive-helper/makefile
+++ b/test/interactive-helper/makefile
@@ -38,3 +38,10 @@ include $(PROGRAM_H)
#SLIBS = -lapt-pkg -lrpm
#SOURCE = rpmver.cc
#include $(PROGRAM_H)
+
+# Program for testing udevcdrom
+PROGRAM=aptwebserver
+SLIBS = -lapt-pkg
+LIB_MAKES = apt-pkg/makefile
+SOURCE = aptwebserver.cc
+include $(PROGRAM_H)
--
cgit v1.2.3-70-g09d2
From bf3daa15e9e744d9481d9e6d1e250b77d1f7b256 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Sat, 15 Jun 2013 16:45:12 +0200
Subject: add directory listing to the webserver
Git-Dch: Ignore
---
test/interactive-helper/aptwebserver.cc | 121 ++++++++++++++++++++++++++++++++
1 file changed, 121 insertions(+)
(limited to 'test')
diff --git a/test/interactive-helper/aptwebserver.cc b/test/interactive-helper/aptwebserver.cc
index 98bbde21b..d25f50624 100644
--- a/test/interactive-helper/aptwebserver.cc
+++ b/test/interactive-helper/aptwebserver.cc
@@ -13,12 +13,14 @@
#include
#include
+#include
#include
#include
#include
#include
#include
#include
+#include
#include
char const * const httpcodeToStr(int const httpcode) /*{{{*/
@@ -164,6 +166,118 @@ void sendError(int const client, int const httpcode, std::string const &request,
sendData(client, response);
}
/*}}}*/
+void sendRedirect(int const client, int const httpcode, std::string const &uri,/*{{{*/
+ std::string const &request, bool content)
+{
+ std::list headers;
+ std::string response("");
+ response.append(httpcodeToStr(httpcode)).append("");
+ response.append("").append(httpcodeToStr(httpcode)).append("
You should be redirected to ").append(uri).append("
");
+ response.append("This page is a result of the request: ");
+ response.append(request).append("");
+ addDataHeaders(headers, response);
+ std::string location("Location: ");
+ if (strncmp(uri.c_str(), "http://", 7) != 0)
+ location.append("http://").append(LookupTag(request, "Host")).append("/").append(uri);
+ else
+ location.append(uri);
+ headers.push_back(location);
+ sendHead(client, httpcode, headers);
+ if (content == true)
+ sendData(client, response);
+}
+ /*}}}*/
+int filter_hidden_files(const struct dirent *a) /*{{{*/
+{
+ if (a->d_name[0] == '.')
+ return 0;
+#ifdef _DIRENT_HAVE_D_TYPE
+ // if we have the d_type check that only files and dirs will be included
+ if (a->d_type != DT_UNKNOWN &&
+ a->d_type != DT_REG &&
+ a->d_type != DT_LNK && // this includes links to regular files
+ a->d_type != DT_DIR)
+ return 0;
+#endif
+ return 1;
+}
+int grouped_alpha_case_sort(const struct dirent **a, const struct dirent **b) {
+#ifdef _DIRENT_HAVE_D_TYPE
+ if ((*a)->d_type == DT_DIR && (*b)->d_type == DT_DIR);
+ else if ((*a)->d_type == DT_DIR && (*b)->d_type == DT_REG)
+ return -1;
+ else if ((*b)->d_type == DT_DIR && (*a)->d_type == DT_REG)
+ return 1;
+ else
+#endif
+ {
+ struct stat f_prop; //File's property
+ stat((*a)->d_name, &f_prop);
+ int const amode = f_prop.st_mode;
+ stat((*b)->d_name, &f_prop);
+ int const bmode = f_prop.st_mode;
+ if (S_ISDIR(amode) && S_ISDIR(bmode));
+ else if (S_ISDIR(amode))
+ return -1;
+ else if (S_ISDIR(bmode))
+ return 1;
+ }
+ return strcasecmp((*a)->d_name, (*b)->d_name);
+}
+ /*}}}*/
+void sendDirectoryListing(int const client, std::string const &dir, /*{{{*/
+ std::string const &request, bool content)
+{
+ std::list headers;
+ std::ostringstream listing;
+
+ struct dirent **namelist;
+ int const counter = scandir(dir.c_str(), &namelist, filter_hidden_files, grouped_alpha_case_sort);
+ if (counter == -1)
+ {
+ sendError(client, 500, request, content);
+ return;
+ }
+
+ listing << "Index of " << dir << ""
+ << ""
+ << "" << std::endl
+ << "Index of " << dir << "
" << std::endl
+ << "| # | Name | Size | Last-Modified |
" << std::endl;
+ if (dir != ".")
+ listing << "| d | Parent Directory | - | - |
";
+ for (int i = 0; i < counter; ++i) {
+ struct stat fs;
+ std::string filename(dir);
+ filename.append("/").append(namelist[i]->d_name);
+ stat(filename.c_str(), &fs);
+ if (S_ISDIR(fs.st_mode))
+ {
+ listing << "| d | "
+ << "d_name << "/\">" << namelist[i]->d_name << " | "
+ << "- | ";
+ }
+ else
+ {
+ listing << "
| f | "
+ << "d_name << "\">" << namelist[i]->d_name << " | "
+ << "" << SizeToStr(fs.st_size) << "B | ";
+ }
+ listing << "" << TimeRFC1123(fs.st_mtime) << " |
" << std::endl;
+ }
+ listing << "
" << std::endl;
+
+ std::string response(listing.str());
+ addDataHeaders(headers, response);
+ sendHead(client, 200, headers);
+ if (content == true)
+ sendData(client, response);
+}
+ /*}}}*/
bool parseFirstLine(int const client, std::string const &request, /*{{{*/
std::string &filename, bool &sendContent,
bool &closeConnection)
@@ -326,6 +440,13 @@ int main(int const argc, const char * argv[])
if (sendContent == true)
sendFile(client, data);
}
+ else if (DirectoryExists(filename) == true)
+ {
+ if (filename == "." || filename[filename.length()-1] == '/')
+ sendDirectoryListing(client, filename, *m, sendContent);
+ else
+ sendRedirect(client, 301, filename.append("/"), *m, sendContent);
+ }
else
sendError(client, 404, *m, sendContent);
}
--
cgit v1.2.3-70-g09d2
From 7ea27d2a6d10ee41f8fca5d8ad7373c8b3d90ea9 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Sat, 15 Jun 2013 23:58:12 +0200
Subject: simple URI rewrite rules config for webserver
we have a test which required traditionally lighttpd to be executed
as it requires a webserver supporting some kind of URI rewriting.
Now with some lines of code our own webserver can do this and the
testcase can be enabled by default. This test hinted at the bug fixed
in the previous commit, so having more tests which can easily be run
is a good thing.
Git-Dch: Ignore
---
test/integration/skip-bug-602412-dequote-redirect | 38 -----------------------
test/integration/test-bug-602412-dequote-redirect | 29 +++++++++++++++++
test/interactive-helper/aptwebserver.cc | 16 ++++++++++
3 files changed, 45 insertions(+), 38 deletions(-)
delete mode 100755 test/integration/skip-bug-602412-dequote-redirect
create mode 100755 test/integration/test-bug-602412-dequote-redirect
(limited to 'test')
diff --git a/test/integration/skip-bug-602412-dequote-redirect b/test/integration/skip-bug-602412-dequote-redirect
deleted file mode 100755
index 689b671ce..000000000
--- a/test/integration/skip-bug-602412-dequote-redirect
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/sh
-set -e
-
-TESTDIR=$(readlink -f $(dirname $0))
-. $TESTDIR/framework
-setupenvironment
-configarchitecture 'i386'
-
-if ! which lighttpd > /dev/null; then
- msgdie 'You need lighttpd for this testcase, sorry…'
- exit 1
-fi
-
-buildsimplenativepackage 'unrelated' 'all' '0.5~squeeze1' 'unstable'
-
-setupaptarchive
-
-echo "server.modules = ( \"mod_redirect\" )
-server.document-root = \"$(readlink -f ./aptarchive)\"
-server.port = 8080
-server.stat-cache-engine = \"disable\"
-url.redirect = ( \"^/pool/(.*)$\" => \"/newpool/\$1\",
- \"^/dists/(.*)$\" => \"/newdists/\$1\" )" > lighttpd.conf
-
-mv aptarchive/pool aptarchive/newpool
-mv aptarchive/dists aptarchive/newdists
-
-lighttpd -t -f lighttpd.conf >/dev/null || msgdie 'Can not change to webserver: our lighttpd config is invalid'
-lighttpd -D -f lighttpd.conf 2>/dev/null >/dev/null &
-addtrap "kill $!;"
-
-APTARCHIVE="file://$(readlink -f ./aptarchive)"
-for LIST in $(find rootdir/etc/apt/sources.list.d/ -name 'apt-test-*.list'); do
- sed -i $LIST -e "s#$APTARCHIVE#http://localhost:8080/#"
-done
-
-aptget update || msgdie 'apt-get update failed'
-aptget install unrelated --download-only || msgdie 'downloading package failed'
diff --git a/test/integration/test-bug-602412-dequote-redirect b/test/integration/test-bug-602412-dequote-redirect
new file mode 100755
index 000000000..c20443559
--- /dev/null
+++ b/test/integration/test-bug-602412-dequote-redirect
@@ -0,0 +1,29 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64'
+
+buildsimplenativepackage 'unrelated' 'all' '0.5~squeeze1' 'unstable'
+
+setupaptarchive
+changetowebserver -o aptwebserver::redirect::replace::/pool/=/newpool/ \
+ -o aptwebserver::redirect::replace::/dists/=/newdists/
+
+mv aptarchive/pool aptarchive/newpool
+mv aptarchive/dists aptarchive/newdists
+
+msgtest 'Test redirection works in' 'apt-get update'
+aptget update -qq && msgpass || msgfail
+
+# check that I-M-S header is kept in redirections
+testequal 'Hit http://localhost:8080 unstable InRelease
+Hit http://localhost:8080 unstable/main Sources
+Hit http://localhost:8080 unstable/main amd64 Packages
+Hit http://localhost:8080 unstable/main Translation-en
+Reading package lists...' aptget update #-o debug::pkgacquire=1 -o debug::pkgacquire::worker=1
+
+msgtest 'Test redirection works in' 'package download'
+aptget install unrelated --download-only -qq && msgpass || msgfail
diff --git a/test/interactive-helper/aptwebserver.cc b/test/interactive-helper/aptwebserver.cc
index d25f50624..de235fa05 100644
--- a/test/interactive-helper/aptwebserver.cc
+++ b/test/interactive-helper/aptwebserver.cc
@@ -420,6 +420,22 @@ int main(int const argc, const char * argv[])
continue;
}
+ // string replacements in the requested filename
+ ::Configuration::Item const *Replaces = _config->Tree("aptwebserver::redirect::replace");
+ if (Replaces != NULL)
+ {
+ std::string redirect = "/" + filename;
+ for (::Configuration::Item *I = Replaces->Child; I != NULL; I = I->Next)
+ redirect = SubstVar(redirect, I->Tag, I->Value);
+ redirect.erase(0,1);
+ if (redirect != filename)
+ {
+ sendRedirect(client, 301, redirect, *m, sendContent);
+ continue;
+ }
+ }
+
+ // deal with the request
if (RealFileExists(filename) == true)
{
FileFd data(filename, FileFd::ReadOnly);
--
cgit v1.2.3-70-g09d2
From 5229b285f07edd5ed695c264c8d80310f339af96 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Sun, 16 Jun 2013 23:23:28 +0200
Subject: tests: accept an explaination for msgfail
Git-Dch: Ignore
---
test/integration/framework | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
(limited to 'test')
diff --git a/test/integration/framework b/test/integration/framework
index 9db4a1017..3f11ac23b 100644
--- a/test/integration/framework
+++ b/test/integration/framework
@@ -38,7 +38,11 @@ msgtest() {
}
msgpass() { echo "${CPASS}PASS${CNORMAL}" >&2; }
msgskip() { echo "${CWARNING}SKIP${CNORMAL}" >&2; }
-msgfail() { echo "${CFAIL}FAIL${CNORMAL}" >&2; EXIT_CODE=$((EXIT_CODE+1)); }
+msgfail() {
+ if [ $# -gt 0 ]; then echo "${CFAIL}FAIL: $*${CNORMAL}" >&2;
+ else echo "${CFAIL}FAIL${CNORMAL}" >&2; fi
+ EXIT_CODE=$((EXIT_CODE+1));
+}
# enable / disable Debugging
MSGLEVEL=${MSGLEVEL:-3}
@@ -56,9 +60,9 @@ if [ $MSGLEVEL -le 2 ]; then
msgpass() { echo -n " ${CPASS}P${CNORMAL}" >&2; }
msgskip() { echo -n " ${CWARNING}S${CNORMAL}" >&2; }
if [ -n "$CFAIL" ]; then
- msgfail() { echo -n " ${CFAIL}FAIL${CNORMAL}" >&2; }
+ msgfail() { echo -n " ${CFAIL}FAIL${CNORMAL}" >&2; EXIT_CODE=$((EXIT_CODE+1)); }
else
- msgfail() { echo -n " ###FAILED###" >&2; }
+ msgfail() { echo -n " ###FAILED###" >&2; EXIT_CODE=$((EXIT_CODE+1)); }
fi
fi
if [ $MSGLEVEL -le 3 ]; then
--
cgit v1.2.3-70-g09d2
From ae99ce2e3cadb07c80b89ab2afc804875b1026c5 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Mon, 17 Jun 2013 11:23:13 +0200
Subject: trigger NODATA error for invalid InRelease files
With the selfgrown splitting we got the problem of not recovering
from networks which just reply with invalid data like those sending
us login pages to authenticate with the network (e.g. hotels) back.
The good thing about the InRelease file is that we know that it must
be clearsigned (a Release file might or might not have a detached sig)
so if we get a file but are unable to split it something is seriously
wrong, so there is not much point in trying further.
The Acquire system already looks out for a NODATA error from gpgv,
so this adds a new error message sent to the acquire system in case
the splitting we do now ourselves failed including this magic word.
Closes: #712486
---
apt-pkg/contrib/gpgv.cc | 2 +-
apt-pkg/contrib/gpgv.h | 15 ++++-
debian/changelog | 1 +
methods/gpgv.cc | 16 +++---
test/integration/framework | 3 +
.../test-ubuntu-bug-346386-apt-get-update-paywall | 64 ++++++++++++++++++++++
test/interactive-helper/aptwebserver.cc | 26 +++++++++
7 files changed, 114 insertions(+), 13 deletions(-)
create mode 100755 test/integration/test-ubuntu-bug-346386-apt-get-update-paywall
(limited to 'test')
diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc
index 31db7d5fe..f47e7ea48 100644
--- a/apt-pkg/contrib/gpgv.cc
+++ b/apt-pkg/contrib/gpgv.cc
@@ -154,7 +154,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
if (sigFd != -1)
unlink(data);
ioprintf(std::cerr, "Splitting up %s into data and signature failed", File.c_str());
- exit(EINTERNAL);
+ exit(112);
}
Args.push_back(sig);
Args.push_back(data);
diff --git a/apt-pkg/contrib/gpgv.h b/apt-pkg/contrib/gpgv.h
index 08b10a97a..45f069058 100644
--- a/apt-pkg/contrib/gpgv.h
+++ b/apt-pkg/contrib/gpgv.h
@@ -23,9 +23,18 @@
/** \brief generates and run the command to verify a file with gpgv
*
* If File and FileSig specify the same file it is assumed that we
- * deal with a clear-signed message. In that case the file will be
- * rewritten to be in a good-known format without uneeded whitespaces
- * and additional messages (unsigned or signed).
+ * deal with a clear-signed message. Note that the method will accept
+ * and validate files which include additional (unsigned) messages
+ * without complaining. Do NOT open files accepted by this method
+ * for reading. Use #OpenMaybeClearSignedFile to access the message
+ * instead to ensure you are only reading signed data.
+ *
+ * The method does not return, but has some noteable exit-codes:
+ * 111 signals an internal error like the inability to execute gpgv,
+ * 112 indicates a clear-signed file which doesn't include a message,
+ * which can happen if APT is run while on a network requiring
+ * authentication before usage (e.g. in hotels)
+ * All other exit-codes are passed-through from gpgv.
*
* @param File is the message (unsigned or clear-signed)
* @param FileSig is the signature (detached or clear-signed)
diff --git a/debian/changelog b/debian/changelog
index 91d4ae536..bd25df1e2 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -20,6 +20,7 @@ apt (0.9.8.3) UNRELEASED; urgency=low
* try defaults if auto-detection failed in apt-cdrom (Closes: #712433)
* support \n and \r\n line endings in ReadMessages
* do not redownload unchanged InRelease files
+ * trigger NODATA error for invalid InRelease files (Closes: #712486)
-- David Kalnischkies Sun, 09 Jun 2013 15:06:24 +0200
diff --git a/methods/gpgv.cc b/methods/gpgv.cc
index 3f814b9f0..fe8bac6c9 100644
--- a/methods/gpgv.cc
+++ b/methods/gpgv.cc
@@ -55,9 +55,6 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
vector &NoPubKeySigners)
{
bool const Debug = _config->FindB("Debug::Acquire::gpgv", false);
- // setup a (empty) stringstream for formating the return value
- std::stringstream ret;
- ret.str("");
if (Debug == true)
std::clog << "inside VerifyGetSigners" << std::endl;
@@ -170,18 +167,19 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
return "";
}
else if (WEXITSTATUS(status) == 1)
- {
return _("At least one invalid signature was encountered.");
- }
else if (WEXITSTATUS(status) == 111)
+ return _("Could not execute 'gpgv' to verify signature (is gpgv installed?)");
+ else if (WEXITSTATUS(status) == 112)
{
- ioprintf(ret, _("Could not execute 'gpgv' to verify signature (is gpgv installed?)"));
- return ret.str();
+ // acquire system checks for "NODATA" to generate GPG errors (the others are only warnings)
+ std::string errmsg;
+ //TRANSLATORS: %s is a single techy word like 'NODATA'
+ strprintf(errmsg, _("Clearsigned file isn't valid, got '%s' (does the network require authentication?)"), "NODATA");
+ return errmsg;
}
else
- {
return _("Unknown error executing gpgv");
- }
}
bool GPGVMethod::Fetch(FetchItem *Itm)
diff --git a/test/integration/framework b/test/integration/framework
index 3f11ac23b..3a02cfb76 100644
--- a/test/integration/framework
+++ b/test/integration/framework
@@ -118,6 +118,9 @@ gdb() {
echo "gdb: run »$*«"
APT_CONFIG=aptconfig.conf LD_LIBRARY_PATH=${BUILDDIRECTORY} $(which gdb) ${BUILDDIRECTORY}/$1
}
+http() {
+ LD_LIBRARY_PATH=${BUILDDIRECTORY} ${BUILDDIRECTORY}/methods/http
+}
exitwithstatus() {
# error if we about to overflow, but ...
diff --git a/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall b/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall
new file mode 100755
index 000000000..1576c396c
--- /dev/null
+++ b/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall
@@ -0,0 +1,64 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture 'native'
+
+insertpackage 'unstable' 'unrelated' 'all' '1.0' 'stable'
+insertsource 'unstable' 'unrelated' 'all' '1.0' 'stable'
+
+echo 'ni ni ni' > aptarchive/knights
+
+setupaptarchive
+changetowebserver -o 'aptwebserver::overwrite::.*::filename=/knights'
+
+msgtest 'Acquire test file from the webserver to check' 'overwrite'
+echo '601 Configuration
+Config-Item: Acquire::http::DependOnSTDIN=0
+
+600 Acquire URI
+URI: http://localhost:8080/holygrail
+Filename: knights-talking
+' | http >/dev/null 2>&1 && msgpass || msgfail
+testfileequal knights-talking 'ni ni ni'
+
+ensure_n_canary_strings_in_dir() {
+ local DIR="$1"
+ local CANARY_STRING="$2"
+ local EXPECTED_N="$3"
+
+ msgtest "Testing in $DIR for $EXPECTED_N canary" "$CANARY_STRING"
+ local N=$(grep "$CANARY_STRING" $DIR/* 2>/dev/null |wc -l )
+ test "$N" = "$EXPECTED_N" && msgpass || msgfail "Expected $EXPECTED_N canaries, got $N"
+}
+
+LISTS='rootdir/var/lib/apt/lists'
+rm -rf rootdir/var/lib/apt/lists
+msgtest 'Got expected NODATA failure in' 'apt-get update'
+aptget update -qq 2>&1 | grep -q 'E: GPG error.*NODATA' && msgpass || msgfail
+
+ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0
+testequal 'partial' ls $LISTS
+
+# and again with pre-existing files with "valid data" which should remain
+for f in Release Release.gpg main_binary-amd64_Packages main_source_Sources; do
+ echo 'peng neee-wom' > $LISTS/localhost:8080_dists_stable_${f}
+done
+
+msgtest 'Got expected NODATA failure in' 'apt-get update'
+aptget update -qq 2>&1 | grep -q 'E: GPG error.*NODATA' && msgpass || msgfail
+
+ensure_n_canary_strings_in_dir $LISTS 'peng neee-wom' 4
+ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0
+
+# and now with a pre-existing InRelease file
+echo 'peng neee-wom' > $LISTS/localhost:8080_dists_stable_InRelease
+rm -f $LISTS/localhost:8080_dists_stable_Release $LISTS/localhost:8080_dists_stable_Release.gpg
+msgtest 'excpected failure of' 'apt-get update'
+aptget update -qq 2>&1 | grep -q 'E: GPG error.*NODATA' && msgpass || msgfail
+
+ensure_n_canary_strings_in_dir $LISTS 'peng neee-wom' 3
+ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0
diff --git a/test/interactive-helper/aptwebserver.cc b/test/interactive-helper/aptwebserver.cc
index de235fa05..05b875673 100644
--- a/test/interactive-helper/aptwebserver.cc
+++ b/test/interactive-helper/aptwebserver.cc
@@ -435,6 +435,32 @@ int main(int const argc, const char * argv[])
}
}
+ ::Configuration::Item const *Overwrite = _config->Tree("aptwebserver::overwrite");
+ if (Overwrite != NULL)
+ {
+ for (::Configuration::Item *I = Overwrite->Child; I != NULL; I = I->Next)
+ {
+ regex_t *pattern = new regex_t;
+ int const res = regcomp(pattern, I->Tag.c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB);
+ if (res != 0)
+ {
+ char error[300];
+ regerror(res, pattern, error, sizeof(error));
+ sendError(client, 500, *m, sendContent, error);
+ continue;
+ }
+ if (regexec(pattern, filename.c_str(), 0, 0, 0) == 0)
+ {
+ filename = _config->Find("aptwebserver::overwrite::" + I->Tag + "::filename", filename);
+ if (filename[0] == '/')
+ filename.erase(0,1);
+ regfree(pattern);
+ break;
+ }
+ regfree(pattern);
+ }
+ }
+
// deal with the request
if (RealFileExists(filename) == true)
{
--
cgit v1.2.3-70-g09d2
From e3c62328abbd548bb0da42fdbad954b3ce4f7102 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Mon, 24 Jun 2013 16:34:38 +0200
Subject: simple fork and pidfile aptwebserver
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Forking only after being ready to accept clients avoids running races
with the tests which sometimes failed on the first 'apt-get update'
(or similar) with the previous background-start and hope for the best…
The commit fixes also some oversight output-order changes in regards to
Description-md5 and (I-M-S) race conditions in various tests.
Git-Dch: Ignore
---
test/integration/Packages-pdiff-usage | 2 ++
test/integration/Packages-pdiff-usage-new | 2 ++
test/integration/Packages-releasefile-verification | 1 +
.../Packages-releasefile-verification-new | 1 +
test/integration/framework | 18 ++++++++---
.../test-bug-590041-prefer-non-virtual-packages | 2 ++
.../test-bug-601016-description-translation | 31 +++++++++++-------
.../test-cve-2013-1051-InRelease-parsing | 2 +-
test/integration/test-pdiff-usage | 2 +-
test/integration/test-releasefile-verification | 4 +--
test/interactive-helper/aptwebserver.cc | 37 ++++++++++++++++++++++
11 files changed, 83 insertions(+), 19 deletions(-)
(limited to 'test')
diff --git a/test/integration/Packages-pdiff-usage b/test/integration/Packages-pdiff-usage
index d1530a95c..ac962f29a 100644
--- a/test/integration/Packages-pdiff-usage
+++ b/test/integration/Packages-pdiff-usage
@@ -19,6 +19,7 @@ Description: Advanced front-end for dpkg
.
APT features complete installation ordering, multiple source capability
and several other unique features, see the Users Guide in apt-doc.
+Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c
Package: oldstuff
Version: 1.0
@@ -32,3 +33,4 @@ SHA1: 3c695e028f74d5c544deeddaaa1242desa81088c
SHA256: b46fd1546151c545fe4bfa56a5cc0e7deaef23e2da3e4f129727fd660f28f050
Description: some cool but old stuff
This package will disappear in the next mirror update
+Description-md5: 1948af60eda0a41dfa9fe83f60eb8389
diff --git a/test/integration/Packages-pdiff-usage-new b/test/integration/Packages-pdiff-usage-new
index 4f374b37f..f8d7b1958 100644
--- a/test/integration/Packages-pdiff-usage-new
+++ b/test/integration/Packages-pdiff-usage-new
@@ -22,6 +22,7 @@ Description: Advanced front-end for dpkg
.
APT features complete installation ordering, multiple source capability
and several other unique features, see the Users Guide in apt-doc.
+Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c
Package: newstuff
Version: 1.0
@@ -35,3 +36,4 @@ SHA1: 3c695e028f7a1ae324deeddaaa1242desa81088c
SHA256: b46fd154615edefab321cc56a5cc0e7deaef23e2da3e4f129727fd660f28f050
Description: some cool and shiny new stuff
This package will appear in the next mirror update
+Description-md5: d5f89fbbc2ac69c43d7e4c9b67d82b6b
diff --git a/test/integration/Packages-releasefile-verification b/test/integration/Packages-releasefile-verification
index 29a385f4f..eb7327279 100644
--- a/test/integration/Packages-releasefile-verification
+++ b/test/integration/Packages-releasefile-verification
@@ -16,3 +16,4 @@ Description: Advanced front-end for dpkg
.
APT features complete installation ordering, multiple source capability
and several other unique features, see the Users Guide in apt-doc.
+Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c
diff --git a/test/integration/Packages-releasefile-verification-new b/test/integration/Packages-releasefile-verification-new
index e3b2edf1f..61509d157 100644
--- a/test/integration/Packages-releasefile-verification-new
+++ b/test/integration/Packages-releasefile-verification-new
@@ -19,3 +19,4 @@ Description: Advanced front-end for dpkg
.
APT features complete installation ordering, multiple source capability
and several other unique features, see the Users Guide in apt-doc.
+Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c
diff --git a/test/integration/framework b/test/integration/framework
index 3a02cfb76..7dd7c20a7 100644
--- a/test/integration/framework
+++ b/test/integration/framework
@@ -605,9 +605,12 @@ buildaptarchivefromfiles() {
cat ${line} | bzip2 > ${line}.bz2
cat ${line} | xz --format=lzma > ${line}.lzma
cat ${line} | xz > ${line}.xz
+ if [ -n "$1" ]; then
+ touch -d "$1" ${line}.gz ${line}.bz2 ${line}.lzma ${line}.xz
+ fi
msgdone "info"
done
- generatereleasefiles
+ generatereleasefiles "$@"
}
# can be overridden by testcases for their pleasure
@@ -719,7 +722,10 @@ signreleasefiles() {
done
for RELEASE in $(find aptarchive/ -name Release); do
gpg --yes --no-default-keyring $SECKEYS $PUBKEYS --default-key "$SIGNER" -abs -o ${RELEASE}.gpg ${RELEASE}
- gpg --yes --no-default-keyring $SECKEYS $PUBKEYS --default-key "$SIGNER" --clearsign -o "$(echo "${RELEASE}" | sed 's#/Release$#/InRelease#')" $RELEASE
+ local INRELEASE="$(echo "${RELEASE}" | sed 's#/Release$#/InRelease#')"
+ gpg --yes --no-default-keyring $SECKEYS $PUBKEYS --default-key "$SIGNER" --clearsign -o $INRELEASE $RELEASE
+ # we might have set a specific date for the Release file, so copy it
+ touch -d "$(stat --format "%y" ${RELEASE})" ${RELEASE}.gpg ${INRELEASE}
done
msgdone "info"
}
@@ -728,8 +734,12 @@ changetowebserver() {
local LOG='/dev/null'
if test -x ${BUILDDIRECTORY}/aptwebserver; then
cd aptarchive
- LD_LIBRARY_PATH=${BUILDDIRECTORY} ${BUILDDIRECTORY}/aptwebserver "$@" >$LOG 2>&1 &
- addtrap "kill $!;"
+ LD_LIBRARY_PATH=${BUILDDIRECTORY} ${BUILDDIRECTORY}/aptwebserver -o aptwebserver::fork=1 "$@" >$LOG 2>&1
+ local PID="$(cat aptwebserver.pid)"
+ if [ -z "$PID" ]; then
+ msgdie 'Could not fork aptwebserver successfully'
+ fi
+ addtrap "kill $PID;"
cd - > /dev/null
elif [ $# -gt 0 ]; then
msgdie 'Need the aptwebserver when passing arguments for the webserver'
diff --git a/test/integration/test-bug-590041-prefer-non-virtual-packages b/test/integration/test-bug-590041-prefer-non-virtual-packages
index e0dd7737f..0ce4c1413 100755
--- a/test/integration/test-bug-590041-prefer-non-virtual-packages
+++ b/test/integration/test-bug-590041-prefer-non-virtual-packages
@@ -9,6 +9,7 @@ pkglibc6="Package: libc6
Architecture: armel
Version: 2.11.2-2~0.3
Description: Embedded GNU C Library: Shared libraries
+Description-md5: b8c1e0561b75e2dc6b6482a99079c3e4
Filename: pool/main/e/eglibc/libc6_2.11.2-2_armel.deb
Installed-Size: 9740
MD5sum: f5b878ce5fb8aa01a7927fa1460df537
@@ -25,6 +26,7 @@ Architecture: i386
Version: 2.1.3-13~0.3
Replaces: libc6 (<< 2.2.5-13~0.3)
Description: The Berkeley database routines [glibc 2.0/2.1 compatibility]
+Description-md5: de1876f7fe7f7709a110875e145e38a8
Filename: pool/main/d/db1-compat/libdb1-compat_2.1.3-13_armel.deb
Installed-Size: 136
MD5sum: 4043f176ab2b40b0c01bc1211b8c103c
diff --git a/test/integration/test-bug-601016-description-translation b/test/integration/test-bug-601016-description-translation
index 03fddbfda..33c209e9d 100755
--- a/test/integration/test-bug-601016-description-translation
+++ b/test/integration/test-bug-601016-description-translation
@@ -9,8 +9,9 @@ configarchitecture 'i386' 'amd64'
# we need a valid locale here, otherwise the language configuration
# will be overridden by LC_ALL=C
LOCALE="$(echo "$LANG" | cut -d'_' -f 1)"
+MD5Sum='Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c'
-PACKAGESTANZA="Package: apt
+PACKAGESTANZA='Package: apt
Priority: important
Section: admin
Installed-Size: 5984
@@ -19,8 +20,7 @@ Architecture: i386
Version: 0.8.7
Filename: pool/main/a/apt/apt_0.8.7_i386.deb
Size: 2140230
-MD5sum: 74769bfbcef9ebc4fa74f7a5271b9c08
-Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c"
+MD5sum: 74769bfbcef9ebc4fa74f7a5271b9c08'
PACKAGESTANZA2='Package: apt
Priority: important
@@ -31,22 +31,23 @@ Architecture: amd64
Version: 0.8.7
Filename: pool/main/a/apt/apt_0.8.7_amd64.deb
Size: 2210342
-MD5sum: 4a869bfbdef9ebc9fa74f7a5271e8d1a
-Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c'
+MD5sum: 4a869bfbdef9ebc9fa74f7a5271e8d1a'
echo "$PACKAGESTANZA
Description: Advanced front-end for dpkg
+$MD5Sum
$PACKAGESTANZA2
-Description: Advanced front-end for dpkg" > aptarchive/Packages
+Description: Advanced front-end for dpkg
+$MD5Sum" > aptarchive/Packages
echo "Package: apt
-Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c
Description-${LOCALE}: Mächtige Oberfläche für dpkg
Das Paket bietet dem Nutzer technisch führende Methoden für den Zugriff
auf den dpkg-Paketmanager. Es beinhaltet das apt-get-Werkzeug und die
APT-Dselect-Methode. Beides sind einfache und sicherere Wege,
- um Pakete zu installieren und Upgrades durchzuführen." | bzip2 > aptarchive/${LOCALE}.bz2
+ um Pakete zu installieren und Upgrades durchzuführen.
+$MD5Sum" | bzip2 > aptarchive/${LOCALE}.bz2
# the $LOCALE translation file will not be included as it is a flat archive it came from and therefore
# its name can not be guessed correctly… (in non-flat archives the files are called Translation-*)
@@ -54,10 +55,12 @@ echo 'APT::Cache::Generate "false";' > rootdir/etc/apt/apt.conf.d/00nogenerate
NOLONGSTANZA="$PACKAGESTANZA
Description: Advanced front-end for dpkg
+$MD5Sum
"
ENGLISHSTANZA="$PACKAGESTANZA
Description: Advanced front-end for dpkg
+$MD5Sum
"
LOCALESTANZA="$PACKAGESTANZA
@@ -66,6 +69,7 @@ Description-${LOCALE}: Mächtige Oberfläche für dpkg
auf den dpkg-Paketmanager. Es beinhaltet das apt-get-Werkzeug und die
APT-Dselect-Methode. Beides sind einfache und sicherere Wege,
um Pakete zu installieren und Upgrades durchzuführen.
+$MD5Sum
"
LOCALESTANZA2="$PACKAGESTANZA2
Description-${LOCALE}: Mächtige Oberfläche für dpkg
@@ -73,6 +77,7 @@ Description-${LOCALE}: Mächtige Oberfläche für dpkg
auf den dpkg-Paketmanager. Es beinhaltet das apt-get-Werkzeug und die
APT-Dselect-Methode. Beides sind einfache und sicherere Wege,
um Pakete zu installieren und Upgrades durchzuführen.
+$MD5Sum
"
testrun() {
@@ -97,28 +102,32 @@ testrun
echo "$PACKAGESTANZA
Description: Advanced front-end for dpkg
+$MD5Sum
$PACKAGESTANZA2
-Description: Advanced front-end for dpkg" > aptarchive/Packages
+Description: Advanced front-end for dpkg
+$MD5Sum" > aptarchive/Packages
echo "Package: apt
-Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c
Description-en: Advanced front-end for dpkg
This is Debian's next generation front-end for the dpkg package manager.
It provides the apt-get utility and APT dselect method that provides a
- simpler, safer way to install and upgrade packages." | bzip2 > aptarchive/en.bz2
+ simpler, safer way to install and upgrade packages.
+$MD5Sum" | bzip2 > aptarchive/en.bz2
ENGLISHSTANZA="$PACKAGESTANZA
Description-en: Advanced front-end for dpkg
This is Debian's next generation front-end for the dpkg package manager.
It provides the apt-get utility and APT dselect method that provides a
simpler, safer way to install and upgrade packages.
+$MD5Sum
"
ENGLISHSTANZA2="$PACKAGESTANZA2
Description-en: Advanced front-end for dpkg
This is Debian's next generation front-end for the dpkg package manager.
It provides the apt-get utility and APT dselect method that provides a
simpler, safer way to install and upgrade packages.
+$MD5Sum
"
testrun
diff --git a/test/integration/test-cve-2013-1051-InRelease-parsing b/test/integration/test-cve-2013-1051-InRelease-parsing
index 853da5ff6..6764fefff 100755
--- a/test/integration/test-cve-2013-1051-InRelease-parsing
+++ b/test/integration/test-cve-2013-1051-InRelease-parsing
@@ -37,7 +37,7 @@ sed -i '/^-----BEGIN PGP SIGNATURE-----/,/^-----END PGP SIGNATURE-----/ s/^$/ /
# we append the (evil unsigned) Release file to the (good signed) InRelease
cat aptarchive/dists/stable/Release >> aptarchive/dists/stable/InRelease
-
+touch -d '+1hour' aptarchive/dists/stable/InRelease
# ensure the update fails
# useful for debugging to add "-o Debug::pkgAcquire::auth=true"
diff --git a/test/integration/test-pdiff-usage b/test/integration/test-pdiff-usage
index 29301d07d..e45326970 100755
--- a/test/integration/test-pdiff-usage
+++ b/test/integration/test-pdiff-usage
@@ -35,7 +35,7 @@ SHA1-History:
SHA1-Patches:
7651fc0ac57cd83d41c63195a9342e2db5650257 19722 2010-08-18-0814.28
$(sha1sum $PATCHFILE | cut -d' ' -f 1) $(stat -c%s $PATCHFILE) $(basename $PATCHFILE)" > $PATCHINDEX
-generatereleasefiles
+generatereleasefiles '+1hour'
signreleasefiles
find aptarchive -name 'Packages*' -type f -delete
aptget update -qq
diff --git a/test/integration/test-releasefile-verification b/test/integration/test-releasefile-verification
index fba7ab290..e56f458d3 100755
--- a/test/integration/test-releasefile-verification
+++ b/test/integration/test-releasefile-verification
@@ -184,5 +184,5 @@ runtest2
DELETEFILE="InRelease"
runtest
-#DELETEFILE="Release.gpg"
-#runtest
+DELETEFILE="Release.gpg"
+runtest
diff --git a/test/interactive-helper/aptwebserver.cc b/test/interactive-helper/aptwebserver.cc
index 05b875673..a8d191d0e 100644
--- a/test/interactive-helper/aptwebserver.cc
+++ b/test/interactive-helper/aptwebserver.cc
@@ -387,6 +387,41 @@ int main(int const argc, const char * argv[])
return 2;
}
+ FileFd pidfile;
+ if (_config->FindB("aptwebserver::fork", false) == true)
+ {
+ std::string const pidfilename = _config->Find("aptwebserver::pidfile", "aptwebserver.pid");
+ int const pidfilefd = GetLock(pidfilename);
+ if (pidfilefd < 0 || pidfile.OpenDescriptor(pidfilefd, FileFd::WriteOnly) == false)
+ {
+ _error->Errno("aptwebserver", "Couldn't acquire lock on pidfile '%s'", pidfilename.c_str());
+ _error->DumpErrors(std::cerr);
+ return 3;
+ }
+
+ pid_t child = fork();
+ if (child < 0)
+ {
+ _error->Errno("aptwebserver", "Forking failed");
+ _error->DumpErrors(std::cerr);
+ return 4;
+ }
+ else if (child != 0)
+ {
+ // successfully forked: ready to serve!
+ std::string pidcontent;
+ strprintf(pidcontent, "%d", child);
+ pidfile.Write(pidcontent.c_str(), pidcontent.size());
+ if (_error->PendingError() == true)
+ {
+ _error->DumpErrors(std::cerr);
+ return 5;
+ }
+ std::cout << "Successfully forked as " << child << std::endl;
+ return 0;
+ }
+ }
+
std::clog << "Serving ANY file on port: " << port << std::endl;
listen(sock, 1);
@@ -502,5 +537,7 @@ int main(int const argc, const char * argv[])
<< " on socket " << sock << std::endl;
close(client);
}
+ pidfile.Close();
+
return 0;
}
--
cgit v1.2.3-70-g09d2
From 7a948ec719ecc020c2337fe3f41c5fc42699e2c1 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Wed, 26 Jun 2013 17:37:57 +0200
Subject: Version 3 for DPkg::Pre-Install-Pkgs with MultiArch info
Adds on top of Version 2 to all displayed version numbers the
architecture as well as the MultiArch flag for consumption by the hooks.
Most of the time the architecture will be the same for both versions
displayed, but packages might change from "all" to "any" (or back)
between versions so we can't display the architecture for packages.
Pseudo-Format for Version 3:
Examples:
stuff - - none < 1 amd64 none **CONFIGURE**
libsame 1 i386 same < 2 i386 same **CONFIGURE**
stuff 2 i386 none > 1 i386 none **CONFIGURE**
libsame 2 i386 same > - - none **REMOVE**
toolkit 1 all foreign > - - none **REMOVE**
Closes: #712116
---
apt-pkg/cacheiterators.h | 1 +
apt-pkg/deb/dpkgpm.cc | 71 +++++++++++-----
apt-pkg/deb/dpkgpm.h | 4 +-
apt-pkg/pkgcache.cc | 12 +++
doc/apt.conf.5.xml | 14 +++-
...bug-712116-dpkg-pre-install-pkgs-hook-multiarch | 95 ++++++++++++++++++++++
6 files changed, 171 insertions(+), 26 deletions(-)
create mode 100755 test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch
(limited to 'test')
diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h
index 179a0e963..886d84838 100644
--- a/apt-pkg/cacheiterators.h
+++ b/apt-pkg/cacheiterators.h
@@ -220,6 +220,7 @@ class pkgCache::VerIterator : public Iterator {
inline VerFileIterator FileList() const;
bool Downloadable() const;
inline const char *PriorityType() const {return Owner->Priority(S->Priority);};
+ const char *MultiArchType() const;
std::string RelStr() const;
bool Automatic() const;
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 3bc31dc37..fb0473535 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -238,15 +238,23 @@ bool pkgDPkgPM::Remove(PkgIterator Pkg,bool Purge)
return true;
}
/*}}}*/
-// DPkgPM::SendV2Pkgs - Send version 2 package info /*{{{*/
+// DPkgPM::SendPkgInfo - Send info for install-pkgs hook /*{{{*/
// ---------------------------------------------------------------------
/* This is part of the helper script communication interface, it sends
very complete information down to the other end of the pipe.*/
bool pkgDPkgPM::SendV2Pkgs(FILE *F)
{
- fprintf(F,"VERSION 2\n");
-
- /* Write out all of the configuration directives by walking the
+ return SendPkgsInfo(F, 2);
+}
+bool pkgDPkgPM::SendPkgsInfo(FILE * const F, unsigned int const &Version)
+{
+ // This version of APT supports only v3, so don't sent higher versions
+ if (Version <= 3)
+ fprintf(F,"VERSION %u\n", Version);
+ else
+ fprintf(F,"VERSION 3\n");
+
+ /* Write out all of the configuration directives by walking the
configuration tree */
const Configuration::Item *Top = _config->Tree(0);
for (; Top != 0;)
@@ -280,30 +288,51 @@ bool pkgDPkgPM::SendV2Pkgs(FILE *F)
pkgDepCache::StateCache &S = Cache[I->Pkg];
fprintf(F,"%s ",I->Pkg.Name());
- // Current version
- if (I->Pkg->CurrentVer == 0)
- fprintf(F,"- ");
+
+ // Current version which we are going to replace
+ pkgCache::VerIterator CurVer = I->Pkg.CurrentVer();
+ if (CurVer.end() == true && (I->Op == Item::Remove || I->Op == Item::Purge))
+ CurVer = FindNowVersion(I->Pkg);
+
+ else if (CurVer.end() == true)
+ {
+ if (Version <= 2)
+ fprintf(F, "- ");
+ else
+ fprintf(F, "- - none ");
+ }
else
- fprintf(F,"%s ",I->Pkg.CurrentVer().VerStr());
-
- // Show the compare operator
- // Target version
+ {
+ fprintf(F, "%s ", CurVer.VerStr());
+ if (Version >= 3)
+ fprintf(F, "%s %s ", CurVer.Arch(), CurVer.MultiArchType());
+ }
+
+ // Show the compare operator between current and install version
if (S.InstallVer != 0)
{
+ pkgCache::VerIterator const InstVer = S.InstVerIter(Cache);
int Comp = 2;
- if (I->Pkg->CurrentVer != 0)
- Comp = S.InstVerIter(Cache).CompareVer(I->Pkg.CurrentVer());
+ if (CurVer.end() == false)
+ Comp = InstVer.CompareVer(CurVer);
if (Comp < 0)
fprintf(F,"> ");
- if (Comp == 0)
+ else if (Comp == 0)
fprintf(F,"= ");
- if (Comp > 0)
+ else if (Comp > 0)
fprintf(F,"< ");
- fprintf(F,"%s ",S.InstVerIter(Cache).VerStr());
+ fprintf(F, "%s ", InstVer.VerStr());
+ if (Version >= 3)
+ fprintf(F, "%s %s ", InstVer.Arch(), InstVer.MultiArchType());
}
else
- fprintf(F,"> - ");
-
+ {
+ if (Version <= 2)
+ fprintf(F, "> - ");
+ else
+ fprintf(F, "> - - none ");
+ }
+
// Show the filename/operation
if (I->Op == Item::Install)
{
@@ -313,9 +342,9 @@ bool pkgDPkgPM::SendV2Pkgs(FILE *F)
else
fprintf(F,"%s\n",I->File.c_str());
}
- if (I->Op == Item::Configure)
+ else if (I->Op == Item::Configure)
fprintf(F,"**CONFIGURE**\n");
- if (I->Op == Item::Remove ||
+ else if (I->Op == Item::Remove ||
I->Op == Item::Purge)
fprintf(F,"**REMOVE**\n");
@@ -404,7 +433,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
}
}
else
- SendV2Pkgs(F);
+ SendPkgsInfo(F, Version);
fclose(F);
diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h
index aab39f633..c31d56f8e 100644
--- a/apt-pkg/deb/dpkgpm.h
+++ b/apt-pkg/deb/dpkgpm.h
@@ -14,6 +14,7 @@
#include
#include