Hi Ian,

I'm not sure that there is a bug to be fixed here, but I think that in
principle there *could* be.  I've tried to create a scenario where one
would run into trouble, but have failed.

The potential bug here (in Pull, as also discussed below) is that we create
the new pending in pull using as one of its components the following
get_unrecorded:

      mp <- get_unrecorded repository (AnyOrder:opts)

This is of course a lazy operation, which lazily reads the pristine and
working directories.

We then update the pristine cache with a

          repairable $ applyToPristine repository pc

and only after that is the first case where we touch mp:

          unless (isNothing mp && pw_resolved `eq_patches` pc) $
               write_pending repository $ join_patches
                   [invert pc, fromMaybePatch mp, pw_resolved]

At this stage, the lazily computed mp is actually computed (reading the
already-modified pristine cache), and used as part of the new pending
patch.  The resulting patch is probably almost always invalid, but we don't
notice, since write_pending normally filters out all the hunk patches, etc,
through its sift_for_pending.  However, there are times when hunk patches
can't be filtered out (i.e. if there are other interesting changes that
don't commute with the hunks--replaces, for example).  Add and remove
patches are all no problem, since slurp isn't lazy in its directory
reading, and this is most of what keeps the code from being *severely*
buggy.

My solution is to remove the easily-abused-in-this-way write_pending
function, similar to what you did with your write_pending_then.  I also add
a add_to_pending function, which is easier to use in the case where we
aren't modifying the pristine cache, and just want to add a new patch
(i.e. setpref, add, remove, mv and replace).

I think that this interface change will make it much harder to write an
incorrect pending.  Ideally, we would write a single function that updates
both the pristine cache, pending and (optionally?) the working directory.
This interface would also be the most flexible if we introduce other
aspects to our repository (e.g. storing hashes of pristine files, or
perhaps inode numbers of files in the working directory that are identical
to their copies in the pristine cache).

Comments are welcome.  And btw, I don't really like the namespace aspect of
my FilePathUtils module.  It's more than a bit ugly, but I haven't had a
better idea.

Fri Jul 22 08:57:25 EDT 2005  David Roundy <[EMAIL PROTECTED]>
  * replace write_pending with "with_new_pending".
  This patch is basically an extension of Ian's earlier patch that created a
  "write_pending_then" function.  This one creates two functions,
  with_new_pending and add_to_pending.
  
  The idea is that we can't check if a new pending is valid until after we've
  updated the pristine cache.  But it's possible that the pending patch
  itself was lazily generated with get_unrecorded, in which case it's not
  safe to modify the pristine cache until after we've written pending.  This
  new interface makes it much harder to make this kind of mistake.  I also
  think it's pretty intuitive.

New patches:

[replace write_pending with "with_new_pending".
David Roundy <[EMAIL PROTECTED]>**20050722125725
 This patch is basically an extension of Ian's earlier patch that created a
 "write_pending_then" function.  This one creates two functions,
 with_new_pending and add_to_pending.
 
 The idea is that we can't check if a new pending is valid until after we've
 updated the pristine cache.  But it's possible that the pending patch
 itself was lazily generated with get_unrecorded, in which case it's not
 safe to modify the pristine cache until after we've written pending.  This
 new interface makes it much harder to make this kind of mistake.  I also
 think it's pretty intuitive.
] 
<
> {
hunk ./Add.lhs 33
 import DarcsUtils ( withCurrentDirectory, nubsort )
 import IsoDate ( getIsoDateTime )
 import Repository ( amInRepository, withRepoLock,
-                    slurp_pending, read_pending, write_pending )
-import Patch ( Patch, is_null_patch, apply_to_slurpy, addfile, adddir, move,
-               join_patches, flatten,
-             )
+                    slurp_pending, add_to_pending )
+import Patch ( Patch, apply_to_slurpy, addfile, adddir, move, join_patches )
 import SlurpDirectory ( Slurpy, slurp_has_anycase, slurp_has,
                         isFileReallySymlink, doesDirectoryReallyExist, 
                         doesFileReallyExist, slurp_hasdir,
hunk ./Add.lhs 118
     ps <- addp msgs opts date cur $ nboring flist
     when (null ps && not (null args)) $ do
         fail "No files were added"
-    when (not gotDryRun) $ do
-        pend <- read_pending repository
-        case pend of
-            Nothing -> write_pending repository $ join_patches
-                     $ filter (not . is_null_patch) ps
-            Just op -> write_pending repository $ join_patches $
-                       flatten $ join_patches [op,join_patches ps]
+    when (not gotDryRun) $ add_to_pending repository (join_patches ps)
   where
     gotDryRun = DryRun `elem` opts
     msgs | gotDryRun = dryRunMessages
hunk ./AmendRecord.lhs 26
 import SignalHandler ( withSignalsBlocked )
 import Repository ( PatchSet,
                     withRepoLock, get_unrecorded, slurp_recorded,
-                    write_pending, sync_repo,
+                    with_new_pending, sync_repo,
                   )
 import DarcsRepo ( read_repo,
                    add_to_inventory, write_patch,
hunk ./AmendRecord.lhs 132
                                     exitWith $ ExitFailure 1
                        write_patch opts $ newp
                        remove_from_unrevert_context [oldp]
-                       withSignalsBlocked $ do
+                       withSignalsBlocked $
+                         with_new_pending repository (join_patches unrec) $ do
                          pris <- identifyPristine
                          applyPristine pris (join_patches chs) `catch`
                              \e -> fail ("Bizarre error in amend-recording:\n" ++ show e)
hunk ./AmendRecord.lhs 142
                          write_inventory "." $ rempatch oldp patches'
                          add_to_inventory "."
                                          [(fromJust $ patch2patchinfo newp)]
-                         write_pending repository $ join_patches unrec
-                         sync_repo repository
-                         putStrLn "Finished amending patch:"
-                         putDocLn $ human_friendly $ fromJust
-                                  $ patch2patchinfo newp
+                       sync_repo repository
+                       putStrLn "Finished amending patch:"
+                       putDocLn $ human_friendly $ fromJust
+                                    $ patch2patchinfo newp
 \end{code}
 
 If you configure darcs to run a test suite, darcs will run this test on the
hunk ./Apply.lhs 23
 import Prelude hiding ( catch )
 import IO ( hClose, stdin, stdout, stderr )
 import Control.Exception ( catch, throw, Exception( ExitException ) )
-import Monad ( when, unless, liftM )
+import Monad ( when, liftM )
 import DarcsUtils ( nubsort )
hunk ./Apply.lhs 25
-import Maybe ( catMaybes, isNothing )
+import Maybe ( catMaybes )
 
 import SignalHandler ( withSignalsBlocked )
 import DarcsCommands ( DarcsCommand(..) )
hunk ./Apply.lhs 45
 import qualified DarcsArguments ( cc )
 import Repository ( PatchSet, withRepoLock, amInRepository,
                     get_unrecorded, slurp_pending, slurp_recorded,
-                    write_pending, sync_repo, read_repo, updateInventory,
+                    with_new_pending, sync_repo, read_repo, updateInventory,
                     applyToPristine,
                   )
 import Patch ( Patch, patch2patchinfo, invert, list_touched_files,
hunk ./Apply.lhs 49
-               join_patches, unjoin_patches, eq_patches, null_patch,
+               join_patches, unjoin_patches, null_patch,
              )
 import qualified Patch (apply)
 import PatchInfo ( human_friendly )
hunk ./Apply.lhs 180
               exitWith $ ExitFailure 1
     tokens <- save_patches repository opts $ unjoin_patches us_patch
     mp <- get_unrecorded repository (AnyOrder:opts)
-    withSignalsBlocked $ do
+    let npend = join_patches [invert us_patch, fromMaybePatch mp, pw_resolved]
+    withSignalsBlocked $ with_new_pending repository npend $ do
       applyToPristine repository us_patch `catch` \e ->
           fail ("Error applying patch to recorded!\nRunning 'darcs repair' on the target repo may help.\n" ++ show e)
       wait_a_moment -- so work will be more recent than rec
hunk ./Apply.lhs 188
       updateInventory repository tokens
       Patch.apply pw_resolved `catch` \e ->
           fail ("Error applying patch to working dir:\n" ++ show e)
-      unless (isNothing mp && pw_resolved `eq_patches` us_patch) $
-           write_pending repository $ join_patches
-               [invert us_patch, fromMaybePatch mp, pw_resolved]
     sync_repo repository
     putStrLn "Finished applying..."
     exitWith ExitSuccess
hunk ./DarcsRepo.lhs 54
                     withRecorded,
                     slurp_all_but_darcs,
                     surely_slurp_Pristine,
-                    read_pending, write_pending,
+                    read_pending, with_new_pending,
                     write_inventory, add_to_inventory, read_repo,
                     lazily_read_repo, sync_repo,
                     get_markedup_file,
hunk ./DarcsRepo.lhs 69
 
 import Directory ( createDirectory, setCurrentDirectory, doesFileExist,
                    doesDirectoryExist )
-import Workaround ( getCurrentDirectory )
+import Workaround ( getCurrentDirectory, renameFile )
 import DarcsUtils ( withCurrentDirectory, bugDoc )
 import System.IO ( hPutStrLn, stderr )
 import System.IO.Unsafe ( unsafeInterleaveIO )
hunk ./DarcsRepo.lhs 74
 import Monad ( liftM, when, unless )
-import Maybe ( maybeToList )
+import Maybe ( maybeToList, isNothing )
 import SignalHandler ( withSignalsBlocked )
 import FastPackedString ( PackedString, packString, gzReadFilePS,
                           breakOnPS, nullPS )
hunk ./DarcsRepo.lhs 167
 
 \begin{code}
 read_pending :: String -> IO (Maybe Patch)
-write_pending :: String -> Patch -> Slurpy -> IO ()
-
 read_pending name = do
   pend <- gzReadFilePS name `catch`
           (\_ -> return $ packString "")
hunk ./DarcsRepo.lhs 174
     Nothing -> return Nothing
     Just (p,_) -> return $ if is_null_patch p then Nothing else Just p
 
-write_pending name origp cur =
- let p = sift_for_pending origp in
- if is_null_patch p
- then writePatch name p
- else do
-  case apply_to_slurpy p cur of
-    Just _ -> writePatch name p
-    Nothing -> do
-      writeBinFile (name ++ "_buggy") ""
-      writePatch (name ++ "_buggy") p
+with_new_pending :: String -> Patch -> IO Slurpy -> IO ()
+with_new_pending name origp job =
+ do let p = sift_for_pending origp
+        newname = name ++ ".new"
+    writePatch newname p
+    mp <- read_pending newname
+    cur <- job
+    unless (isNothing mp) $
+      when (isNothing $ apply_to_slurpy (fromJust mp) cur) $ do
+      let buggyname = name ++ "_buggy"
+      renameFile newname buggyname
       bugDoc $ text "There was an attempt to write an invalid pending!"
hunk ./DarcsRepo.lhs 186
-            $$ text "If possible, please send the contents of _darcs/patches/pending_buggy"
+            $$ text "If possible, please send the contents of"
+               <+> text buggyname
             $$ text "along with a bug report."
hunk ./DarcsRepo.lhs 189
+    renameFile newname name
 
 sift_for_pending :: Patch -> Patch
 sift_for_pending patch =
hunk ./Mv.lhs 30
 import Directory ( renameDirectory )
 import Workaround ( renameFile )
 import Repository ( identifyRepository, withRepoLock, amInRepository,
-                    slurp_pending, read_pending, write_pending,
+                    slurp_pending, add_to_pending,
                   )
hunk ./Mv.lhs 32
-import Patch ( join_patches, flatten, move )
+import Patch ( join_patches, move )
 import SlurpDirectory ( Slurpy, slurp, slurp_has,
                         slurp_hasdir, slurp_hasfile, slurp_has_anycase )
 import FileName ( fp2fn, fn2fp, super_name )
hunk ./Mv.lhs 96
    then move_to_dir opts [old] new
    else do
     cur <- slurp_pending repository
-    pend <- read_pending repository
     check_new_and_old_filenames opts cur work (old,new)
     withSignalsBlocked $ do
       move_file_or_dir work old new
hunk ./Mv.lhs 99
-      case pend of
-          Nothing -> write_pending repository $ move old new
-          Just op -> write_pending repository $ join_patches $
-                     flatten $ join_patches [op, move old new]
+      add_to_pending repository (move old new)
 \end{code}
 
 \begin{code}
hunk ./Mv.lhs 118
     repository <- identifyRepository "."
     cur <- slurp_pending repository
     work <- slurp "."
-    pend <- read_pending repository
     mapM_ (check_new_and_old_filenames opts cur work) $ zip moved movetargets
     withSignalsBlocked $ do
       sequence_ $ map2 (move_file_or_dir work) moved movetargets
hunk ./Mv.lhs 121
-      case pend of
-          Nothing -> write_pending repository $ join_patches movepatches
-          Just op -> write_pending repository $ join_patches $
-                     flatten $ join_patches (op: movepatches)
+      add_to_pending repository (join_patches movepatches)
 
 check_new_and_old_filenames
     :: [DarcsFlag] -> Slurpy -> Slurpy -> (FilePath, FilePath) -> IO ()
hunk ./Pull.lhs 22
               check_unrecorded_conflicts,
             ) where
 import System ( ExitCode(..), exitWith )
-import Monad ( when, unless, liftM )
-import Maybe ( catMaybes, isNothing )
+import Monad ( when, liftM )
+import Maybe ( catMaybes )
 
 import SignalHandler ( withSignalsBlocked )
 import DarcsCommands ( DarcsCommand(..) )
hunk ./Pull.lhs 41
                     amInRepository, withRepoLock,
                     slurp_recorded, slurp_recorded_and_unrecorded,
                     read_repo, absolute_dir, get_unrecorded,
-                    write_pending, read_pending, sync_repo,
+                    with_new_pending, read_pending, sync_repo,
                     applyToPristine, writePatch, updateInventory,
                   )
 import Patch ( Patch, join_patches, merge, patch2patchinfo,
hunk ./Pull.lhs 46
                unjoin_patches, list_touched_files,
-               invert, list_conflicted_files, eq_patches, null_patch,
+               invert, list_conflicted_files, null_patch,
                apply,
              )
 import SelectChanges ( promptChar )
hunk ./Pull.lhs 170
                   exitWith $ ExitFailure 1
       patchTokens <- save_patches repository opts $ unjoin_patches pc
       mp <- get_unrecorded repository (AnyOrder:opts)
-      withSignalsBlocked $ do
+      let newpend = join_patches [invert pc, fromMaybePatch mp, pw_resolved]
+      withSignalsBlocked $ with_new_pending repository newpend $ do
           repairable $ applyToPristine repository pc
             `catch` \e ->
                 fail ("Error applying patch to recorded.\nRunning 'darcs repair' on the target repo may help.\n" ++ show e)
hunk ./Pull.lhs 176
           updateInventory repository patchTokens
-          unless (isNothing mp && pw_resolved `eq_patches` pc) $
-               write_pending repository $ join_patches
-                   [invert pc, fromMaybePatch mp, pw_resolved]
           -- so work will be more recent than rec:
           revertable wait_a_moment
           revertable $ apply pw_resolved `catch` \e ->
hunk ./Record.lhs 40
 import Lock ( readBinFile, withTemp )
 import Repository ( amInRepository, identifyRepository, withRepoLock,
                     get_unrecorded,
-                    write_pending, sync_repo, read_repo,
+                    with_new_pending, sync_repo, read_repo,
                     slurp_recorded, updateInventory, writePatch,
                     applyToPristine, patchTokenToPatchFile,
                   )
hunk ./Record.lhs 205
                          Nothing -> return ()
                  when (Verbose `elem` opts) $
                      putStrLn "Applying to current..."
-                 withSignalsBlocked $ do
+                 withSignalsBlocked $
+                   with_new_pending repository (join_patches skipped) $ do
                    applyToPristine repository mypatch'
                    updateInventory repository [(myinfo, token)]
hunk ./Record.lhs 209
-                   write_pending repository $ join_patches skipped
                  when (Verbose `elem` opts) $
                      putStrLn "Syncing timestamps..."
                  sync_repo repository
hunk ./Remove.lhs 28
                         working_repo_dir,
                       )
 import Repository ( identifyRepository, withRepoLock, amInRepository,
-                    slurp_pending, read_pending, write_pending,
+                    slurp_pending, add_to_pending,
                   )
hunk ./Remove.lhs 30
-import Patch ( Patch, rmdir, join_patches, flatten )
+import Patch ( Patch, rmdir, join_patches )
 import SlurpDirectory ( slurp_removedir, slurp_removefile )
 import RepoPrefs ( filetype_function )
 import Diff ( smart_diff )
hunk ./Remove.lhs 77
 remove_cmd opts relargs = let args = map (fix_filepath opts) relargs in
     withRepoLock $ \repository -> do
     p <- make_remove_patch args
-    pend <- read_pending repository
-    case pend of
-        Nothing -> write_pending repository p
-        Just op -> write_pending repository $ join_patches $
-                   flatten $ join_patches [op,p]
+    add_to_pending repository p
 
 make_remove_patch :: [FilePath] -> IO Patch
 make_remove_patch files = do repository <- identifyRepository "."
hunk ./Replace.lhs 26
 import DarcsCommands
 import DarcsArguments
 import Repository ( withRepoLock,
-                    slurp_pending, read_pending, write_pending,
+                    slurp_pending, add_to_pending,
                   )
 import DarcsRepo ( am_in_repo, slurp_recorded_and_unrecorded
                  )
hunk ./Replace.lhs 31
 import Patch ( apply, apply_to_slurpy, tokreplace, force_replace_slurpy,
-               join_patches, flatten, Patch,
+               join_patches, Patch,
              )
 import SlurpDirectory ( slurp_hasfile, Slurpy )
 import FileName ( fp2fn )
hunk ./Replace.lhs 137
       fail $ "Can't do replace on working!\n"
           ++ "Perhaps one of the files already contains '"++ new++"'?\n"
           ++ show e
-  pend <- read_pending repository
-  write_pending repository $ join_patches $
-      maybe [] flatten pend ++ fst (unzip ps_and_pswork)
+  add_to_pending repository (join_patches $ fst $ unzip ps_and_pswork)
   where fs = map (fix_filepath opts) relfs
         ftf _ = TextFile
 
hunk ./Repository.lhs 23
                     slurp_recorded, slurp_recorded_and_unrecorded,
                     get_unrecorded, read_repo, sync_repo, absolute_dir,
                     prefsUrl,
-                    read_pending, write_pending, withRepoLock,
+                    read_pending, with_new_pending, add_to_pending,
+                    withRepoLock,
                     PatchToken, patchTokenToPatchFile,
                     writePatch, updateInventory, unrevertUrl,
                     applyToPristine,
hunk ./Repository.lhs 187
 read_pending (Repo r _ tp) =
     withCurrentDirectory r (DarcsRepo.read_pending (pendingName tp))
 
-write_pending :: Repository -> Patch -> IO ()
-write_pending repo@(Repo r _ tp) p =
-    do pristine <- slurp_recorded repo
-       withCurrentDirectory r
-           (DarcsRepo.write_pending (pendingName tp) p pristine)
+add_to_pending :: Repository -> Patch -> IO ()
+add_to_pending repo p =
+    do pend <- read_pending repo
+       let pnew = case pend of Nothing -> p
+                               Just pold -> join_patches [pold, p]
+       with_new_pending repo pnew (return ())
+
+with_new_pending :: Repository -> Patch -> IO () -> IO ()
+with_new_pending repo@(Repo r _ tp) p job =
+    withCurrentDirectory r $
+    DarcsRepo.with_new_pending (pendingName tp) p $ job >> slurp_recorded repo
 
 unempty :: [a] -> Maybe [a]
 unempty [] = Nothing
hunk ./Resolve.lhs 28
                         ignoretimes, verbose, working_repo_dir,
                       )
 import Repository ( withRepoLock, amInRepository,
-                    read_repo, sync_repo, get_unrecorded, write_pending,
+                    read_repo, sync_repo, get_unrecorded, with_new_pending,
                     )
 import Patch ( join_patches, invert, apply, is_null_patch )
 import Resolution ( patchset_conflict_resolutions )
hunk ./Resolve.lhs 85
                  apply (invert p) `catch` \e ->
                     bug ("Can't undo pending changes!" ++ show e)
                  sync_repo repository
-  withSignalsBlocked $
-      do apply res `catch` \e ->
-             bug ("Problem resolving conflicts in resolve!" ++ show e)
-         write_pending repository res
-         putStrLn "Finished resolving."
+  withSignalsBlocked $ with_new_pending repository res $
+      apply res `catch` \e ->
+      bug ("Problem resolving conflicts in resolve!" ++ show e)
+  putStrLn "Finished resolving."
 resolve_cmd _ _ = impossible
 \end{code}
 
hunk ./Revert.lhs 34
 import DarcsUtils ( askUser )
 import Repository ( withRepoLock,
                     get_unrecorded,
-                    write_pending, sync_repo,
+                    with_new_pending, sync_repo,
                     amInRepository, slurp_recorded_and_unrecorded,
                   )
 import Patch ( join_patches, invert, is_null_patch,
hunk ./Revert.lhs 111
                           _ -> exitWith $ ExitSuccess
              write_unrevert (join_patches skipped') p rec
              withSignalsBlocked $
-                 do apply (invert $ join_patches p) `catch` \e ->
-                        fail ("Unable to apply inverse patch!" ++ show e)
-                    write_pending repository $ join_patches skipped'
-             sync_repo repository
-             putStrLn "Finished reverting."
+                 with_new_pending repository (join_patches skipped')$
+                 apply (invert $ join_patches p) `catch` \e ->
+                 fail ("Unable to apply inverse patch!" ++ show e)
+  sync_repo repository
+  putStrLn "Finished reverting."
 \end{code}
 
hunk ./Rollback.lhs 26
                         verbose, working_repo_dir, nocompress,
                         match_one_nontag,
                       )
-import Repository ( amInRepository, withRepoLock, read_pending, write_pending,
+import Repository ( amInRepository, withRepoLock, read_pending,
+                    with_new_pending,
                     applyToPristine, writePatch, updateInventory,
                   )
 import Patch ( join_patches, invert, patch2patchinfo, null_patch, )
hunk ./Rollback.lhs 88
           fail "cannot roll back a 'tag' patch."
       Just pinfo | not (is_inverted pinfo) ->
           fail "cannot roll back a 'rollback' patch."
-      Just pinfo -> do (_, t) <- writePatch repository opts $ invert p
-                       withSignalsBlocked $
-                           do applyToPristine repository (invert p) `catch`
-                                  \e ->
-                                      fail ("Unable to apply inverse patch!\n"
-                                            ++ show e)
-                              write_pending repository $ join_patches [p, pend]
-                              updateInventory repository [(pinfo, t)]
-                       putStrLn "Finished rolling back."
+      Just pinfo ->
+          do (_, t) <- writePatch repository opts $ invert p
+             let newpend = join_patches [p, pend]
+             withSignalsBlocked $ with_new_pending repository newpend $
+               do applyToPristine repository (invert p) `catch` \e ->
+                      fail ("Unable to apply inverse patch!\n" ++ show e)
+                  updateInventory repository [(pinfo, t)]
+             putStrLn "Finished rolling back."
 \end{code}
 
hunk ./SetPref.lhs 25
 
 import DarcsCommands ( DarcsCommand(..), nodefaults )
 import DarcsArguments ( DarcsFlag, )
-import Repository ( identifyRepository, amInRepository,
-                    write_pending, read_pending )
-import Patch ( flatten, join_patches, changepref, )
+import Repository ( identifyRepository, amInRepository, add_to_pending )
+import Patch ( changepref )
 import RepoPrefs ( get_prefval, change_prefval, )
 #include "impossible.h"
 \end{code}
hunk ./SetPref.lhs 112
                       Nothing -> return ""
   change_prefval pref old val
   putStrLn $ "Changing value of "++pref++" from '"++old++"' to '"++val++"'"
-  pend <- read_pending repository
-  case pend of
-      Nothing -> write_pending repository $
-                     join_patches [changepref pref old val]
-      Just op -> write_pending repository $
-                     join_patches $ flatten op ++ [changepref pref old val]
+  add_to_pending repository (changepref pref old val)
 setpref_cmd _ _ = impossible
 \end{code}
 
hunk ./Unrecord.lhs 34
              )
 import Repository ( PatchSet, withRepoLock, slurp_recorded,
                     get_unrecorded,
-                    read_pending, write_pending, sync_repo,
+                    read_pending, with_new_pending, sync_repo,
                   )
 import DarcsRepo ( read_repo,
                    write_inventory, write_patch,
hunk ./Unrecord.lhs 155
        when (null to_unrecord) $ do putStrLn "No patches selected!"
                                     exitWith ExitSuccess
        remove_from_unrevert_context to_unrecord
-       withSignalsBlocked $ do
+       let newpend = join_patches (to_unrecord ++ pend)
+       withSignalsBlocked $ with_new_pending repository newpend $ do
           when (Verbose `elem` opts) $
                putStrLn "About to write out (potentially) modified patches..."
           let (_, skipped) = commute_to_end to_unrecord allpatches
hunk ./Unrecord.lhs 169
           pris <- identifyPristine
           applyPristine pris (invert $ join_patches to_unrecord) `catch` \e ->
               fail ("Unable to apply inverse patch!\n" ++ show e)
-          when (Verbose `elem` opts) $ putStrLn "Updating pending..."
-          write_pending repository $ join_patches (to_unrecord ++ pend)
           sync_repo repository
           putStrLn "Finished unrecording."
 
hunk ./Unrecord.lhs 295
         when (null ps) $ do putStrLn "No patches selected!"
                             exitWith ExitSuccess
         remove_from_unrevert_context ps
-        withSignalsBlocked $ do
+        withSignalsBlocked $ with_new_pending repository pend' $ do
            let (_, skipped) = commute_to_end ps allpatches
            sequence_ $ map (write_patch opts) skipped
            repo_patches <- read_repo "."
hunk ./Unrecord.lhs 305
                fail ("Unable to apply inverse patch!\n" ++ show e)
            apply (invert p_after_pending) `catch` \e ->
                fail ("Couldn't undo patch in working dir.\n" ++ show e)
-           write_pending repository pend'
-           sync_repo repository
-           putStrLn "Finished unpulling."
+        sync_repo repository
+        putStrLn "Finished unpulling."
 \end{code}
 
hunk ./Unrevert.lhs 31
 import Directory ( removeFile )
 import Repository ( PatchSet, identifyRepository, withRepoLock,
                     slurp_recorded, unrevertUrl,
-                    read_pending, write_pending,
+                    read_pending, with_new_pending,
                     sync_repo,
                     read_repo, amInRepository,
                     slurp_recorded_and_unrecorded,
hunk ./Unrevert.lhs 106
         let pend_and_p = case pend of
                          Nothing -> join_patches p
                          Just pending -> join_patches (pending : p)
-        withSignalsBlocked $
+        withSignalsBlocked $ with_new_pending repository pend_and_p $
           do
              apply (join_patches p) `catch` \e ->
                  fail ("Error applying unrevert to working directory...\n"
hunk ./Unrevert.lhs 112
                     ++ show e)
              write_unrevert pend_and_p skipped rec
-             write_pending repository pend_and_p
         sync_repo repository
         putStrLn "Finished unreverting."
 unrevert_cmd _ _ = impossible
}

Context:

[Make DarcsRepo.add_to_inventory take a list.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050720174029
 This avoids opening the inventory multiple times.  Thanks to Ian for the hint.
] 
[Use mapM_ instead of the comprehensible alternative.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050720164258
 Mentioning mapM_ always impresses people at dinner parties.  Thanks to
 Ian for the hint.
] 
[Move iterateGitTree out of the IO monad.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050720162841
 We're reading immutable on-disk data, it's safe to do it unsafely.
] 
[Clean up usage of interleaveIO in Git.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050720162251] 
[fix error in name of --reorder-patches flag.
David Roundy <[EMAIL PROTECTED]>**20050722110752] 
[TAG 1.0.4pre1
David Roundy <[EMAIL PROTECTED]>**20050718112234] 
[make configure automatically guess the release state based on defaultrepo and tags.
David Roundy <[EMAIL PROTECTED]>**20050718112222] 
[Push and pull can now show the detailed diffs of patches
Jim Radford <[EMAIL PROTECTED]>**20050717042645
 The same distinction is now made between --summary and --verbose
 as changes makes.
] 
[TAG 2005-07-18
Ian Lynagh <[EMAIL PROTECTED]>**20050718193534] 
[fix write_problem to show all problems.
David Roundy <[EMAIL PROTECTED]>**20050717110628] 
[Rename bound variable in fromJust macro.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050716221705
 Avoids ``shadows existing variable'' warnings which for some reason are
 errors.
 
 Could we please use Lisp macros instead?
] 
[bugfix, make _darcs/prefs/defaults really override $HOME/.darcs/defaults
Tommy Pettersson <[EMAIL PROTECTED]>**20050612174925
 Variants of the same flag from the two defaults files where just merged,
 and an ALL in the local defaults could not override an explicit command
 in the global defaults, as would be expected.
] 
[use AC_SEARCH_LIBS instead of AC_CHECK_LIB
Wim Lewis <[EMAIL PROTECTED]>**20050707181811] 
[Update AC_PREREQ to 2.54
Wim Lewis <[EMAIL PROTECTED]>**20050707181631
 The form of AC_C_BIGENDIAN used here didn't show up until 2.53 or 2.54.
 Also, no need to specify the third arg, since it defaults to erroring out anyway.
] 
[TAG 2005-007-16
Ian Lynagh <[EMAIL PROTECTED]>**20050716181541] 
[don't import head and tail, which are in the prelude.
David Roundy <[EMAIL PROTECTED]>**20050716143547] 
[Keep file modes in dirty Git slurpies.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050716071846
 This prevents Darcs from resetting Git file permissions.
] 
[Update HEAD in place.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050716071116] 
[Generalise write_pending.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050716002145
 I missed this, which breaks add and remove.
] 
[Use emptyGitSlurpy in gitCommitToPatch'.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050715234115] 
[Fix parsing of Git merges with no common ancestor.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050715233226] 
[Implement emptyGitSlurpy.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050715233211] 
[Fix typo in applyF_direct (Git).
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050715233140] 
[Don't include ./ when generating patches from Git.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050715203248] 
[Generalise rollback.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050715194322] 
[Make histories that come from Git lazy in the presence of merges.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050715193440
 Use the fact that we know the length of the result of a merge to produce a
 spine-lazy list of patches.  This makes ``darcs changes'' never touch
 a blob.
] 
[Make darcs understand Git n-ary merges.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050715192333] 
[move read/write format checks into identifyRepository and withRepoLock.
David Roundy <[EMAIL PROTECTED]>**20050714105840] 
[Generalise Pull and Apply.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050712145643] 
[Generate Git PatchInfos from scratch.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050712123945
 patchtopatchinfo is not lazy enough.
] 
[Replace frobPatchFile with patchTokenToPatchFile.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050711045246] 
[Make writing of patches work in arbitrary directories.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050711021014] 
[Use impossible.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050711015640] 
[Make patch tokens opaque.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050711014829] 
[cleanups in RepoFormat as suggested by Ian.
David Roundy <[EMAIL PROTECTED]>**20050711125711] 
[fix typo in git prefsUrl.
David Roundy <[EMAIL PROTECTED]>**20050711100531] 
[generalize Revert and Unrevert.
David Roundy <[EMAIL PROTECTED]>**20050711100429] 
[fix bug where we failed to convert sha1 to hex.
David Roundy <[EMAIL PROTECTED]>**20050711092602] 
[Only read darcs/cgi.conf once.
Wim Lewis <[EMAIL PROTECTED]>**20050623081319
 Modified read_conf() so it caches the parsed configuration values
 in a hash, instead of re-opening and re-reading the configuration
 file several times per CGI invocation. (A probably-unimportant side
 effect of this is that flag names can no longer contain spaces, but
 that shouldn't affect anybody.)
] 
[Make record repository-format agnostic.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050710034630] 
[Implement polymorphic write support.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050710034310] 
[Make withRepoLock polymorphic.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050710023802] 
[Make writePatch and updateInventory polymorphic.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050710021543] 
[Make sync_repo polymorphic.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050710021426] 
[Import GitRepo from darcs-git.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050710015221
 This version has write support and support for reverse-engineering
 Darcs merges from Git merges.
] 
[Add ``lax'' argument to applyToGitSlurpy.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050710014814
 When lax is true, we apply merger_equivalent to mergers.
] 
[Make read/write_pending polymorphic.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050710012515] 
[don't go through shell when execing darcs
Wim Lewis <[EMAIL PROTECTED]>**20050710062743
 Use the LIST variant of exec to avoid exposing the arguments of the darcs
 command to shell interpretation. Also, pipe the output directly to where
 it's going instead of reading it in and writing it out again.
] 
[fix incorrectly quoted regexp
Wim Lewis <[EMAIL PROTECTED]>**20050710051424
 Unquoted regexp evaluated to 0 or 1, which didn't immediately break the cgi
 because most hashes have those characters in them. Also fixed a bogus
 initializer caught by "perl -w".
] 
[update comments in darcs.cgi
Wim Lewis <[EMAIL PROTECTED]>**20050710050226] 
[Use a pipe instead of a temp file
Wim Lewis <[EMAIL PROTECTED]>**20050710005052
 Instead of storing the intermediate XML in a temporary file and then invoking
 xsltproc, just pipe the XML directly into the xslt processor on the fly.
] 
[use darcs_xml() where it simplifies things
Wim Lewis <[EMAIL PROTECTED]>**20050709023659] 
[Fix make_changelog to work with David's new identifyRepository.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050710002419] 
[Fix typo in import of malloc.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050710001235] 
[Add comment about immutability of Git trees.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050709215815] 
[Fix location of HEAD in Git.updateHead.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050709215408] 
[implement missing DarcsIO methods in SlurpMonad.
David Roundy <[EMAIL PROTECTED]>**20050709192216] 
[clean up GitTreeIterator.
David Roundy <[EMAIL PROTECTED]>**20050709174440] 
[eliminate excess touching in Git.
David Roundy <[EMAIL PROTECTED]>**20050709170954] 
[make GitFileInfo a cleaner more haskellish data type.
David Roundy <[EMAIL PROTECTED]>**20050709170457] 
[add some typesafety to haskell cache_entry-related Git code.
David Roundy <[EMAIL PROTECTED]>**20050709153935] 
[add a bit of type safety to the pointers to git_tree_iterator.
David Roundy <[EMAIL PROTECTED]>**20050709153337] 
[make GitFile use the ffi more nicely.
David Roundy <[EMAIL PROTECTED]>**20050709152131] 
[replace fromSingleton with gitSingleCommitValue which gives better error message.
David Roundy <[EMAIL PROTECTED]>**20050709145616] 
[implement CString utility functions in FastPackedString.
David Roundy <[EMAIL PROTECTED]>**20050709145549] 
[use withSlurpy to implement apply_to_slurpy.
David Roundy <[EMAIL PROTECTED]>**20050709145517] 
[make darcs send look in the right place for target email address.
David Roundy <[EMAIL PROTECTED]>**20050709121505] 
[fix bug in Repository abstraction code that broke remote pulls.
David Roundy <[EMAIL PROTECTED]>**20050709120518
 This change adds to the Repository data object the URL of the repository in
 question, allowing us to use this abstraction with both remote and local
 repositories.
] 
[add support for repository format checking.
David Roundy <[EMAIL PROTECTED]>**20050709112017
 The idea being to be forward-compatible with repository format changes.
] 
[add an unused RepoFormat module.
David Roundy <[EMAIL PROTECTED]>**20050430123937] 
[Documentation nits & typos
Wim Lewis <[EMAIL PROTECTED]>**20050618193852] 
[Merge conflicts in configure.ac, and add blank line to try to avoid future conflicts
Ian Lynagh <[EMAIL PROTECTED]>**20050707160658] 
[TAG 1.0.3
Tomasz Zielonka <[EMAIL PROTECTED]>**20050524215127] 
[bump version to 1.0.3
Tomasz Zielonka <[EMAIL PROTECTED]>**20050524215115] 
[Revert an accidental Repository -> DarcsRepo change in a string
Ian Lynagh <[EMAIL PROTECTED]>**20050707160431] 
[Revert "Cache pristine directory within NoPristine"
Ian Lynagh <[EMAIL PROTECTED]>**20050707153500] 
[fixed a few typos in docs & comments
Wim Lewis <[EMAIL PROTECTED]>**20050624070640] 
[make git support configurable (copied from Juliusz's patch).
David Roundy <[EMAIL PROTECTED]>**20050701135046] 
[TAG another version that works in the git-merge saga.
David Roundy <[EMAIL PROTECTED]>**20050701133252] 
[fix errors from merging more darcs-git stuff.
David Roundy <[EMAIL PROTECTED]>**20050701133228] 
[resolve some more conflicts.
David Roundy <[EMAIL PROTECTED]>**20050701132446] 
[TAG working version in middle of darcs-git merge.
David Roundy <[EMAIL PROTECTED]>**20050701125730] 
[resolve conflicts between git and darcs-unstable.
David Roundy <[EMAIL PROTECTED]>**20050701125706] 
[Cache pristine directory within NoPristine.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050426172006] 
[eliminate unnecesary unsafePerformIOs in Git.
David Roundy <[EMAIL PROTECTED]>**20050701142312] 
[Move gitIsTree to C code.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050509235651] 
[Simplify gitBlobToPatches.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050509234445] 
[Remove obsolete comment.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050507195543] 
[Make ordering of trees Linus-compatible.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050507184412] 
[Don't sort when purifying Git slurpies.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050507024134
 The new ordering is preserved by purification.
] 
[Replace the definition of Ord on GitSlurpy with one that works.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050507023832
 This is still not Linus-compliant, as Haskell and C use different ordering
 conventions.
] 
[Fix typo in noname.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050506222328] 
[Make gitFooToPatches work with dirty trees.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050506200939] 
[Export GitSlurpy.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050506181048] 
[Implement a variant of gitCommitToPatch that takes a GitSlurpy reference.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050506180031] 
[Get rid of gitCommitToPIMP.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050505181603] 
[Move reading git commits out of the IO monad.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050505180609] 
[Simplify generation of PatchSets from Git repos.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050505170207] 
[Fix parsing of multiple parents in Git commits.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050505153025
 Multiple parents come in separate parent lines, not a single line as I
 thought.
] 
[Fix Git date handling.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504233745] 
[Fix formatting of Git files.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504211643] 
[Fix formatting of Git records.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504210607] 
[Only free those names that were allocated in git_write_tree_done.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504204933] 
[Free the right buffer in git_write_tree_done.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504204910] 
[Estimate the size of a new tree correctly.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504204850] 
[Actually create new .git/HEAD (blush).
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504204825] 
[Use "." as root of GitSlurpies.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504203304] 
[Implement updateHead.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504193546] 
[Implement git_update_head.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504193529] 
[Implement writeGitCommit.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504192232] 
[Add type argument to writeGitFile.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504185421] 
[Make slurpGitCommit return a GitSlurpy after all.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504143935] 
[Implement make_git_file_info.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504142613] 
[Implement purification of Git trees.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504142042] 
[Actually implement purification of blobs.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504125709] 
[Add repo argument to purify.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050503234432] 
[Partial implementation of purifyGitSlurpy.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050503232848] 
[Generalise trackdown.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050426233012] 
[Make whatsnew go through Repository.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050426162106
 This won't work for Git repositories until they implement slurp_recorded
 and get_recorded.
] 
[Implement git_format_time.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504192053] 
[Export Slurpy constructors.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050426195817] 
[Export applyBinary and applyHunkLines.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050503224204] 
[Really don't include directories in slurpies.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050429235609] 
[Make dist work with git repositories.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050426203906] 
[Fix merge conflicts.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050425194100] 
[Remove unsafeConstructPS.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050509233129] 
[Declare Git's global variables as extern.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050507224710
 Silly GHCi doesn't grok common symbols.
] 
[Use RepoPrefs.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050506220257] 
[Implement repoPrefs.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050506220152] 
[Export PatchInfo constructor.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050504190531] 
[Implement applyToGitSlurpy.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050503231941] 
[Basic implementation of dirty Git slurpies.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050503222642] 
[Use the cache when slurping the pristine state.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050430000813] 
[Restructure patch generation from Git repos.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050427213320] 
[Don't store directories in slurpies.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050427000833] 
[Instance Show Slurpy.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050426235914] 
[Start slurping at ".".
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050426203853] 
[Implement slurping from git repositories.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050426195957] 
[Make pattern exhaustive.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050426195941] 
[Check for presence of .git/HEAD.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050426195914] 
[Move slurp_pending and slurp_recorded into Repository.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050426185425] 
[Move get_unrecorded to Repository.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050426175527] 
[Implement send for git repositories.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050425210728] 
[Implement changes for git repositories.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050425205329] 
[Use ForeignPtrs instead of raw pointers when useful.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050425180449
 Now I remember why I hate Haskell.
] 
[Some less IO monad hacking.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050425180207] 
[Fix handling of subtrees.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050425162405] 
[Implement subtrees.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050425063228] 
[Parse new-style git dates.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050425001902] 
[Initial implementation of pulling from git.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050424213832] 
[Add licence statements to Linus' files.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050426161330] 
[Implement constructPS.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050425180306
 I use touchForeignPtr in the finaliser when building a PS from a
 ForeignPtr.
] 
[Import parts of Linus' git 0.6.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050424213310] 
[Implement unsafeConstructPS.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050424212204] 
[Export diff_files from Diff.lhs.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050424212113] 
[Export emptyFileContents from SlurpDirectory.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050424212051] 
[First cut at remodularising repo access.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050424145002] 
[Change Repository to DarcsRepo.
Juliusz Chroboczek <[EMAIL PROTECTED]>**20050424140132] 
[TAG 2005-07-07
Ian Lynagh <[EMAIL PROTECTED]>**20050707144607] 
Patch bundle hash:
b647a5a570dcc84353d1c9d597eaa9017ec9d917
_______________________________________________
darcs-devel mailing list
[email protected]
http://www.abridgegame.org/cgi-bin/mailman/listinfo/darcs-devel

Reply via email to