summaryrefslogtreecommitdiff
path: root/apt-pkg/pkgcachegen.cc
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg/pkgcachegen.cc')
-rw-r--r--apt-pkg/pkgcachegen.cc83
1 files changed, 69 insertions, 14 deletions
diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc
index 0eba5795f..d5b282007 100644
--- a/apt-pkg/pkgcachegen.cc
+++ b/apt-pkg/pkgcachegen.cc
@@ -950,19 +950,75 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
if (unlikely(Dependency == 0))
return false;
- // Fill it in
- pkgCache::DepIterator Dep(Cache,Cache.DepP + Dependency);
- Dynamic<pkgCache::DepIterator> DynDep(Dep);
- Dep->ParentVer = Ver.Index();
- Dep->Type = Type;
- Dep->CompareOp = Op;
- Dep->Version = Version;
- Dep->ID = Cache.HeaderP->DependsCount++;
+ bool isDuplicate = false;
+ map_pointer_t DependencyData = 0;
+ map_pointer_t * PkgRevDepends = &Pkg->RevDepends;
+ map_pointer_t previous_id = 0;
- // Link it to the package
- Dep->Package = Pkg.Index();
- Dep->NextRevDepends = Pkg->RevDepends;
- Pkg->RevDepends = Dep.Index();
+ while (*PkgRevDepends != 0)
+ {
+ pkgCache::Dependency * const L = Cache.DepP + *PkgRevDepends;
+ PkgRevDepends = &L->NextRevDepends;
+ if (L->DependencyData == previous_id)
+ break;
+ previous_id = L->DependencyData;
+ pkgCache::DependencyData const * const D = Cache.DepDataP + previous_id;
+ if (D->Type == Type && D->CompareOp == Op && D->Version == Version)
+ {
+ DependencyData = previous_id;
+ isDuplicate = true;
+ break;
+ }
+ }
+
+ if (isDuplicate == false)
+ {
+ void const * const oldMap2 = Map.Data();
+ DependencyData = AllocateInMap(sizeof(pkgCache::DependencyData));
+ if (unlikely(DependencyData == 0))
+ return false;
+ if (oldMap2 != Map.Data())
+ PkgRevDepends += (map_pointer_t const * const) Map.Data() - (map_pointer_t const * const) oldMap2;
+ }
+
+ pkgCache::Dependency * Link = Cache.DepP + Dependency;
+ Link->ParentVer = Ver.Index();
+ Link->DependencyData = DependencyData;
+ Link->ID = Cache.HeaderP->DependsCount++;
+
+ pkgCache::DepIterator Dep(Cache, Link);
+ Dynamic<pkgCache::DepIterator> DynDep(Dep);
+ if (isDuplicate == false)
+ {
+ Dep->Type = Type;
+ Dep->CompareOp = Op;
+ Dep->Version = Version;
+ Dep->Package = Pkg.Index();
+ ++Cache.HeaderP->DependsDataCount;
+ Link->NextRevDepends = Pkg->RevDepends;
+ Pkg->RevDepends = Dependency;
+ }
+ else
+ {
+ // dependency data is already fine, we just set the reverse link
+ // and in such a way that the loop above can finish fast, so we keep
+ // non-duplicates at the front and for the duplicates we:
+ // a) move to the end of the list, b) insert before another own duplicate
+ // or c) find two duplicates behind each other.
+ map_pointer_t const own_id = Link->DependencyData;
+ while (*PkgRevDepends != 0)
+ {
+ pkgCache::Dependency * const L = Cache.DepP + *PkgRevDepends;
+ PkgRevDepends = &L->NextRevDepends;
+ if (L->DependencyData == own_id || L->DependencyData == previous_id)
+ {
+ Link->NextRevDepends = L->NextRevDepends;
+ break;
+ }
+ previous_id = L->DependencyData;
+ }
+ *PkgRevDepends = Dependency;
+ }
// Do we know where to link the Dependency to?
if (OldDepLast == NULL)
@@ -974,9 +1030,8 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
OldDepLast += (map_pointer_t const * const) Map.Data() - (map_pointer_t const * const) oldMap;
Dep->NextDepends = *OldDepLast;
- *OldDepLast = Dep.Index();
+ *OldDepLast = Dependency;
OldDepLast = &Dep->NextDepends;
-
return true;
}
/*}}}*/