diff --git a/CHANGES b/CHANGES
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,27 @@
+Version 0.3 released 08 Apr 2009
+
+* Added new 'directory' function, which returns a list of resources given
+  a directory name. Resources are marked as either FSFile or
+  FSDirectory. Thanks to Thomas Hartman for showing the need for
+  'directory', and for distinguishing explicitly between files and
+  directories. In 'index' the distinction was previously left implicit,
+  which worked for git but not darcs: 'index' provided no way of
+  distinguishing an empty directory from a file.
+
+* In 'directory' and 'index', git ls-tree is used instead of git ls-files;
+  this guarantees that only files that have been committed are returned.
+  'index' now lists only files, and no longer includes empty directories
+  even in darcs.
+
+* Added new richDirectory function to Data.FileStore.Generic.
+  richDirectory returns a directory that includes information
+  about the latest revision of each file. Thanks to Thomas Hartman for
+  the patch.
+
+* Replaced ResourceName type with FilePath.
+
+* Added repository information to cabal file.
+
 Version 0.2 released 08 Feb 2009
 
 * Changed diff to do a line-by-line rather than word-by-word diff.
@@ -27,6 +51,8 @@
   and for creating a second file in a subdirectory.
 
 * Minor code cleanup.
+
+* Added CHANGES.
 
 Version 0.1 released 24 Jan 2009
 
diff --git a/Data/FileStore/Darcs.hs b/Data/FileStore/Darcs.hs
--- a/Data/FileStore/Darcs.hs
+++ b/Data/FileStore/Darcs.hs
@@ -22,12 +22,12 @@
 import Data.DateTime (parseDateTime, toSqlString)
 import Data.FileStore.Types
 import Data.FileStore.Utils (hashsMatch, isInsideRepo, parseMatchLine, runShellCommand, escapeRegexSpecialChars)
-import Data.List (intersect, nub)
+import Data.List (intersect, nub, sort, isPrefixOf)
 import Data.Maybe (fromMaybe, fromJust)
 import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
 import System.Directory (doesFileExist, doesDirectoryExist, createDirectoryIfMissing)
 import System.Exit (ExitCode(ExitSuccess))
-import System.FilePath ((</>), takeDirectory, dropFileName)
+import System.FilePath ((</>), takeDirectory, dropFileName, addTrailingPathSeparator)
 import Text.Regex.Posix ((=~))
 import Text.XML.Light
 import qualified Data.ByteString.Lazy as B (ByteString, writeFile)
@@ -45,6 +45,7 @@
   , latest          = darcsLatestRevId repo
   , revision        = darcsGetRevision repo
   , index           = darcsIndex repo
+  , directory       = darcsDirectory repo
   , search          = darcsSearch repo
   , idsMatch        = const hashsMatch repo }
                    
@@ -138,7 +139,7 @@
                          return $ lines $ toString r
 
 -- | If name doesn't exist in repo or is not a file, throw NotFound
-ensureFileExists :: FilePath -> ResourceName -> IO ()
+ensureFileExists :: FilePath -> FilePath -> IO ()
 ensureFileExists repo name = do
   isFile <- doesFileExist (repo </> encodeString name)
   when (not isFile) $ throwIO NotFound
@@ -160,7 +161,7 @@
      else throwIO $ UnknownError $ "darcs init failed:\n" ++ err
 
 -- | Save changes (creating the file and directory if needed), add, and commit.
-darcsSave :: Contents a => FilePath -> ResourceName -> Author -> Description -> a -> IO ()
+darcsSave :: Contents a => FilePath -> FilePath -> Author -> Description -> a -> IO ()
 darcsSave repo name author logMsg contents = do
   let filename = repo </> encodeString name
   inside <- isInsideRepo repo filename
@@ -174,7 +175,7 @@
 
 -- | Commit changes to a resource.  Raise 'Unchanged' exception if there were none.
 --   This is not for creating a new file; see 'darcsSave'. This is just for updating.
-darcsCommit :: FilePath -> [ResourceName] -> Author -> Description -> IO ()
+darcsCommit :: FilePath -> [FilePath] -> Author -> Description -> IO ()
 darcsCommit repo names author logMsg = do
   let args = ["--all", "-A", (authorName author ++ " <" ++ authorEmail author ++ ">"), "-m", logMsg] ++ names
   (statusCommit, errCommit, _) <- runDarcsCommand repo "record" args
@@ -185,7 +186,7 @@
                        else UnknownError $ "Could not darcs record " ++ unwords names ++ "\n" ++ errCommit
 
 -- | Change the name of a resource.
-darcsMove :: FilePath -> ResourceName -> ResourceName -> Author -> Description -> IO ()
+darcsMove :: FilePath -> FilePath -> FilePath -> Author -> Description -> IO ()
 darcsMove repo oldName newName author logMsg = do
   let newPath = repo </> newName
   inside <- isInsideRepo repo newPath
@@ -199,7 +200,7 @@
      else throwIO NotFound
 
 -- | Delete a resource from the repository.
-darcsDelete :: FilePath -> ResourceName -> Author -> Description -> IO ()
+darcsDelete :: FilePath -> FilePath -> Author -> Description -> IO ()
 darcsDelete repo name author logMsg = do
   runShellCommand repo Nothing "rm" [name]
   darcsCommit repo [name] author logMsg
@@ -211,7 +212,7 @@
 
 -- | Return list of log entries for the list of resources.
 -- If list of resources is empty, log entries for all resources are returned.
-darcsLog :: FilePath -> [ResourceName] -> TimeRange -> IO [Revision]
+darcsLog :: FilePath -> [FilePath] -> TimeRange -> IO [Revision]
 darcsLog repo names (TimeRange begin end) = do
     let opts = timeOpts begin end
     do (status, err, output) <- runDarcsCommand repo "changes" $ ["--xml-output", "--summary"] ++ names ++ opts
@@ -239,7 +240,7 @@
                                 return $ head result
 
 -- | Return revision ID for latest commit for a resource.
-darcsLatestRevId :: FilePath -> ResourceName -> IO RevisionId
+darcsLatestRevId :: FilePath -> FilePath -> IO RevisionId
 darcsLatestRevId repo name = do
   ensureFileExists repo name
   -- changes always succeeds, so no need to check error
@@ -252,7 +253,7 @@
 -- | Retrieve the contents of a resource.
 darcsRetrieve :: Contents a
             => FilePath
-            -> ResourceName
+            -> FilePath
             -> Maybe RevisionId    -- ^ @Just@ revision ID, or @Nothing@ for latest
             -> IO a
 darcsRetrieve repo name Nothing =
@@ -266,14 +267,30 @@
      else throwIO $ UnknownError $ "Error in darcs query contents:\n" ++ err
 
 -- | Get a list of all known files inside and managed by a repository.
-darcsIndex :: FilePath ->IO [ResourceName]
+darcsIndex :: FilePath ->IO [FilePath]
 darcsIndex repo = do
-    (status, errOutput, output) <- runDarcsCommand repo "query"  ["manifest"]
-    if status == ExitSuccess
-    -- We need to do 'drop 2' because Darcs returns files like ["./foobar"], and
-    -- the ./ is always present & always not wanted.
-     then return (map (drop 2) . lines . toString $ output)
-     else error $ "'darcs query manifest' returned error status.\n" ++ errOutput
+  (status, _errOutput, output) <- runDarcsCommand repo "query"  ["files","--no-directories"]
+  if status == ExitSuccess
+     then return $ map (drop 2) . lines . toString $ output
+     else return []   -- return empty list if invalid path (see gitIndex)
+
+-- | Get a list of all resources inside a directory in the repository.
+darcsDirectory :: FilePath -> FilePath -> IO [Resource]
+darcsDirectory repo dir = do
+  let dir' = if null dir then "" else addTrailingPathSeparator dir
+  (status1, _errOutput1, output1) <- runDarcsCommand repo "query"  ["files","--no-directories"]
+  (status2, _errOutput2, output2) <- runDarcsCommand repo "query" ["files","--no-files"]
+  if status1 == ExitSuccess && status2 == ExitSuccess
+     then do
+       let files = map (drop $ length dir' + 2) . filter (("." </> dir') `isPrefixOf`) . lines . toString $ output1
+       -- We need to do 'drop $ length dir' + 3' because Darcs returns files like ["./foo/foobar"].
+       let dirs  = map (drop $ length dir' + 2) . filter (("." </> dir') `isPrefixOf`) . drop 1 . lines . toString $ output2
+       -- We need the drop 1 to eliminate the root directory, which appears first.
+       -- Now, select the ones that are in THIS directory and convert to Resources:
+       let files' = map FSFile  $ filter ('/' `notElem`) files
+       let dirs'  = map FSDirectory $ filter ('/' `notElem`) dirs
+       return $ sort (files' ++ dirs') 
+     else return []  -- returns empty list for invalid path (see gitDirectory)
 
 -- | Uses grep to search repository.
 darcsSearch :: FilePath -> SearchQuery -> IO [SearchMatch]
