[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Garbage collection and removed packages



  There's a bug (#478116) in this patch I wrote last year.  I sent the
patch directly to Michael, but I'm resending to deity@ so Otavio can
follow this too.  The full context follows:

On Sun, Jun 17, 2007 at 04:58:40PM -0700, Daniel Burrows <dburrows@debian.org> was heard to say:
>   So I've been fiddling a bunch with the new apt and integrating
> aptitude with it, and I ran into a snag.
> 
>   The garbage collection algorithm in aptitude would mutate the
> cache as it went, cancelling garbage removals that it hit and then
> following the dependencies of the newly non-removed packages.  When
> you ported aptitude's algorithm to apt, you decided to not do this,
> and I think that's probably the right decision.
> 
>   However, the current version of apt marks all removed packages
> as garbage, even if an installed package depends on them.  This
> feels wrong to me; I think that it would be much more straightforward
> conceptually and for frontends if apt didn't set the garbage flag
> on packages which participate in a dependency of an installed package.
> 
>   i.e., if we have
> 
>     A Depends B
>     B Depends C
>     B, C are being removed
>     A is installed, not being removed
> 
>   then B and C should NOT be marked with the "garbage" flag.  This
> makes some nice features (like auto-resurrecting packages from the
> unused-remove state) possible.
> 
>   Implementing this to the extent that aptitude needs is easy.
> Right now we only mark the version of a package that will be
> installed after all pending actions are discharged; if the package
> will be removed, it's skipped.  Just change this rule so that we
> mark the *current* version of removed packages, and apt will not
> set the garbage flag on removed packages whose current version
> is part of a dependency chain.

  How lightly, how blithely I said that.

  So, here's the situation now: if you remove xterm,

    daniel@alpaca:~$ aptitude -s purge xterm
    Reading package lists... Done
    Building dependency tree       
    Reading state information... Done
    Reading extended state information       
    Initializing package states... Done
    The following packages will be REMOVED:
      xterm{p}  
    0 packages upgraded, 0 newly installed, 1 to remove and 2 not upgraded.
    Need to get 0B of archives. After unpacking 1139kB will be freed.
    Do you want to continue? [Y/n/?] n
    Abort.

  you will discover that xbitmaps is still installed!  Worse, if you run
aptitude again, you will discover that xbitmaps is being automatically
removed.

    daniel@alpaca:~$ aptitude -s install
    Reading package lists... Done
    Building dependency tree       
    Reading state information... Done
    Reading extended state information       
    Initializing package states... Done
    The following packages will be REMOVED:
      xbitmaps{u}  
    0 packages upgraded, 0 newly installed, 1 to remove and 2 not upgraded.
    Need to get 0B of archives. After unpacking 479kB will be freed.
    Do you want to continue? [Y/n/?]

  What's going on here?  Well, xterm is being removed, and we happily
follow the dependencies of removed packages.  I've added some debugging
code to apt, and we can see it mark xterm and its outgoing deps:

    Marking: xterm
    Following dep: xterm 235-1 Depends xbitmaps
    [...]

  This leads to the question: why does auto-marking ever work?  I
believe that this bug only afflicts packages that are themselves
dependencies of manually installed packages.  Many packages aren't, so
autoremoval appears to work fine with them: nothing ever triggers
MarkRequired on the package, and thus it never gets marked.  I can
trigger this with other packages that are in a similar situation: for
instance, if I remove ghc6, then haskell-utils has no revdeps, but it
still gets stuck on the system.


  Can we solve the two problems at once?  To recap, we want:

    (a) manually removed packages aren't marked as garbage.
    (b) all dependencies of manually removed packages that are not,
        themselves, being manually removed should be marked as garbage.

  I think the core problem here is that (b) can't be implemented in apt,
because it doesn't keep track of whether a package was removed because
it was garbage.  If we recur on all removed packages, we run into the
bug that was reported above; if we recur on no removed packages, then
aptitude can't figure out which packages to reinstate without multiple
runs.  That is: if you have A -> B{a} -> C{a} with B and C automatically
installed, and you mark A for removal and then cancel that removal,
B will be marked as not-garbage and its removal cancelled, but since B
is removed, the mark step won't recur to C and C will stay removed.

  What I'd really like is to trace out the dependency tree, stopping the
trace at a *manually* removed package.  That is, if you have

    A -> B -> C
    A -> D -> E

  with B, C, D, and E automatically installed and A manually installed,
if B, C, and E are being automatically removed and D is being manually
removed, then A, B, C, and D would get marked.  So B and C could be
reinstated by the frontend (if it had the appropriate superpowers),
while E would be automatically removed and D would be left alone.


  But apt has no concept of packages being removed because they are
garbage.  We could try overloading the Auto flag, but that breaks
another feature: in aptitude, removing or keeping an automatic package
that's being removed will only clear the auto flag if it was removed due
to being unused.  In other words, a package can be both "automatically
installed" and "manually removed".

  I think that the only way to solve this is to add a new flag to the
Flag enumeration in pkgcache.h.  The new flag, call it UnusedRemoved for
now, will mean "removed because it was unused"; MarkRequired will then
mark any removed packages, but only recur on removed packages if
UnusedRemoved is set.  Frontends will have the option of setting
UnusedRemoved on packages that are in this state; by default it will
never be set by apt, and if it's not set apt will behave in the same
manner that it does now.


  Comments?  Will this change the ABI? (I don't think so if we stick to
just adding a new enum member: old apts will ignore that bit and new
ones will assume it's zero if the frontend doesn't set it)  Can we get
this into 0.7.12?

  Daniel


Reply to: