haskell-nix / hnix-store

Haskell implementation of the Nix store
Apache License 2.0
83 stars 23 forks source link

remote: add deleteSpecific #268

Closed squalus closed 8 months ago

squalus commented 8 months ago

Add the gcDeleteSpecific action of the CollectGarbage operation.

ignoreLiveness is not exposed since nix-daemon always errors out if it's set. (https://github.com/NixOS/nix/blob/a8fea5a54/src/libstore/daemon.cc#L728)

maxFreedBytes is not exposed since it just doesn't seem very useful. nix-store --delete does not expose it either.

The CollectGarbage operation has three other actions that could potentially be exposed. They seem different enough that I think you'd want different functions for dealing with them. (Ref: https://github.com/NixOS/nix/blob/a8fea5a54/src/libstore/gc-store.hh#L15)

The test is a little strange. It needs to delete the tempRoot of the newly added path. It can do this by restarting the nix-daemon or by manually deleting it from the filesystem. So the test manually deletes it, using a path it builds from the storeDir.

sorki commented 8 months ago

Looks good! I'll merge this and rebase my branch at #255 as I'm about to start picking the serialization for operations apart and adding server side for them, I think you can start targeting that one instead of master soon^tm. Will try to do the most intrusive changes today.

I've also have GC.hs file I wrote years ago in my TODO list that I wasn't sure what to do with but now it seems clear, I'll integrate that as well

{-|
Description : Garbage collection actions / options
Maintainer  : srk <srk@48.io>
|-}
module System.Nix.GC (
    Action(..)
  , Options(..)
  , Result(..)
  ) where

import           System.Nix.Path           (PathSet)

{- Garbage collector operation:
     - ReturnLive: return the set of paths reachable from
       (i.e. in the closure of) the roots.
     - ReturnDead: return the set of paths not reachable from
       the roots.
     - DeleteDead: actually delete the latter set.
     - DeleteSpecific: delete the paths listed in
        `pathsToDelete', insofar as they are not reachable.
-}

data Action = ReturnLive | ReturnDead | DeleteDead | DeleteSpecific
  deriving (Eq, Ord, Enum, Show)

 -- | Garbage collector operation options
data Options = Options
  { -- | operation
    operation      :: !Action
    -- | If `ignoreLiveness' is set, then reachability from the roots is
    -- ignored (dangerous!).  However, the paths must still be
    -- unreferenced *within* the store (i.e., there can be no other
    -- store paths that depend on them).
  , ignoreLiveness :: !Bool
    -- | For DeleteSpecific, the paths to delete
  , pathsToDelete  :: !PathSet
  , -- | Stop after at least `maxFreed` bytes have been freed
    maxFreed       :: !Integer
  } deriving (Eq, Ord, Show)

data Result = Result
 { -- | Depending on the action, the GC roots, or the paths that would be or have been deleted
   paths      :: !PathSet
 , -- |  For ReturnDead, DeleteDead and DeleteSpecific, the number of bytes that would be or was freed
   bytesFreed :: !Integer
 } deriving (Eq, Ord, Show)
sorki commented 8 months ago

Cherry-picked into #255 https://github.com/haskell-nix/hnix-store/pull/255/commits/9bcb1fe00ba47081393ab64faa548efe9f6bac16 Thanks!