diff --git a/Data/FileStore/Generic.hs b/Data/FileStore/Generic.hs
--- a/Data/FileStore/Generic.hs
+++ b/Data/FileStore/Generic.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE ScopedTypeVariables #-}
 {- |
    Module      : Data.FileStore.Generic
    Copyright   : Copyright (C) 2009 John MacFarlane, Gwern Branwen, Sebastiaan Visser
@@ -17,6 +18,7 @@
            , diff
            , searchRevisions
            , smartRetrieve
+           , richDirectory
            )
 
 where
@@ -26,6 +28,7 @@
 import Data.FileStore.Utils
 import Data.List (isInfixOf)
 import Data.Algorithm.Diff (DI(..), getGroupedDiff)
+import System.FilePath ((</>))
 import Prelude hiding (catch)
 
 handleUnknownError :: SomeException -> IO a
@@ -35,7 +38,7 @@
 -- error.
 create :: Contents a
        => FileStore
-       -> ResourceName      -- ^ Resource to create.
+       -> FilePath          -- ^ Resource to create.
        -> Author            -- ^ Author of change.
        -> Description       -- ^ Description of change.
        -> a                 -- ^ Contents of resource.
@@ -50,7 +53,7 @@
 -- @Left@ merge information is returned.  Otherwise, @Right@ the new contents are saved.  
 modify  :: Contents a
         => FileStore
-        -> ResourceName      -- ^ Resource to create.
+        -> FilePath          -- ^ Resource to create.
         -> RevisionId        -- ^ ID of previous revision that is being modified.
         -> Author            -- ^ Author of change.
         -> Description       -- ^ Description of change.
@@ -75,7 +78,7 @@
 -- or @B@ (in both), and the list is a list of lines (without
 -- newlines at the end).
 diff :: FileStore
-     -> ResourceName      -- ^ Resource name to get diff for.
+     -> FilePath      -- ^ Resource name to get diff for.
      -> Maybe RevisionId  -- ^ @Just@ old revision ID, or @Nothing@ for empty.
      -> Maybe RevisionId  -- ^ @Just@ oew revision ID, or @Nothing@ for latest.
      -> IO [(DI, [String])]
@@ -93,7 +96,7 @@
                 -> Bool              -- ^ When true the description must
                                      --   match exactly, when false partial
                                      --   hits are allowed.
-                -> ResourceName      -- ^ The resource to search history for.
+                -> FilePath          -- ^ The resource to search history for.
                 -> Description       -- ^ Revision description to search for.
                 -> IO [Revision]
 
@@ -112,7 +115,7 @@
   :: Contents a
   => FileStore
   -> Bool            -- ^ @True@ for exact description match, @False@ for partial match.
-  -> ResourceName    -- ^ Resource name to retrieve.
+  -> FilePath        -- ^ Resource name to retrieve.
   -> Maybe String    -- ^ @Just@ revision ID or description, or @Nothing@ for empty.
   -> IO a
 smartRetrieve fs exact name mrev = do
@@ -135,4 +138,14 @@
 
         -- Retrieve resource for latest matching revision.
         else retrieve fs name (Just $ revId $ Prelude.head revs)
+
+-- | Like 'directory', but returns information about the latest revision.
+richDirectory :: FileStore -> FilePath -> IO [(Resource, Either String Revision)]
+richDirectory fs fp = do
+  rs <- directory fs fp
+  mapM f rs
+  where f r = Control.Exception.catch (g r) (\(e :: FileStoreError)-> return $ ( r, Left . show $ e ) )
+        g r@(FSDirectory _dir) = return (r,Left "richDirectory, we don't care about revision info for repos")
+        g res@(FSFile file) = do rev <- revision fs =<< latest fs ( fp </> file )
+                                 return (res,Right rev)
 
diff --git a/Data/FileStore/Git.hs b/Data/FileStore/Git.hs
--- a/Data/FileStore/Git.hs
+++ b/Data/FileStore/Git.hs
@@ -17,6 +17,7 @@
            )
 where
 import Data.FileStore.Types
+import Data.Maybe (mapMaybe)
 import System.Exit
 import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
 import Data.FileStore.Utils (hashsMatch, isInsideRepo, runShellCommand, escapeRegexSpecialChars) 
@@ -48,6 +49,7 @@
   , latest            = gitLatestRevId repo
   , revision          = gitGetRevision repo
   , index             = gitIndex repo
+  , directory         = gitDirectory repo
   , search            = gitSearch repo 
   , idsMatch          = const hashsMatch repo
   }
@@ -82,7 +84,7 @@
 
 -- | Commit changes to a resource.  Raise 'Unchanged' exception if there were
 -- no changes.
-gitCommit :: FilePath -> [ResourceName] -> Author -> String -> IO ()
+gitCommit :: FilePath -> [FilePath] -> Author -> String -> IO ()
 gitCommit repo names author logMsg = do
   (statusCommit, errCommit, _) <- runGitCommand repo "commit" $ ["--author", authorName author ++ " <" ++
                                     authorEmail author ++ ">", "-m", logMsg] ++ names
@@ -93,7 +95,7 @@
                        else UnknownError $ "Could not git commit " ++ unwords names ++ "\n" ++ errCommit
 
 -- | Save changes (creating file and directory if needed), add, and commit.
-gitSave :: Contents a => FilePath -> ResourceName -> Author -> Description -> a -> IO ()
+gitSave :: Contents a => FilePath -> FilePath -> Author -> Description -> a -> IO ()
 gitSave repo name author logMsg contents = do
   let filename = repo </> encodeString name
   inside <- isInsideRepo repo filename
@@ -108,7 +110,7 @@
 -- | Retrieve contents from resource.
 gitRetrieve :: Contents a
             => FilePath
-            -> ResourceName
+            -> FilePath
             -> Maybe RevisionId    -- ^ @Just@ revision ID, or @Nothing@ for latest
             -> IO a
 gitRetrieve repo name revid = do
@@ -124,7 +126,7 @@
      else throwIO $ UnknownError $ "Error in git cat-file:\n" ++ err'
 
 -- | Delete a resource from the repository.
-gitDelete :: FilePath -> ResourceName -> Author -> Description -> IO ()
+gitDelete :: FilePath -> FilePath -> Author -> Description -> IO ()
 gitDelete repo name author logMsg = do
   (statusAdd, errRm, _) <- runGitCommand repo "rm" [name]
   if statusAdd == ExitSuccess
@@ -132,7 +134,7 @@
      else throwIO $ UnknownError $ "Could not git rm '" ++ name ++ "'\n" ++ errRm
 
 -- | Change the name of a resource.
-gitMove :: FilePath -> ResourceName -> ResourceName -> Author -> Description -> IO ()
+gitMove :: FilePath -> FilePath -> FilePath -> Author -> Description -> IO ()
 gitMove repo oldName newName author logMsg = do
   gitLatestRevId repo oldName   -- will throw a NotFound error if oldName doesn't exist
   let newPath = repo </> encodeString newName
@@ -146,7 +148,7 @@
      else throwIO $ UnknownError $ "Could not git mv " ++ oldName ++ " " ++ newName ++ "\n" ++ err
 
 -- | Return revision ID for latest commit for a resource.
-gitLatestRevId :: FilePath -> ResourceName -> IO RevisionId
+gitLatestRevId :: FilePath -> FilePath -> IO RevisionId
 gitLatestRevId repo name = do
   (status, _, output) <- runGitCommand repo "rev-list" ["--max-count=1", "HEAD", "--", name]
   if status == ExitSuccess
@@ -169,14 +171,29 @@
                  Right xs    -> throwIO $ UnknownError $ "git rev-list returned more than one result: " ++ show xs
      else throwIO NotFound
 
--- | Get list of files in repository.
-gitIndex :: FilePath -> IO [ResourceName]
+-- | Get a list of all known files inside and managed by a repository.
+gitIndex :: FilePath ->IO [FilePath]
 gitIndex repo = do
-  (status, errOutput, output) <- runGitCommand repo "ls-files" []
+  (status, _err, output) <- runGitCommand repo "ls-tree" ["-r","-t","HEAD"]
   if status == ExitSuccess
-     then return $ map convertEncoded $ lines $ toString output
-     else error $ "git ls-files returned error status.\n" ++ errOutput
+     then return $ mapMaybe (lineToFilename . words) . lines . toString $ output
+     else return [] -- if error, will return empty list
+                    -- note:  on a newly initialized repo, 'git ls-tree HEAD' returns an error
+   where lineToFilename (_:"blob":_:rest) = Just $ convertEncoded $ unwords rest
+         lineToFilename _                 = Nothing
 
+-- | Get list of resources in one directory of the repository.
+gitDirectory :: FilePath -> FilePath -> IO [Resource]
+gitDirectory repo dir = do
+  (status, _err, output) <- runGitCommand repo "ls-tree" ["HEAD:" ++ dir]
+  if status == ExitSuccess
+     then return $ map (lineToResource . words) $ lines $ toString output
+     else return []   -- if error, this will return empty list
+                      -- note:  on a newly initialized repo, 'git ls-tree HEAD:' returns an error
+   where lineToResource (_:"blob":_:rest) = FSFile $ convertEncoded $ unwords rest
+         lineToResource (_:"tree":_:rest) = FSDirectory $ convertEncoded $ unwords rest
+         lineToResource _                 = error "Encountered an item that is neither blob nor tree in git ls-tree"
+
 -- | Uses git-grep to search repository.  Escape regex special characters, so the pattern
 -- is interpreted as an ordinary string.
 gitSearch :: FilePath -> SearchQuery -> IO [SearchMatch]
@@ -199,7 +216,7 @@
 
 {-
 -- | Uses git-diff to get a dif between two revisions.
-gitDiff :: FilePath -> ResourceName -> RevisionId -> RevisionId -> IO String
+gitDiff :: FilePath -> FilePath -> RevisionId -> RevisionId -> IO String
 gitDiff repo name from to = do
   (status, _, output) <- runGitCommand repo "diff" [from, to, name]
   if status == ExitSuccess
@@ -214,7 +231,7 @@
 
 -- | Return list of log entries for the given time frame and list of resources.
 -- If list of resources is empty, log entries for all resources are returned.
-gitLog :: FilePath -> [ResourceName] -> TimeRange -> IO [Revision]
+gitLog :: FilePath -> [FilePath] -> TimeRange -> IO [Revision]
 gitLog repo names (TimeRange mbSince mbUntil) = do
   (status, err, output) <- runGitCommand repo "whatchanged" $
                            ["--pretty=format:%h%n%ct%n%an%n%ae%n%s%n"] ++
diff --git a/Data/FileStore/Types.hs b/Data/FileStore/Types.hs
--- a/Data/FileStore/Types.hs
+++ b/Data/FileStore/Types.hs
@@ -13,7 +13,7 @@
 
 module Data.FileStore.Types
            ( RevisionId
-           , ResourceName
+           , Resource(..)
            , Author(..)
            , Change(..)
            , Description
@@ -35,10 +35,13 @@
 import Data.DateTime (DateTime)
 import Control.Exception (Exception)
 import Prelude hiding (catch)
+import System.FilePath (FilePath)
 
 type RevisionId   = String
 
-type ResourceName = String
+data Resource = FSFile FilePath
+              | FSDirectory FilePath
+              deriving (Show, Read, Eq, Typeable, Ord)
 
 data Author =
   Author {
@@ -47,9 +50,9 @@
   } deriving (Show, Read, Eq, Typeable)
 
 data Change =
-    Added ResourceName
-  | Deleted ResourceName
-  | Modified ResourceName
+    Added FilePath
+  | Deleted FilePath
+  | Modified FilePath
   deriving (Show, Read, Eq, Typeable)
 
 type Description = String
@@ -127,7 +130,7 @@
 
 data SearchMatch =
   SearchMatch {
-    matchResourceName :: ResourceName
+    matchResourceName :: FilePath
   , matchLineNumber   :: Integer
   , matchLine         :: String
   } deriving (Show, Read, Eq, Typeable)
@@ -141,7 +144,7 @@
 
     -- | Save contents in the filestore.
   , save           :: Contents a
-                   => ResourceName      -- Resource to save.
+                   => FilePath          -- Resource to save.
                    -> Author            --  Author of change.
                    -> Description       --  Description of change.
                    -> a                 --  New contents of resource.
@@ -149,32 +152,32 @@
     
     -- | Retrieve the contents of the named resource.
   , retrieve       :: Contents a
-                   => ResourceName      -- Resource to retrieve.
+                   => FilePath          -- Resource to retrieve.
                    -> Maybe RevisionId  -- @Just@ a particular revision ID, or @Nothing@ for latest
                    -> IO a
 
     -- | Delete a named resource, providing author and log message.
-  , delete         :: ResourceName      -- Resource to delete.
+  , delete         :: FilePath          -- Resource to delete.
                    -> Author            -- Author of change.
                    -> Description       -- Description of change.
                    -> IO ()
 
     -- | Rename a resource, providing author and log message.
-  , rename         :: ResourceName      -- Resource original name.
-                   -> ResourceName      -- Resource new name.
+  , rename         :: FilePath          -- Resource original name.
+                   -> FilePath          -- Resource new name.
                    -> Author            -- Author of change.
                    -> Description       -- Description of change.
                    -> IO ()
 
     -- | Get history for a list of named resources in a (possibly openended) time range.
     -- If the list is empty, history for all resources will be returned. 
-  , history        :: [ResourceName]    -- List of resources to get history for, or @[]@ for all.
+  , history        :: [FilePath]        -- List of resources to get history for, or @[]@ for all.
                    -> TimeRange         -- Time range within which to get history.
                    -> IO [Revision]
 
     -- | Return the revision ID of the latest change for a resource.  Raises 'NotFound'
     -- if the resource is not found.
-  , latest         :: ResourceName      -- Resource to get revision ID for.
+  , latest         :: FilePath          -- Resource to get revision ID for.
                    -> IO RevisionId
 
     -- | Return information about a revision, given the ID.  Raises 'NotFound' if there is
@@ -183,7 +186,11 @@
                    -> IO Revision
 
     -- | Return a list of resources in the filestore.
-  , index          :: IO [ResourceName]
+  , index          :: IO [FilePath]
+
+  -- | Return a list of resources in a directory of the filestore.
+  , directory      :: FilePath          -- Directory to list (empty for root)
+                   -> IO [Resource]
 
     -- | @True@ if the revision IDs match, in the sense that the
     -- can be treated as specifying the same revision.
diff --git a/Tests.lhs b/Tests.lhs
--- a/Tests.lhs
+++ b/Tests.lhs
@@ -6,6 +6,7 @@
     runghc -idist/build/autogen Tests.lhs
 
 > import Data.FileStore
+> import Data.List (sort)
 > import Test.HUnit
 > import System.Directory (removeDirectoryRecursive)
 > import Control.Monad (forM)
@@ -14,6 +15,7 @@
 > import Data.DateTime
 > import Data.Maybe (mapMaybe)
 > import System.Directory (doesFileExist)
+> import System.FilePath
 > import System.Process
 > import Data.Algorithm.Diff (DI(..))
 
@@ -33,6 +35,7 @@
 >     , ("create resource in subdirectory", createTest2)
 >     , ("create resource with non-ascii name", createTest3)
 >     , ("try to create resource outside repo", createTest4)
+>     , ("directory", directoryTest)
 >     , ("retrieve resource", retrieveTest1)
 >     , ("retrieve resource in a subdirectory", retrieveTest2)
 >     , ("retrieve resource with non-ascii name", retrieveTest3)
@@ -84,7 +87,7 @@
 >   create fs subdirTestTitle testAuthor "description of change" testContents
 >   revid <- latest fs testTitle
 >   assertBool "revision returns a revision after create" (not (null revid))
->   create fs "subdir/Subdir title2.txt" testAuthor "+Second file" testContents
+>   create fs (subdirTestTitle ++ "2") testAuthor "+Second file" testContents
 
 *** Create a resource with a non-ascii title, and check to see that revision returns a revision for it:
 
@@ -102,6 +105,20 @@
 >   exists <- doesFileExist "tmp/oops"
 >   assertBool "file ../oops was created outside repository" (not exists)
 
+*** Test directory
+
+> directoryTest fs = TestCase $ do
+
+    Get directory for top-level
+
+>   files <- directory fs ""
+>   assertEqual "result of directory on top-level" (sort [FSDirectory "subdir", FSFile testTitle, FSFile nonasciiTestTitle]) (sort files)
+
+    Get contents of subdirectory
+
+>   subdirFiles <- directory fs "subdir"
+>   assertEqual "result of directory on subdir" [FSFile (takeFileName subdirTestTitle), FSFile (takeFileName (subdirTestTitle ++ "2"))] subdirFiles
+
 *** Retrieve latest version of a resource:
 
 > retrieveTest1 fs = TestCase $ do
@@ -180,7 +197,7 @@
 
 >   delete fs toBeDeleted testAuthor "goodbye"
 >   ind <- index fs
->   assertBool "index does not contain resource that was deleted" (not (toBeDeleted `elem` ind))
+>   assertBool "index does not contain resource that was deleted" (toBeDeleted `notElem` ind)
 
 *** Rename a resource:
 
diff --git a/filestore.cabal b/filestore.cabal
--- a/filestore.cabal
+++ b/filestore.cabal
@@ -1,5 +1,5 @@
 Name:                filestore
-Version:             0.2
+Version:             0.3
 Cabal-version:       >= 1.2
 Build-type:          Custom
 Tested-with:         GHC==6.10.1
@@ -14,13 +14,24 @@
 License-File:        LICENSE
 Author:              John MacFarlane, Gwern Branwen, Sebastiaan Visser
 Maintainer:          jgm@berkeley.edu
-Build-depends:       base >= 4, bytestring, utf8-string, filepath, directory, datetime,
-                     parsec >= 2 && < 3, process, time, datetime, regex-posix, xml, split, Diff
-Extra-source-files:  Tests.lhs
-Exposed-modules:     Data.FileStore, Data.FileStore.Types, Data.FileStore.Git, Data.FileStore.Darcs,
-                     -- Data.FileStore.Sqlite3,
-                     Data.FileStore.Utils, Data.FileStore.Generic
-Other-modules:       Paths_filestore
+Homepage:            http://johnmacfarlane.net/repos/filestore
+
 Data-Files:          extra/post-update, CHANGES
-Ghc-Options:         -Wall
-Ghc-Prof-Options:    -auto-all
+Extra-source-files:  Tests.lhs
+
+-- Commented out until Cabal 1.6 becomes common.
+-- Source-repository head
+--    Type:            darcs
+--    Location:        http://johnmacfarlane.net/repos/filestore
+
+Library
+    Build-depends:       base >= 4, bytestring, utf8-string, filepath, directory, datetime,
+                         parsec >= 2 && < 3, process, time, datetime, regex-posix, xml, split, Diff
+
+    Exposed-modules:     Data.FileStore, Data.FileStore.Types, Data.FileStore.Git, Data.FileStore.Darcs,
+                         -- Data.FileStore.Sqlite3,
+                         Data.FileStore.Utils, Data.FileStore.Generic
+    Other-modules:       Paths_filestore
+
+    Ghc-Options:         -Wall
+    Ghc-Prof-Options:    -auto-all
