[prev in list] [next in list] [prev in thread] [next in thread] 

List:       darcs-devel
Subject:    [darcs-devel] darcs patch: Start Compat.hs,
From:       Ian Lynagh <igloo () earth ! li>
Date:       2005-07-30 14:28:58
Message-ID: E1DysKg-00076i-00 () userpc15 ! comlab ! ox ! ac ! uk
[Download RAW message or body]

Sat Jul 30 01:48:29 BST 2005  Ian Lynagh <igloo@earth.li>
  * Start Compat.hs, and move stdout_is_a_pipe from compat.c

Sat Jul 30 02:01:18 BST 2005  Ian Lynagh <igloo@earth.li>
  * Remove unused function

Sat Jul 30 03:09:18 BST 2005  Ian Lynagh <igloo@earth.li>
  * Move mkstemp to Compat.hs

Sat Jul 30 13:22:55 BST 2005  Ian Lynagh <igloo@earth.li>
  * Remove is_symlink

Sat Jul 30 14:12:05 BST 2005  Ian Lynagh <igloo@earth.li>
  * Move maybe_relink out of compat.c

Sat Jul 30 14:40:30 BST 2005  Ian Lynagh <igloo@earth.li>
  * Split the raw mode stuff out into its own .hsc file. Windows needs some=
 TLC

Sat Jul 30 15:17:03 BST 2005  Ian Lynagh <igloo@earth.li>
  * Move atomic_create/sloppy_atomic_create to Compat

[Attachment #3 (text/x-darcs-patch)]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


New patches:

[Start Compat.hs, and move stdout_is_a_pipe from compat.c
Ian Lynagh <igloo@earth.li>**20050730004829] {
addfile ./Compat.hs
hunk ./Compat.hs 1
+
+module Compat (stdout_is_a_pipe) where
+
+import System.Posix.Files ( getFdStatus, isNamedPipe )
+import System.Posix.IO ( stdOutput )
+
+stdout_is_a_pipe :: IO Bool
+stdout_is_a_pipe
+ = do stat <- getFdStatus stdOutput
+      return (isNamedPipe stat)
+
hunk ./GNUmakefile 21
- -	CheckFileSystem.lhs ColourPrinter.lhs Curl.hs DarcsIO.lhs	\
+	CheckFileSystem.lhs ColourPrinter.lhs Compat.hs Curl.hs DarcsIO.lhs	\
hunk ./SignalHandler.lhs 32
- -import Foreign.C ( CInt )
hunk ./SignalHandler.lhs 33
+import Compat ( stdout_is_a_pipe )
hunk ./SignalHandler.lhs 43
- -foreign import ccall unsafe "static compat.h stdout_is_a_pipe"
- -        stdout_is_a_pipe :: IO CInt
- -
hunk ./SignalHandler.lhs 58
- -                   when (is_pipe /= 0) $
+                   when is_pipe $
hunk ./compat.c 13
- -int stdout_is_a_pipe() {
- -    struct stat s;
- -    int ret;
- -    ret = fstat(STDOUT_FILENO, &s);
- -    if (ret == 0)
- -        return !S_ISFIFO(s.st_mode);
- -    else
- -        return 0;
- -}
- -
hunk ./compat.h 26
- -int stdout_is_a_pipe();
- -
}

[Remove unused function
Ian Lynagh <igloo@earth.li>**20050730010118] {
hunk ./compat.c 183
- -int pipe(int fildes[2]) {
- -    return _pipe(fildes, 8 * (2<<10), O_BINARY);
- -}
- -
}

[Move mkstemp to Compat.hs
Ian Lynagh <igloo@earth.li>**20050730020918] {
hunk ./Compat.hs 2
- -module Compat (stdout_is_a_pipe) where
+{-# OPTIONS -fffi #-}
hunk ./Compat.hs 4
+module Compat (stdout_is_a_pipe, mkstemp, mk_stdout_temp, canonFilename) where
+
+import DarcsUtils ( withCurrentDirectory )
+#ifdef WIN32
+import DarcsUtils ( showHexLen )
+#endif
+
+#ifdef WIN32
+import Control.Exception ( Exception(IOException), throwIO )
+#endif
+import Control.Monad ( liftM )
+#ifdef WIN32
+import Data.Bits ( (.&.) )
+#endif
+#ifndef WIN32
+import Foreign.C.Error ( throwErrno )
+import Foreign.C.String ( CString, withCString, peekCString )
+import Foreign.C.Types ( CInt )
+#endif
+import System.Directory ( getCurrentDirectory )
+import System.IO ( Handle, hFlush, stdout, stderr, hSetBuffering,
+                   BufferMode(NoBuffering), hSetBinaryMode )
+#ifdef WIN32
+import System.IO.Error ( mkIOError, illegalOperationErrorType )
+#endif
hunk ./Compat.hs 30
- -import System.Posix.IO ( stdOutput )
+#ifdef WIN32
+import System.Posix.Files ( stdFileMode )
+#endif
+import System.Posix.IO ( stdOutput, stdError, fdToHandle, dupTo )
+#ifdef WIN32
+import System.Posix.IO ( defaultFileFlags, openFd,
+                         exclusive, OpenMode(WriteOnly) )
+#endif
+import System.Posix.Types ( Fd(..) )
+#ifdef WIN32
+import System.Random ( randomIO )
+#endif
hunk ./Compat.hs 47
+
+canonFilename :: FilePath -> IO FilePath
+canonFilename f@(_:':':_) = return f -- absolute windows paths
+canonFilename f@('/':_) = return f
+canonFilename ('.':'/':f) = do cd <- getCurrentDirectory
+                               return $ cd ++ "/" ++ f
+canonFilename f = case reverse $ dropWhile (/='/') $ reverse f of
+                  "" -> liftM (++('/':f)) getCurrentDirectory
+                  rd -> withCurrentDirectory rd $
+                          do fd <- getCurrentDirectory
+                             return $ fd ++ "/" ++ simplefilename
+    where
+    simplefilename = reverse $ takeWhile (/='/') $ reverse f
+
+#ifdef WIN32
+mkstemp_core :: FilePath -> IO (Fd, String)
+mkstemp_core fp
+ = do fp' <- case splitAt 6 fp of
+                 ("XXXXXX", rev_fp) -> return $ reverse rev_fp
+                 _ -> let e = mkIOError illegalOperationErrorType
+                                        "mkstemp" Nothing (Just fp)
+                      in throwIO (IOException e)
+      r <- randomIO
+      let fp'' = fp' ++ (showHexLen 6 (r .&. 0xFFFFFF :: Int))
+      fd <- openFd fp WriteOnly (Just stdFileMode) flags
+      return (fd, fp'')
+  where flags = defaultFileFlags { exclusive = True }
+#else
+mkstemp_core :: String -> IO (Fd, String)
+mkstemp_core str = withCString (str++"XXXXXX") $
+    \cstr -> do fd <- c_mkstemp cstr
+                if fd < 0
+                  then throwErrno $ "Failed to create temporary file "++str
+                  else do str' <- peekCString cstr
+                          fname <- canonFilename str'
+                          return (Fd fd, fname)
+
+foreign import ccall unsafe "static stdlib.h mkstemp"
+    c_mkstemp :: CString -> IO CInt
+#endif
+
+mkstemp :: String -> IO (Handle, String)
+mkstemp str = do (fd, fn) <- mkstemp_core str
+                 h <- fdToHandle fd
+                 hSetBinaryMode h True
+                 return (h, fn)
+
+mk_stdout_temp :: String -> IO String
+mk_stdout_temp str = do (fd, fn) <- mkstemp_core str
+                        hFlush stdout
+                        hFlush stderr
+                        dupTo fd stdOutput
+                        dupTo fd stdError
+                        hFlush stdout
+                        hFlush stderr
+                        hSetBuffering stdout NoBuffering
+                        hSetBuffering stderr NoBuffering
+                        return fn
hunk ./DarcsUtils.lhs 9
+                    showHexLen,
hunk ./DarcsUtils.lhs 12
+import Numeric ( showHex )
hunk ./DarcsUtils.lhs 25
+
+showHexLen :: (Integral a) => Int -> a -> String
+showHexLen n x = let s = showHex x ""
+                 in replicate (n - length s) ' ' ++ s
hunk ./Lock.lhs 37
- -import GHC.Handle ( hSetBinaryMode )
hunk ./Lock.lhs 44
- -import Foreign.C ( withCString, CString, peekCString,
+import Foreign.C ( withCString, CString,
hunk ./Lock.lhs 47
- -import Workaround ( fileMode, getFileStatus, setFileMode, openFd, )
+import Workaround ( fileMode, getFileStatus, setFileMode )
hunk ./Lock.lhs 57
+import Compat ( mkstemp, mk_stdout_temp, canonFilename )
hunk ./Lock.lhs 111
- -
- -canonFilename :: FilePath -> IO FilePath
- -canonFilename f@(_:':':_) = return f -- absolute windows paths
- -canonFilename f@('/':_) = return f
- -canonFilename ('.':'/':f) = do cd <- getCurrentDirectory
- -                               return $ cd ++ "/" ++ f
- -canonFilename f = case reverse $ dropWhile (/='/') $ reverse f of
- -                  "" -> liftM (++('/':f)) getCurrentDirectory
- -                  rd -> withCurrentDirectory rd $
- -                          do fd <- getCurrentDirectory
- -                             return $ fd ++ "/" ++ simplefilename
- -    where
- -    simplefilename = reverse $ takeWhile (/='/') $ reverse f
hunk ./Lock.lhs 137
- -
- -mk_stdout_temp :: String -> IO String
- -mk_stdout_temp str = withCString (str++"XXXXXX") $
- -    \cstr -> do fd <- c_mkstemp cstr
- -                if fd < 0
- -                  then throwErrno $ "Failed to create temporary file "++str
- -                  else do str' <- peekCString cstr
- -                          fname <- canonFilename str'
- -                          hFlush stdout
- -                          hFlush stderr
- -                          c_dup2 fd 1
- -                          c_dup2 fd 2
- -                          hFlush stdout
- -                          hFlush stderr
- -                          hSetBuffering stdout NoBuffering
- -                          hSetBuffering stderr NoBuffering
- -                          return fname
- -
- -mkstemp :: String -> IO (Handle, String)
- -mkstemp str = withCString (str++"XXXXXX") $
- -    \cstr -> do fd <- c_mkstemp cstr
- -                if fd < 0
- -                  then throwErrno $ "Failed to create temporary file "++str
- -                  else do str' <- peekCString cstr
- -                          fname <- canonFilename str'
- -                          h <- openFd (fromIntegral fd) Nothing fname ReadWriteMode True False
- -                          hSetBinaryMode h True
- -                          return (h, fname)
- -
- -foreign import ccall unsafe "static unistd.h dup2" c_dup2 :: CInt -> CInt -> IO CInt
- -foreign import ccall unsafe "static stdlib.h mkstemp" c_mkstemp :: CString -> IO CInt
hunk ./compat.c 161
- -int mkstemp(char *p)
- -{
- -    static int inited_rand = 0;
- -    size_t len = strlen(p);
- -    if (len < 6 || strcmp(p+len-6, "XXXXXX")) {
- -        errno = EINVAL;
- -        return -1;
- -    }
- -    if (!inited_rand) {
- -        srand(time(NULL));
- -        inited_rand = 1;
- -    }
- -    // WARNING! The following is written for the win32 version of snprintf,
- -    // which differs from the POSIX snprintf in how it treats the second
- -    // argument.  The win32 snprintf doesn't print a nul character on
- -    // overflow, so the second argument had better be one less than the
- -    // size of the buffer, and the last character of the buffer had better
- -    // be preset to nul.
- -    snprintf(p+len-6, 6, "%06x", rand()<<16 ^ rand());
- -    return open(p, O_CREAT | O_EXCL | O_RDWR, 0666);
- -}
- -
hunk ./compat.h 10
- -int mkstemp(char *p);
- -int pipe( int fildes[2] );
}

[Remove is_symlink
Ian Lynagh <igloo@earth.li>**20050730122255] {
hunk ./Lock.lhs 58
+import System.Posix.Files ( getSymbolicLinkStatus, isDirectory )
hunk ./Lock.lhs 206
- -foreign import ccall unsafe "static compat.h is_symlink" is_symlink
- -    :: CString -> IO CInt
- -
hunk ./Lock.lhs 208
- -    fe <- doesDirectoryExist f
- -    if not fe then return False
- -       else withCString f $ \cf-> (0==) `liftM` is_symlink cf
+    fs <- getSymbolicLinkStatus f
+    return (isDirectory fs)
hunk ./SlurpDirectory.lhs 59
- -import Foreign.C.String
- -import Foreign.C ( CInt )
hunk ./SlurpDirectory.lhs 286
- -foreign import ccall unsafe "static compat.h is_symlink" is_symlink
- -    :: CString -> IO CInt
- -
hunk ./SlurpDirectory.lhs 287
- -isFileReallySymlink f = do
- -    withCString f $ \cf -> do sym <- is_symlink cf
- -                              return $ sym /= 0
+isFileReallySymlink f = do fs <- getSymbolicLinkStatus f
+                           return (isSymbolicLink fs)
hunk ./SlurpDirectory.lhs 291
- -doesFileReallyExist f = do
- -    fe <- doesFileExist f
- -    if not fe then return False
- -       else do symlink <- isFileReallySymlink f
- -               return $ not symlink
+doesFileReallyExist f = do fs <- getSymbolicLinkStatus f
+                           return (isRegularFile fs)
+
hunk ./SlurpDirectory.lhs 295
- -doesDirectoryReallyExist f = do
- -    fe <- doesDirectoryExist f
- -    if not fe then return False
- -       else do symlink <- isFileReallySymlink f
- -               return $ not symlink
+doesDirectoryReallyExist f = do fs <- getSymbolicLinkStatus f
+                                return (isDirectory fs)
hunk ./compat.c 161
- -int is_symlink(const char *file) {
- -    return 0; /* FIXME: should ignore windows shortcuts */
- -}
- -
hunk ./compat.c 256
- -
- -int is_symlink(const char *file) {
- -  struct stat buf;
- -  if (lstat(file, &buf)) return 0; /* treat error as non-symlink */
- -  return S_ISLNK(buf.st_mode);
- -}
- -
hunk ./compat.h 22
- -int is_symlink(const char *file);
- -
}

[Move maybe_relink out of compat.c
Ian Lynagh <igloo@earth.li>**20050730131205] {
hunk ./Compat.hs 4
- -module Compat (stdout_is_a_pipe, mkstemp, mk_stdout_temp, canonFilename) where
+module Compat (stdout_is_a_pipe, mkstemp, mk_stdout_temp, canonFilename,
+               maybe_relink) where
+
+import Prelude hiding ( catch )
hunk ./Compat.hs 10
- -#ifdef WIN32
hunk ./Compat.hs 11
+#ifndef WIN32
+import DarcsUtils ( add_to_error_loc, isUnsupportedOperationError )
+import FastPackedString ( readFileLazily )
hunk ./Compat.hs 16
- -#ifdef WIN32
hunk ./Compat.hs 17
+#ifndef WIN32
+import Control.Exception ( catch )
+import Control.Monad ( unless )
hunk ./Compat.hs 22
- -#ifdef WIN32
hunk ./Compat.hs 23
- -#endif
hunk ./Compat.hs 24
+import Data.Bits ( xor, shiftR )
hunk ./Compat.hs 28
+import System.Directory ( removeFile, renameFile )
hunk ./Compat.hs 33
+#ifndef WIN32
+import System.IO ( hPutStrLn )
+import System.IO.Error ( isDoesNotExistError, isPermissionError )
+#endif
hunk ./Compat.hs 41
+#ifndef WIN32
+import System.Posix.Files ( getFileStatus, isRegularFile, createLink,
+                            modificationTime, fileID, fileSize, deviceID )
+#endif
hunk ./Compat.hs 56
+#endif
+#ifndef WIN32
+import System.Time ( getClockTime, ClockTime(TOD) )
hunk ./Compat.hs 123
+
+#ifdef WIN32
+
+maybe_relink :: Bool -> FilePath -> FilePath -> IO Bool
+maybe_relink _ _ _ = return False
+
+#else
+
+{-
+Tries to link src to dst if both files exist and have the same
+contents.  If careful is false only the file sizes are compared; if
+it is true, the full contents are compared.
+
+This code assumes that dst cannot change behind our back -- the
+caller is supposed to protect it by a lock.  On the other hand, it
+does handle simultaneous access to src, but only if src is never
+modified in place.  It should also be safe over NFS.
+
+Assumes that rename cannot fail mid-way on a single filesystem.
+-}
+
+maybe_relink :: Bool -> FilePath -> FilePath -> IO Bool
+maybe_relink careful src dst = do
+    m_src_stat <- (liftM Just $ getFileStatus src) `catch` \e ->
+                  case e of
+                      IOException e'
+                       | isDoesNotExistError e'
+                         -> return Nothing
+                      _ -> throwIO (add_to_error_loc e ("Relinking " ++ dst))
+    case m_src_stat of
+        Nothing -> return False
+        Just src_stat -> do
+            dst_stat <- getFileStatus dst
+
+            unless (isRegularFile src_stat)
+                   (fail (src ++ " is not a regular file"))
+            unless (isRegularFile dst_stat)
+                   (fail (dst ++ " is not a regular file"))
+
+            if deviceID src_stat /= deviceID dst_stat then return False
+              else if fileID src_stat == fileID dst_stat then return True
+              else if fileSize src_stat /= fileSize dst_stat then return False
+              else do TOD _ usec <- getClockTime
+                      let x = (shiftR usec 16 `xor` usec) .&. 0xFFFF
+                          tempname = dst ++ showHexLen 4 x
+                      {- link is atomic even on NFS, we will fail
+                         gracefully if the name is not unique. -}
+                      do createLink src tempname
+                         temp_stat <- getFileStatus tempname
+                         {- Check for a race condition. The size and
+                            mtime checks are gratuitious, but they don't
+                            cost much, and might save your data if
+                            you're on a filesystem without i-nodes. -}
+                         if fileID temp_stat /= fileID src_stat ||
+                            fileSize temp_stat /= fileSize src_stat ||
+                            modificationTime temp_stat /=
+                                modificationTime src_stat
+                           then do hPutStrLn stderr "race condition avoided"
+                                   removeFile tempname
+                                   return False
+                           else if careful
+                                then do lf1 <- readFileLazily tempname
+                                        lf2 <- readFileLazily dst
+                                        {- This == test is technically too
+                                           strong, but will pretty much
+                                           always br right in practice -}
+                                        if lf1 == lf2
+                                          then do renameFile tempname dst
+                                                  return True
+                                          else do removeFile tempname
+                                                  return False
+                                else do renameFile tempname dst
+                                        return True
+                       `catch` \e -> do removeFile tempname `catch`
+                                                             \_ -> return ()
+                                        throwIO e
+ `catch` \e -> case e of
+                   IOException e'
+                    | isPermissionError e' || isUnsupportedOperationError e' ->
+                       return False
+                   _ -> throwIO (add_to_error_loc e ("Relinking " ++ dst))
+
+#endif
hunk ./DarcsUtils.lhs 9
- -                    showHexLen,
+                    showHexLen, add_to_error_loc, isUnsupportedOperationError,
hunk ./DarcsUtils.lhs 12
+import Control.Exception ( Exception(IOException) )
+import GHC.IOBase ( IOException(ioe_location),
+                    IOErrorType(UnsupportedOperation) )
+import System.IO.Error ( ioeGetErrorType )
hunk ./DarcsUtils.lhs 33
+
+add_to_error_loc :: Exception -> String -> Exception
+add_to_error_loc (IOException ioe) s
+    = IOException $ ioe { ioe_location = s ++ ": " ++ ioe_location ioe }
+add_to_error_loc e _ = e
+
+isUnsupportedOperationError :: IOError -> Bool
+isUnsupportedOperationError = isUnsupportedOperationErrorType . ioeGetErrorType
+
+isUnsupportedOperationErrorType :: IOErrorType -> Bool
+isUnsupportedOperationErrorType UnsupportedOperation = True
+isUnsupportedOperationErrorType _ = False
hunk ./FastPackedString.hs 45
+        readFileLazily,  -- :: FilePath -> IO LazyFile
hunk ./FastPackedString.hs 819
+    deriving Eq
hunk ./FastPackedString.hs 848
- -        else do let read_rest = do
- -                        -- We might be making too big a fp here
- -                        fp <- mallocForeignPtr blocksize
- -                        debugForeignPtr fp $ "gzReadFileLazily "++f
- -                        lread <- withForeignPtr fp
- -                               $ \p -> hGetBuf h p blocksize
- -                        case lread of
- -                            0 -> return []
- -                            l -> do rest <- unsafeInterleaveIO read_rest
- -                                    return (PS fp 0 l:rest)
- -                rest <- unsafeInterleaveIO read_rest
- -                return $ LazyPackedStrings (header:rest)
+        else liftM (LazyPackedStrings . (header:)) $ readHandleLazily h
+    where blocksize = 1024
+
+readFileLazily :: FilePath -> IO LazyFile
+readFileLazily f =
+#if defined(__GLASGOW_HASKELL__)
+    if use_mmap
+      then liftM MMappedPackedString (mmapFilePS f)
+      else
+#endif
+           do h <- openBinaryFile f ReadMode
+              liftM LazyPackedStrings $ readHandleLazily h
+
+readHandleLazily :: Handle -> IO [PackedString]
+readHandleLazily h
+ = do let read_rest = do
+              -- We might be making too big a fp here
+              fp <- mallocForeignPtr blocksize
+              debugForeignPtr fp ("readHandleLazily " ++ show h)
+              lread <- withForeignPtr fp
+                     $ \p -> hGetBuf h p blocksize
+              case lread of
+                  0 -> return []
+                  l -> do rest <- unsafeInterleaveIO read_rest
+                          return (PS fp 0 l:rest)
+      unsafeInterleaveIO read_rest
hunk ./Lock.lhs 57
- -import Compat ( mkstemp, mk_stdout_temp, canonFilename )
+import Compat ( mkstemp, mk_stdout_temp, canonFilename, maybe_relink )
hunk ./Lock.lhs 296
- -foreign import ccall unsafe "compat.h maybe_relink" c_maybe_relink
- -    :: CString -> CString -> CInt -> IO CInt
- -
hunk ./Lock.lhs 301
- -maybeRelink src dst =
- -    withCString src $ \csrc ->
- -    withCString dst $ \cdst ->
- -    do rc <- c_maybe_relink csrc cdst 1
- -       (case rc of
- -        0 -> return True
- -        1 -> return True
- -        -1 -> throwErrno ("Relinking " ++ dst)
- -        -2 -> return False
- -        -3 -> do putStrLn ("Relinking: race condition avoided on file " ++
- -                            dst)
- -                 return False
- -        _ -> fail ("Unexpected situation when relinking " ++ dst))
+maybeRelink src dst = maybe_relink True src dst
hunk ./compat.c 258
- -#ifdef _WIN32
- -int
- -maybe_relink(const char *src, const char *dst, int careful)
- -{
- -    return 0;
- -}
- -
- -#else
- -
- -/* Tries to link src to dst if both files exist and have the same
- -   contents.  If careful is false only the file sizes are compared; if
- -   it is true, the full contents are compared.
- -
- -   This code assumes that dst cannot change behind our back -- the
- -   caller is supposed to protect it by a lock.  On the other hand, it
- -   does handle simultaneous access to src, but only if src is never
- -   modified in place.  It should also be safe over NFS.
- -
- -   Assumes that rename cannot fail mid-way on a single filesystem.
- -
- -   Returns 1 on success, 0 if the files are already linked, -1 for an
- -   error in errno, -2 if the files cannot be linked because they are not
- -   the same, on different devices, or on a filesystem with no support for
- -   hard links, -3 if there was a race condition, -4 if something unexpected
- -   happened. */
- -
- -int
- -maybe_relink(char *src, char *dst, int careful)
- -{
- -#define RELINK_BUFFER_SIZE 8192
- -
- -    int len, rc, saved_errno;
- -    char *tempname;
- -    struct stat srcstat, dststat, tempstat;
- -    struct timeval now;
- -
- -    rc = stat(src, &srcstat);
- -    if(rc < 0) {
- -        if(errno == ENOENT)
- -            return -2;
- -        else
- -            return -1;
- -    }
- -
- -    rc = stat(dst, &dststat);
- -    if(rc < 0) return -1;
- -
- -    if(!S_ISREG(srcstat.st_mode) || !S_ISREG(dststat.st_mode)) {
- -        return -4;
- -    }
- -
- -    if(srcstat.st_dev != dststat.st_dev) {
- -        return -2;
- -    }
- -
- -    if(srcstat.st_ino == dststat.st_ino)
- -        /* Files are already linked */
- -        return 0;
- -
- -    if(srcstat.st_size != dststat.st_size)
- -        return -2;
- -
- -    /* link is atomic even on NFS, we will fail gracefully if the name
- -       is not unique. */
- -    gettimeofday(&now, NULL);
- -    rc = strlen(dst) + 6;
- -    tempname = malloc(rc);
- -    if(tempname == NULL) return -1;
- -    len = snprintf(tempname, rc, "%s-%04x", dst,
- -                   ((unsigned)(now.tv_usec ^ (now.tv_usec >> 16))) & 0xFFFF);
- -    if(len < 0 || len >= rc) {
- -        free(tempname);
- -        return -4;
- -    }
- -
- -    rc = link(src, tempname);
- -    if(rc < 0) {
- -        /* We need to try to remove the link in case this was a
- -           problem with NFS over an unreliable transport. */
- -        goto fail;
- -    }
- -
- -    rc = stat(tempname, &tempstat);
- -    if(rc < 0) goto fail;
- -
- -    /* Check for a race condition.  The size and mtime checks are
- -       gratuitious, but they don't cost much, and might save your data
- -       if you're on a filesystem without i-nodes. */
- -    if(tempstat.st_ino != srcstat.st_ino ||
- -       tempstat.st_size != srcstat.st_size ||
- -       tempstat.st_mtime != srcstat.st_mtime) {
- -        unlink(tempname);
- -        free(tempname);
- -        return -3;
- -    }
- -    if(careful) {
- -        int fd1, fd2, i, rc1, rc2;
- -        char buf1[RELINK_BUFFER_SIZE], buf2[RELINK_BUFFER_SIZE];
- -
- -        fd1 = open(tempname, O_RDONLY);
- -        if(fd1 < 0) goto fail;
- -        fd2 = open(dst, O_RDONLY);
- -        if(fd2 < 0) { close(fd1); goto fail; }
- -
- -        i = 0;
- -        /* This comparison is approximate: it doesn't deal with short
- -           reads and EINTR.  It's okay, as these cases are rare and if
- -           they happen, we're still safe. */
- -        while(i < tempstat.st_size) {
- -            rc1 = read(fd1, buf1, RELINK_BUFFER_SIZE);
- -            if(rc1 < 0) { close(fd1); close(fd2); goto fail; }
- -            rc2 = read(fd2, buf2, RELINK_BUFFER_SIZE);
- -            if(rc2 < 0) { close(fd1); close(fd2); goto fail; }
- -            if(rc1 == 0 || rc1 != rc2 || memcmp(buf1, buf2, rc1) != 0) {
- -                close(fd1); close(fd2);
- -                unlink(tempname);
- -                free(tempname);
- -                return -2;
- -            }
- -            i += rc1;
- -        }
- -        close(fd1); close(fd2);
- -    }
- -
- -    rc = rename(tempname, dst);
- -    if(rc < 0) goto fail;
- -
- -    free(tempname);
- -    return 1;
- -
- - fail:
- -    saved_errno = errno;
- -    unlink(tempname);
- -    free(tempname);
- -    errno = saved_errno;
- -    if(errno == EPERM || errno == EOPNOTSUPP)
- -        return -2;
- -    return -1;
- -
- -#undef RELINK_BUFFER_SIZE
- -}
- -
- -#endif
hunk ./compat.h 22
- -int maybe_relink(const char *src, const char *dst, int careful);
}

[Split the raw mode stuff out into its own .hsc file. Windows needs some TLC
Ian Lynagh <igloo@earth.li>**20050730134030] {
hunk ./GNUmakefile 32
- -	PrintPatch.lhs Printer.lhs RegChars.lhs \
+	PrintPatch.lhs Printer.lhs RawMode.hs RegChars.lhs \
hunk ./GNUmakefile 249
+	rm -f RawMode.hs
addfile ./RawMode.hsc
hunk ./RawMode.hsc 1
+
+module RawMode (get_raw_mode, set_raw_mode) where
+
+#ifdef _WIN32
+
+-- Various details are missing, unfinished and compilation etc not tested
+-- as I don't have Windows.
+
+#include <XXX.h>
+
+type DWORD = #type DWORD
+type HANDLE = #type HANDLE
+
+foreign import ccall unsafe "XXX.h GetStdHandle"
+    c_GetStdHandle :: Handle -> IO c_STD_INPUT_HANDLE
+
+foreign import ccall unsafe "XXX.h GetConsoleMode"
+    c_GetConsoleMode :: Handle -> Ptr DWORD -> IO ()
+
+get_mode :: IO DWORD
+get_mode = do stdin_handle <- c_GetStdHandle (#const STD_INPUT_HANDLE)
+              p <- malloc
+              c_GetConsoleMode stdin_handle p
+              console_mode <- peek p
+              free p
+              return console_mode
+
+int get_raw_mode()
+{
+    return (get_mode() & ENABLE_LINE_INPUT) == 0;
+}
+
+void set_raw_mode(int raw)
+{
+    HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
+    DWORD console_mode = get_mode();
+    if (raw)
+        console_mode &= ~(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT);
+    else
+        console_mode |= ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT;
+    if (!SetConsoleMode(stdin_handle, console_mode))
+        fprintf(stderr, "SetConsoleMode error: %x\n", GetLastError());
+}
+
+#else
+
+get_raw_mode :: IO Bool
+get_raw_mode = return False
+
+set_raw_mode :: Bool -> IO ()
+set_raw_mode _ = return ()
+
+#endif
+
hunk ./SelectChanges.lhs 54
- -import Foreign.C ( CInt )
hunk ./SelectChanges.lhs 78
+import RawMode ( get_raw_mode, set_raw_mode )
hunk ./SelectChanges.lhs 215
- -foreign import ccall "compat.h get_raw_mode" get_raw_mode :: IO CInt
- -foreign import ccall "compat.h set_raw_mode" set_raw_mode :: CInt -> IO ()
- -
hunk ./SelectChanges.lhs 222
- -                                       set_raw_mode 1
+                                       set_raw_mode True
hunk ./autoconf.mk.in 85
+%.hs : %.hsc
+	hsc2hs $< -o $@
+
hunk ./compat.c 160
- -#ifdef _WIN32
- -static DWORD get_mode()
- -{
- -    DWORD console_mode;
- -    HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
- -    GetConsoleMode(stdin_handle, &console_mode);
- -    return console_mode;
- -}
- -
- -int get_raw_mode()
- -{
- -    return (get_mode() & ENABLE_LINE_INPUT) == 0;
- -}
- -
- -void set_raw_mode(int raw)
- -{
- -    HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
- -    DWORD console_mode = get_mode();
- -    if (raw)
- -        console_mode &= ~(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT);
- -    else
- -        console_mode |= ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT;
- -    if (!SetConsoleMode(stdin_handle, console_mode))
- -        fprintf(stderr, "SetConsoleMode error: %x\n", GetLastError());
- -}
- -
- -
- -#else
- -
- -int get_raw_mode()
- -{
- -    return 0;
- -}
- -
- -void set_raw_mode(int raw)
- -{
- -}
+#ifndef _WIN32
hunk ./compat.h 13
- -int get_raw_mode();
- -void set_raw_mode(int raw);
- -
}

[Move atomic_create/sloppy_atomic_create to Compat
Ian Lynagh <igloo@earth.li>**20050730141703] {
hunk ./Compat.hs 5
- -               maybe_relink) where
+               maybe_relink, atomic_create, sloppy_atomic_create) where
hunk ./Compat.hs 12
- -import DarcsUtils ( add_to_error_loc, isUnsupportedOperationError )
+import DarcsUtils ( add_to_error_loc, isUnsupportedOperationError,
+                    isHardwareFaultError )
hunk ./Compat.hs 19
- -import Control.Exception ( catch )
- -import Control.Monad ( unless )
+import Control.Exception ( catch, finally )
+import Control.Monad ( when, unless )
hunk ./Compat.hs 26
+import Data.IORef ( IORef, newIORef, readIORef, writeIORef )
+import Data.Maybe ( isJust )
hunk ./Compat.hs 31
+import Network.BSD ( getHostName )
hunk ./Compat.hs 39
- -import System.IO.Error ( isDoesNotExistError, isPermissionError )
+import System.IO.Error ( isDoesNotExistError, isPermissionError,
+                         alreadyExistsErrorType, isAlreadyExistsError,
+                         ioeSetErrorType )
hunk ./Compat.hs 46
- -import System.Posix.Files ( getFdStatus, isNamedPipe )
hunk ./Compat.hs 47
- -import System.Posix.Files ( getFileStatus, isRegularFile, createLink,
- -                            modificationTime, fileID, fileSize, deviceID )
+import System.IO.Unsafe ( unsafePerformIO )
+import System.Posix.Env ( getEnv )
hunk ./Compat.hs 50
+import System.Posix.Files ( getFdStatus, isNamedPipe )
hunk ./Compat.hs 53
+#else
+import System.Posix.Files ( getFileStatus, isRegularFile, createLink,
+                            modificationTime, fileID, fileSize, deviceID,
+                            linkCount, stdFileMode )
hunk ./Compat.hs 58
- -import System.Posix.IO ( stdOutput, stdError, fdToHandle, dupTo )
+import System.Posix.IO ( openFd, closeFd, stdOutput, stdError, fdToHandle,
+                         dupTo, defaultFileFlags, exclusive,
+                         OpenMode(WriteOnly) )
hunk ./Compat.hs 65
+#ifndef WIN32
+import System.Posix.Process ( getProcessID )
+#endif
hunk ./Compat.hs 220
+#endif
+
+sloppy_atomic_create :: FilePath -> IO ()
+sloppy_atomic_create fp
+    = do fd <- openFd fp WriteOnly (Just stdFileMode) flags
+         closeFd fd
+  where flags = defaultFileFlags { exclusive = True }
+
+atomic_create :: FilePath -> IO ()
+
+#ifdef _WIN32
+
+atomic_create fp = sloppy_atomic_create fp
+
+#else
+
+{-# NOINLINE hostname_ref #-}
+hostname_ref :: IORef (Maybe String)
+hostname_ref = unsafePerformIO (newIORef Nothing)
+
+get_hostname :: IO String
+get_hostname
+ = getHostName `catch` \_ ->
+       do hPutStrLn stderr "Error reading hostname when locking."
+          return "kremvax"
+
+careful_atomic_create :: FilePath -> IO ()
+{-
+O_EXCL is not available over NFSv2, and even under NFSv3, it is
+broken on many systems.  The following protocol is provably
+safe assuming that:
+- creation of hard links is atomic;
+- stat hits the server rather than working from the cache.
+-}
+careful_atomic_create fp =
+    do m_hostname <- readIORef hostname_ref
+       hostname <- case m_hostname of
+                       Just hostname -> return hostname
+                       Nothing -> do
+                           hostname <- get_hostname
+                           let hostname' = take 15
+                                         $ takeWhile ('.' /=) hostname
+                           writeIORef hostname_ref (Just hostname')
+                           return hostname'
+       pid <- getProcessID
+       TOD _ usec <- getClockTime
+
+       let directory = case break ('/' ==) $ reverse fp of
+                           (_, xs) -> reverse xs
+           file = directory
+               ++ "darcs_lock_"
+               ++ hostname
+               ++ showHexLen 4 (pid .&. 0xFFFF)
+               ++ showHexLen 4 ((shiftR usec 16 `xor` usec) .&. 0xFFFF)
+
+       finally (do sloppy_atomic_create file
+                   createLink file fp `catch` \e ->
+                       case e of
+                           IOException e'
+                            {- Linux returns EPERM when making hard
+                               links on filesystems that don't support
+                               them.
+                               It seems that MacOS returns EOPNOTSUPP
+                               on filesystems that don't support hard
+                               links. -}
+                            | isPermissionError e' ||
+                              isUnsupportedOperationError e' ->
+                               sloppy_atomic_create fp
+                            {- The link may still have been successful
+                               if we're running over UDP and got EEXIST
+                               or EIO.  Check the file's link count. -}
+                            | isAlreadyExistsError e' ||
+                              isHardwareFaultError e' ->
+                               do fs <- getFileStatus file
+                                  let e'' = ioeSetErrorType e'
+                                                alreadyExistsErrorType
+                                  when (linkCount fs /= 2)
+                                       (throwIO (IOException e''))
+                           _ -> throwIO e
+               )
+               (removeFile file `catch` \e ->
+                    case e of
+                        IOException e' | isDoesNotExistError e' -> return ()
+                        _ -> throwIO e)
+
+atomic_create fp = do m <- getEnv "DARCS_SLOPPY_LOCKS"
+                      if isJust m
+                        then sloppy_atomic_create fp
+                        else careful_atomic_create fp
hunk ./DarcsUtils.lhs 9
- -                    showHexLen, add_to_error_loc, isUnsupportedOperationError,
+                    showHexLen, add_to_error_loc,
+                    isUnsupportedOperationError, isHardwareFaultError,
hunk ./DarcsUtils.lhs 15
- -                    IOErrorType(UnsupportedOperation) )
+                    IOErrorType(UnsupportedOperation, HardwareFault) )
hunk ./DarcsUtils.lhs 46
+
+isHardwareFaultError :: IOError -> Bool
+isHardwareFaultError = isHardwareFaultErrorType . ioeGetErrorType
+
+isHardwareFaultErrorType :: IOErrorType -> Bool
+isHardwareFaultErrorType HardwareFault = True
+isHardwareFaultErrorType _ = False
hunk ./GNUmakefile 14
- -GHCFLAGS += -Wall -Werror -package util -I.
+GHCFLAGS += -Wall -Werror -package util -package network -I.
hunk ./Lock.lhs 34
- -import IO hiding ( bracket )
- -import System.IO ( openBinaryFile )
- -import Control.Exception ( bracket, catchJust, ioErrors, finally )
+import System.IO ( openBinaryFile, hClose, hPutStr, Handle,
+                   IOMode(WriteMode, AppendMode) )
+import System.IO.Error ( isDoesNotExistError, isAlreadyExistsError )
+import Control.Exception ( bracket, catchJust, ioErrors, finally, throwIO,
+                           Exception(IOException), catch, try )
hunk ./Lock.lhs 45
- -import Foreign
- -import Foreign.C ( withCString, CString,
- -                   throwErrno, getErrno, eEXIST, CInt, CUInt )
+import Foreign.C ( CUInt )
hunk ./Lock.lhs 50
- -import DarcsUtils ( catchall )
+import DarcsUtils ( catchall, add_to_error_loc )
hunk ./Lock.lhs 57
- -import Compat ( mkstemp, mk_stdout_temp, canonFilename, maybe_relink )
+import Compat ( mkstemp, mk_stdout_temp, canonFilename, maybe_relink,
+                atomic_create, sloppy_atomic_create )
hunk ./Lock.lhs 62
- -takeLock :: String -> IO Bool
hunk ./Lock.lhs 88
- -takeLock s = withCString s $ \cstr -> do
- -    rc <- c_atomic_create cstr
- -    if rc >= 0 then return True
- -               else do errno <- getErrno
- -                       if errno == eEXIST
- -                          then return False
- -                          else do pwd <- getCurrentDirectory
- -                                  throwErrno $ "takeLock "++s++" in "++pwd
+takeLock :: FilePath -> IO Bool
+takeLock fp =
+    do atomic_create fp
+       return True
+  `catch` \e -> case e of
+                    IOException e'
+                     | isAlreadyExistsError e' ->
+                        return False
+                    _ -> do pwd <- getCurrentDirectory
+                            throwIO $ add_to_error_loc e
+                                            ("takeLock "++fp++" in "++pwd)
hunk ./Lock.lhs 100
- -foreign import ccall unsafe "compat.h atomic_create" c_atomic_create
- -    :: CString -> IO CInt
- -
- -takeFile :: String -> IO Bool
- -takeFile s = withCString s $ \cstr -> do
- -    rc <- c_sloppy_create cstr
- -    if rc >= 0 then return True
- -               else do errno <- getErrno
- -                       if errno == eEXIST
- -                          then return False
- -                          else do pwd <- getCurrentDirectory
- -                                  throwErrno $ "takeFile "++s++" in "++pwd
- -
- -foreign import ccall unsafe "compat.h sloppy_atomic_create" c_sloppy_create
- -    :: CString -> IO CInt
+takeFile :: FilePath -> IO Bool
+takeFile fp =
+    do sloppy_atomic_create fp
+       return True
+  `catch` \e -> case e of
+                    IOException e'
+                     | isAlreadyExistsError e' ->
+                        return False
+                    _ -> do pwd <- getCurrentDirectory
+                            throwIO $ add_to_error_loc e
+                                            ("takeFile "++fp++" in "++pwd)
hunk ./Lock.lhs 187
- -                `IO.catch` (\e -> if isAlreadyExistsError e
- -                            then create_directory name (n+1)
- -                            else ioError e)
+                `catch` (\e -> case e of
+                              IOException e'
+                               | isAlreadyExistsError e' ->
+                                  create_directory name (n+1)
+                              _ -> throwIO e)
hunk ./compat.c 18
- -int sloppy_atomic_create(const char *p)
- -{
- -    int fd;
- -    fd = open(p, O_WRONLY | O_EXCL | O_CREAT, 0666);
- -    if(fd < 0)
- -        return -1;
- -    close(fd);
- -    return 1;
- -}
- -
- -#ifdef _WIN32
- -
- -int atomic_create(const char *p)
- -{
- -    return sloppy_atomic_create(p);
- -}
- -
- -#else
- -
- -static int careful_atomic_create(const char *p)
- -{
- -    /* O_EXCL is not available over NFSv2, and even under NFSv3, it is
- -       broken on many systems.  The following protocol is provably
- -       safe assuming that:
- -       - creation of hard links is atomic;
- -       - stat hits the server rather than working from the cache.
- -    */
- -
- -    static char hostname[65] = {'\0'};
- -    int fd, rc, saved_errno;
- -#define FILENAME_SIZE (11 + 15 + 8 + 1)
- -    char *filename;
- -    char *lastslash;
- -    int dirlen;
- -    struct timeval now;
- -    struct stat sb;
- -
- -    if(hostname[0] == '\0') {
- -        char *c;
- -        /* POSIX guarantees 65 is enough. */
- -        rc = gethostname(hostname, 65);
- -        if(rc < 0 || rc >= 65) {
- -            fprintf(stderr, "Error reading hostname when locking.\n");
- -            strcpy(hostname, "kremvax");
- -        }
- -        c = strchr(hostname, '.');
- -        if(c != NULL)
- -            *c = '\0';
- -        hostname[15] = '\0';
- -    }
- -
- -    lastslash = strrchr(p, '/');
- -    dirlen = lastslash ? lastslash - p + 1 : 0;
- -
- -    filename = malloc(dirlen + FILENAME_SIZE);
- -    if(filename == NULL)
- -        return -1;
- -
- -    if(dirlen > 0)
- -        memcpy(filename, p, dirlen);
- -    filename[dirlen] = '\0';
- -
- -    gettimeofday(&now, NULL);
- -
- -    rc = snprintf(filename + dirlen, FILENAME_SIZE, "darcs_lock_%s%04x%04x",
- -                  hostname, ((unsigned)getpid()) & 0xFFFF,
- -                  ((unsigned)(now.tv_usec ^ (now.tv_usec >> 16))) & 0xFFFF);
- -    if(rc < 0 || rc >= FILENAME_SIZE) {
- -        fprintf(stderr, "Error writing to lock filename (%d)\n", 
- -                rc < 0 ? errno : 0);
- -        goto fail2;
- -    }
- -
- -    fd = open(filename, O_WRONLY | O_EXCL | O_CREAT, 0666);
- -    if(fd < 0)
- -        goto fail2;
- -
- -    /* Paranoia: should cause the client to flush its metadata cache. */
- -    rc = close(fd);
- -    if(rc < 0) {
- -        fprintf(stderr, "Error closing file %s. (%d)\n", filename, errno);
- -        goto fail;
- -    }
- -
- -    rc = link(filename, p);
- -    if(rc >= 0)
- -        goto success;
- -    else if(errno == EPERM || errno == EOPNOTSUPP) {
- -        /* Linux returns EPERM when making hard links on filesystems
- -           that don't support them. */
- -        /* It seems that MacOS returns EOPNOTSUPP on filesystems that
- -           don't support hard links. */
- -        unlink(filename);
- -        free(filename);
- -        return sloppy_atomic_create(p);
- -    } else if(errno != EEXIST && errno != EIO)
- -        goto fail;
- -
- -    /* The link may still have been successful if we're running over
- -       UDP and got EEXIST or EIO.  Check the file's link count. */
- -
- -    rc = stat(filename, &sb);
- -    if(rc < 0) {
- -        goto fail;
- -    }
- -
- -    if(sb.st_nlink != 2) {
- -        errno = EEXIST;
- -        goto fail;
- -    }
- -
- - success:
- -    unlink(filename);
- -    free(filename);
- -    return 1;
- -
- - fail:
- -    saved_errno = errno;
- -    unlink(filename);
- -    errno = saved_errno;
- - fail2:
- -    free(filename);
- -    return -1;
- -}
- -
- -int atomic_create(const char *p)
- -{
- -    static int sloppy = -1;
- -
- -    if(sloppy < 0) {
- -        char *s = getenv("DARCS_SLOPPY_LOCKS");
- -        sloppy = (s != NULL);
- -    }
- -
- -    if(sloppy)
- -        return sloppy_atomic_create(p);
- -    else
- -        return careful_atomic_create(p);
- -}
- -
- -#endif
- -
hunk ./compat.h 6
- -int sloppy_atomic_create(const char *p);
- -int atomic_create(const char *p);
- -
- -#ifdef _WIN32
- -int renamefile(const char *from, const char *to);
- -#endif
- -
}

Context:

[remove TODO annotation for two tests that now pass.
David Roundy <droundy@abridgegame.org>**20050728115034] 
[fix bug introduced in 208 fix which messed up --list-options output.
David Roundy <droundy@abridgegame.org>**20050729121804
 We need to make sure that drop_paths doesn't do anything to an absolute
 path or URL.
] 
[Merge changes
Ian Lynagh <igloo@earth.li>**20050728230858] 
[Include autoconf-detected libs in LDFLAGS
Joshua J. Berry <condor-dev@condordes.net>**20050728031609
 Autoconf uses @LIBS@ -- not @LDFLAGS@ -- for libraries it detects (e.g. using
 AC_SEARCH_LIBS).
] 
[Update QueryManifest with the Repository changes
Ian Lynagh <igloo@earth.li>**20050728185646] 
[resolve conflict with myself...
David Roundy <droundy@abridgegame.org>**20050727100745] 
[fix pulling from a relative defaultrepo from within a subdirectory.
David Roundy <droundy@abridgegame.org>**20050722105708
 This is a fix for bug #208.  It is perhaps a tad more invasive than
 necesary, and introduces a FilePathUtils module that is perhaps
 overkill... especially since it doesn't do much.
] 
[Merge changes
Florian Weimer <fw@deneb.enyo.de>**20050607203225] 
[Fix typo
Florian Weimer <fw@deneb.enyo.de>**20050510113824] 
[Test case for "query manifest"
Florian Weimer <fw@deneb.enyo.de>**20050510113803] 
[Remove the "query changes" and "query annotate" subcommands
Florian Weimer <fw@deneb.enyo.de>**20050510060221] 
[Do not mention file name in error message for disabled commands
Florian Weimer <fw@deneb.enyo.de>**20050510054931
 
 We have multiple configuration files, and we do not know tat this point which
 file contains the "disable" option.
] 
[Remove --disable on supercommands
Florian Weimer <fw@deneb.enyo.de>**20050510054744] 
[Resolve conflict
Florian Weimer <fw@deneb.enyo.de>**20050510054405] 
[Add --help in command_options, like --disable
Florian Weimer <fw@deneb.enyo.de>**20050510053348
 
 --list-options is still separate, to keep it undocumented.
] 
[Resolve conflict
Florian Weimer <fw@deneb.enyo.de>**20050510052119] 
[Move --disable to the end of the option list
Florian Weimer <fw@deneb.enyo.de>**20050510051905] 
[Include the query subcommand documentation in Query.lhs
Florian Weimer <fw@deneb.enyo.de>**20050510051533] 
[Print usage information if the subcommand is missing
Florian Weimer <fw@deneb.enyo.de>**20050509101427
 
 Add a separating line to the invalid subcommand error message.
] 
[Fix empty lines in "darcs query --help" output
Florian Weimer <fw@deneb.enyo.de>**20050509100509] 
[Resolve conflicts
Florian Weimer <fw@deneb.enyo.de>**20050509094729] 
[Add the --disable option in command_options, not in run_the_command
Florian Weimer <fw@deneb.enyo.de>**20050509093929
   
 This change makes it possible to specialize the list of default commands
 (such as --disable) on different DarcsCommand constructors.
] 
[Add --pending option to "query manifest"
Florian Weimer <fw@deneb.enyo.de>**20050508080502] 
[Add the --files and --directories options to "query manifest"
Florian Weimer <fw@deneb.enyo.de>**20050507223327] 
[Implement list_slurpy_dirs
Florian Weimer <fw@deneb.enyo.de>**20050507223257] 
[Add --null flag to the "query manifest" command
Florian Weimer <fw@deneb.enyo.de>**20050507213547] 
[Add "query manifest" command
Florian Weimer <fw@deneb.enyo.de>**20050507163125] 
[Implement the \haskell command for subcommands
Florian Weimer <fw@deneb.enyo.de>**20050507160607] 
[Mention the structure of subcommands in the documentation
Florian Weimer <fw@deneb.enyo.de>**20050507151003] 
[Handle subcommands in the preprocessor
Florian Weimer <fw@deneb.enyo.de>**20050507150829
 
 You can use "\options{SUPER SUB}" to document the options of a
 subcommand.
] 
[Do not include the "query" command in the manual
Florian Weimer <fw@deneb.enyo.de>**20050507150707
 
 The commands will be documented individually, in the relevant section.
] 
[Mention "query" subcommands in the man page
Florian Weimer <fw@deneb.enyo.de>**20050507135756
 
 "changes" is now documented as "query changes".  "query annotate" is
 mentioned, too.
] 
[add subcommand infrastructure and (currently useless) query command.
David Roundy <droundy@abridgegame.org>**20050507115457
 The idea of course is that this can be readily extended to add nice new
 simple subcommands under query.
] 
[Don't die on sigALRM (linking with -threaded means we see loads of them)
Ian Lynagh <igloo@earth.li>**20050728131023] 
[Give help for 'c' in selectchanges
Ian Lynagh <igloo@earth.li>**20050728125910] 
[Small tweaks to the with_new_pending patch
Ian Lynagh <igloo@earth.li>**20050727025308] 
[replace write_pending with "with_new_pending".
David Roundy <droundy@abridgegame.org>**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.
] 
[new changelog entries.
David Roundy <droundy@abridgegame.org>**20050726123329] 
[clean up formatting in Depends.
David Roundy <droundy@abridgegame.org>**20050723130807] 
[changelog entry for fix to RT#208.
David Roundy <droundy@abridgegame.org>**20050722113803] 
[make make_changelog a bit more flexible in its parsing.
David Roundy <droundy@abridgegame.org>**20050722113701
 One can now have blank lines between the match: lines and the actual
 comments.
] 
[give better error message when dealing with a non-repository.
David Roundy <droundy@abridgegame.org>**20050722105908] 
[make make_changelog ignore boring files (emacs backups) in changelog.in/entries/.
David Roundy <droundy@abridgegame.org>**20050726121455] 
[add changelog entry for get --partial fix.
David Roundy <droundy@abridgegame.org>**20050723130715] 
[scrunch up the tla/cvs tables a bit in the manual.
David Roundy <droundy@abridgegame.org>**20050724181011] 
[another alternative formatting for cvs/tla tables.
Erik Schnetter <schnetter@aei.mpg.de>**20050724134656] 
[fix bug in get_patches_beyond_tag that broke get --partial.
David Roundy <droundy@abridgegame.org>**20050723125507
 The bug was that we sometimes looked at patches that weren't strictly
 necesary.  This was because of the concat in get_patches_beyond_tag, which
 loses information about tag dependencies.  A clean implementation of a
 get_extra that accepts a true PatchSet would be a nicer fix (since it might
 fix other similar problems), but this fix is also correct and simple.
] 
[alternative formatting for cvs/tla tables.
Erik Schnetter <schnetter@aei.mpg.de>**20050724113905] 
[make add/remove --list-options not output preceding ./
David Roundy <droundy@abridgegame.org>**20050723134758
 We were treating the repository root differently from subdirectories
 because the file paths didn't need to get "fixed".  Addresses bug #158.
] 
[fix unit test that prompts for input
Will <will@glozer.net>**20050722181028] 
[put configure.ac back in the public domain.
David Roundy <droundy@abridgegame.org>**20050720115702] 
[advance DARCS_VERSION to 1.0.4pre2.
David Roundy <droundy@abridgegame.org>**20050720115536
 In the new tradition of changing the version after a release rather than
 before a release (although when the release type changes to rc or actual
 release it'll have to be done before the release).
] 
[drop $srcdir use; build-directories aren't supported anyway
Peter Simons <simons@cryp.to>**20050719140044] 
[clean generated manual files at realclean
Peter Simons <simons@cryp.to>**20050719135935] 
[cosmetic changes
Peter Simons <simons@cryp.to>**20050719135834] 
[move comment to the right place
Peter Simons <simons@cryp.to>**20050719135818] 
[let config.status generate config.command
Peter Simons <simons@cryp.to>**20050719135733] 
[make use of autoconf 2.5x's AC_INIT macro
Peter Simons <simons@cryp.to>**20050719135611] 
[use ./config.status to re-configure build after autoconf changes
Peter Simons <simons@cryp.to>**20050719135435] 
[update distclean and realclean targets
Peter Simons <simons@cryp.to>**20050719135415] 
[canonize simons@cryp.to
Peter Simons <simons@cryp.to>**20050719134834] 
[cosmetic change
Peter Simons <simons@cryp.to>**20050719134816] 
[update test suite to work with Peter's makefile changes.
David Roundy <droundy@abridgegame.org>**20050721102319] 
[fix error in name of --reorder-patches flag.
David Roundy <droundy@abridgegame.org>**20050722110752] 
[Make DarcsRepo.add_to_inventory take a list.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050720174029
 This avoids opening the inventory multiple times.  Thanks to Ian for the hint.
] 
[Use mapM_ instead of the comprehensible alternative.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050720164258
 Mentioning mapM_ always impresses people at dinner parties.  Thanks to
 Ian for the hint.
] 
[Move iterateGitTree out of the IO monad.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050720162841
 We're reading immutable on-disk data, it's safe to do it unsafely.
] 
[Clean up usage of interleaveIO in Git.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050720162251] 
[TAG 1.0.4pre1
David Roundy <droundy@abridgegame.org>**20050718112234] 
[make configure automatically guess the release state based on defaultrepo and tags.
David Roundy <droundy@abridgegame.org>**20050718112222] 
[fix write_problem to show all problems.
David Roundy <droundy@abridgegame.org>**20050717110628] 
[don't import head and tail, which are in the prelude.
David Roundy <droundy@abridgegame.org>**20050716143547] 
[Push and pull can now show the detailed diffs of patches
Jim Radford <radford@blackbean.org>**20050717042645
 The same distinction is now made between --summary and --verbose
 as changes makes.
] 
[Rename bound variable in fromJust macro.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050716221705
 Avoids ``shadows existing variable'' warnings which for some reason are
 errors.
 
 Could we please use Lisp macros instead?
] 
[TAG 2005-07-18
Ian Lynagh <igloo@earth.li>**20050718193534] 
[bugfix, make _darcs/prefs/defaults really override $HOME/.darcs/defaults
Tommy Pettersson <ptp@lysator.liu.se>**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.
] 
[TAG 2005-007-16
Ian Lynagh <igloo@earth.li>**20050716181541] 
[Keep file modes in dirty Git slurpies.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050716071846
 This prevents Darcs from resetting Git file permissions.
] 
[Update HEAD in place.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050716071116] 
[Generalise write_pending.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050716002145
 I missed this, which breaks add and remove.
] 
[Use emptyGitSlurpy in gitCommitToPatch'.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050715234115] 
[Fix parsing of Git merges with no common ancestor.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050715233226] 
[Implement emptyGitSlurpy.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050715233211] 
[Fix typo in applyF_direct (Git).
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050715233140] 
[Don't include ./ when generating patches from Git.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050715203248] 
[Generalise rollback.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050715194322] 
[Make histories that come from Git lazy in the presence of merges.
Juliusz Chroboczek <jch@pps.jussieu.fr>**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 <jch@pps.jussieu.fr>**20050715192333] 
[move read/write format checks into identifyRepository and withRepoLock.
David Roundy <droundy@abridgegame.org>**20050714105840] 
[cleanups in RepoFormat as suggested by Ian.
David Roundy <droundy@abridgegame.org>**20050711125711] 
[Generalise Pull and Apply.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050712145643] 
[Generate Git PatchInfos from scratch.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050712123945
 patchtopatchinfo is not lazy enough.
] 
[Replace frobPatchFile with patchTokenToPatchFile.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050711045246] 
[Make writing of patches work in arbitrary directories.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050711021014] 
[Use impossible.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050711015640] 
[Make patch tokens opaque.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050711014829] 
[fix typo in git prefsUrl.
David Roundy <droundy@abridgegame.org>**20050711100531] 
[generalize Revert and Unrevert.
David Roundy <droundy@abridgegame.org>**20050711100429] 
[fix bug where we failed to convert sha1 to hex.
David Roundy <droundy@abridgegame.org>**20050711092602] 
[use AC_SEARCH_LIBS instead of AC_CHECK_LIB
Wim Lewis <wiml@hhhh.org>**20050707181811] 
[Update AC_PREREQ to 2.54
Wim Lewis <wiml@hhhh.org>**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.
] 
[don't go through shell when execing darcs
Wim Lewis <wiml@hhhh.org>**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 <wiml@hhhh.org>**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 <wiml@hhhh.org>**20050710050226] 
[Use a pipe instead of a temp file
Wim Lewis <wiml@hhhh.org>**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 <wiml@hhhh.org>**20050709023659] 
[Make record repository-format agnostic.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050710034630] 
[Implement polymorphic write support.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050710034310] 
[Make withRepoLock polymorphic.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050710023802] 
[Make writePatch and updateInventory polymorphic.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050710021543] 
[Make sync_repo polymorphic.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050710021426] 
[Import GitRepo from darcs-git.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050710015221
 This version has write support and support for reverse-engineering
 Darcs merges from Git merges.
] 
[Add ``lax'' argument to applyToGitSlurpy.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050710014814
 When lax is true, we apply merger_equivalent to mergers.
] 
[Make read/write_pending polymorphic.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050710012515] 
[Fix make_changelog to work with David's new identifyRepository.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050710002419] 
[Fix typo in import of malloc.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050710001235] 
[Add comment about immutability of Git trees.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050709215815] 
[Fix location of HEAD in Git.updateHead.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050709215408] 
[implement missing DarcsIO methods in SlurpMonad.
David Roundy <droundy@abridgegame.org>**20050709192216] 
[clean up GitTreeIterator.
David Roundy <droundy@abridgegame.org>**20050709174440] 
[eliminate excess touching in Git.
David Roundy <droundy@abridgegame.org>**20050709170954] 
[make GitFileInfo a cleaner more haskellish data type.
David Roundy <droundy@abridgegame.org>**20050709170457] 
[add some typesafety to haskell cache_entry-related Git code.
David Roundy <droundy@abridgegame.org>**20050709153935] 
[add a bit of type safety to the pointers to git_tree_iterator.
David Roundy <droundy@abridgegame.org>**20050709153337] 
[make GitFile use the ffi more nicely.
David Roundy <droundy@abridgegame.org>**20050709152131] 
[replace fromSingleton with gitSingleCommitValue which gives better error message.
David Roundy <droundy@abridgegame.org>**20050709145616] 
[implement CString utility functions in FastPackedString.
David Roundy <droundy@abridgegame.org>**20050709145549] 
[use withSlurpy to implement apply_to_slurpy.
David Roundy <droundy@abridgegame.org>**20050709145517] 
[make darcs send look in the right place for target email address.
David Roundy <droundy@abridgegame.org>**20050709121505] 
[fix bug in Repository abstraction code that broke remote pulls.
David Roundy <droundy@abridgegame.org>**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 <droundy@abridgegame.org>**20050709112017
 The idea being to be forward-compatible with repository format changes.
] 
[add an unused RepoFormat module.
David Roundy <droundy@abridgegame.org>**20050430123937] 
[Only read darcs/cgi.conf once.
Wim Lewis <wiml@hhhh.org>**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.)
] 
[Removed an unused reference to Slurpy
Ian Lynagh <igloo@earth.li>**20050709114603] 
[Documentation nits & typos
Wim Lewis <wiml@hhhh.org>**20050618193852] 
[Merge conflicts in configure.ac, and add blank line to try to avoid future conflicts
Ian Lynagh <igloo@earth.li>**20050707160658] 
[TAG 1.0.3
Tomasz Zielonka <tomasz.zielonka@gmail.com>**20050524215127] 
[bump version to 1.0.3
Tomasz Zielonka <tomasz.zielonka@gmail.com>**20050524215115] 
[Revert an accidental Repository -> DarcsRepo change in a string
Ian Lynagh <igloo@earth.li>**20050707160431] 
[Revert "Cache pristine directory within NoPristine"
Ian Lynagh <igloo@earth.li>**20050707153500] 
[fixed a few typos in docs & comments
Wim Lewis <wiml@hhhh.org>**20050624070640] 
[make git support configurable (copied from Juliusz's patch).
David Roundy <droundy@abridgegame.org>**20050701135046] 
[TAG another version that works in the git-merge saga.
David Roundy <droundy@abridgegame.org>**20050701133252] 
[fix errors from merging more darcs-git stuff.
David Roundy <droundy@abridgegame.org>**20050701133228] 
[resolve some more conflicts.
David Roundy <droundy@abridgegame.org>**20050701132446] 
[TAG working version in middle of darcs-git merge.
David Roundy <droundy@abridgegame.org>**20050701125730] 
[resolve conflicts between git and darcs-unstable.
David Roundy <droundy@abridgegame.org>**20050701125706] 
[Cache pristine directory within NoPristine.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050426172006] 
[eliminate unnecesary unsafePerformIOs in Git.
David Roundy <droundy@abridgegame.org>**20050701142312] 
[Move gitIsTree to C code.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050509235651] 
[Simplify gitBlobToPatches.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050509234445] 
[Remove obsolete comment.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050507195543] 
[Make ordering of trees Linus-compatible.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050507184412] 
[Don't sort when purifying Git slurpies.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050507024134
 The new ordering is preserved by purification.
] 
[Replace the definition of Ord on GitSlurpy with one that works.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050507023832
 This is still not Linus-compliant, as Haskell and C use different ordering
 conventions.
] 
[Fix typo in noname.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050506222328] 
[Make gitFooToPatches work with dirty trees.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050506200939] 
[Export GitSlurpy.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050506181048] 
[Implement a variant of gitCommitToPatch that takes a GitSlurpy reference.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050506180031] 
[Get rid of gitCommitToPIMP.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050505181603] 
[Move reading git commits out of the IO monad.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050505180609] 
[Simplify generation of PatchSets from Git repos.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050505170207] 
[Fix parsing of multiple parents in Git commits.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050505153025
 Multiple parents come in separate parent lines, not a single line as I
 thought.
] 
[Fix Git date handling.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504233745] 
[Fix formatting of Git files.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504211643] 
[Fix formatting of Git records.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504210607] 
[Only free those names that were allocated in git_write_tree_done.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504204933] 
[Free the right buffer in git_write_tree_done.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504204910] 
[Estimate the size of a new tree correctly.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504204850] 
[Actually create new .git/HEAD (blush).
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504204825] 
[Use "." as root of GitSlurpies.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504203304] 
[Implement updateHead.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504193546] 
[Implement git_update_head.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504193529] 
[Implement writeGitCommit.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504192232] 
[Add type argument to writeGitFile.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504185421] 
[Make slurpGitCommit return a GitSlurpy after all.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504143935] 
[Implement make_git_file_info.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504142613] 
[Implement purification of Git trees.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504142042] 
[Actually implement purification of blobs.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504125709] 
[Add repo argument to purify.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050503234432] 
[Partial implementation of purifyGitSlurpy.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050503232848] 
[Generalise trackdown.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050426233012] 
[Make whatsnew go through Repository.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050426162106
 This won't work for Git repositories until they implement slurp_recorded
 and get_recorded.
] 
[Implement git_format_time.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504192053] 
[Export Slurpy constructors.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050426195817] 
[Export applyBinary and applyHunkLines.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050503224204] 
[Really don't include directories in slurpies.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050429235609] 
[Make dist work with git repositories.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050426203906] 
[Fix merge conflicts.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050425194100] 
[Remove unsafeConstructPS.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050509233129] 
[Declare Git's global variables as extern.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050507224710
 Silly GHCi doesn't grok common symbols.
] 
[Use RepoPrefs.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050506220257] 
[Implement repoPrefs.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050506220152] 
[Export PatchInfo constructor.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050504190531] 
[Implement applyToGitSlurpy.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050503231941] 
[Basic implementation of dirty Git slurpies.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050503222642] 
[Use the cache when slurping the pristine state.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050430000813] 
[Restructure patch generation from Git repos.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050427213320] 
[Don't store directories in slurpies.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050427000833] 
[Instance Show Slurpy.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050426235914] 
[Start slurping at ".".
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050426203853] 
[Implement slurping from git repositories.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050426195957] 
[Make pattern exhaustive.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050426195941] 
[Check for presence of .git/HEAD.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050426195914] 
[Move slurp_pending and slurp_recorded into Repository.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050426185425] 
[Move get_unrecorded to Repository.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050426175527] 
[Implement send for git repositories.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050425210728] 
[Implement changes for git repositories.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050425205329] 
[Use ForeignPtrs instead of raw pointers when useful.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050425180449
 Now I remember why I hate Haskell.
] 
[Some less IO monad hacking.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050425180207] 
[Fix handling of subtrees.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050425162405] 
[Implement subtrees.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050425063228] 
[Parse new-style git dates.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050425001902] 
[Initial implementation of pulling from git.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050424213832] 
[Add licence statements to Linus' files.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050426161330] 
[Implement constructPS.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050425180306
 I use touchForeignPtr in the finaliser when building a PS from a
 ForeignPtr.
] 
[Import parts of Linus' git 0.6.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050424213310] 
[Implement unsafeConstructPS.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050424212204] 
[Export diff_files from Diff.lhs.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050424212113] 
[Export emptyFileContents from SlurpDirectory.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050424212051] 
[First cut at remodularising repo access.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050424145002] 
[Change Repository to DarcsRepo.
Juliusz Chroboczek <jch@pps.jussieu.fr>**20050424140132] 
[TAG 2005-07-07
Ian Lynagh <igloo@earth.li>**20050707144607] 
Patch bundle hash:
dd9c93b0a6fb70a15dae983cf6d212ada2e95093
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFC646qw1LMYXi7WGsRAu6VAKDQt02KSlKn/9QJHr+lFOW7zbDIWwCgnMp6
AirReX4lBGV0O7oazZfPvlY=
=il75
-----END PGP SIGNATURE-----


_______________________________________________
darcs-devel mailing list
darcs-devel@darcs.net
http://www.abridgegame.org/cgi-bin/mailman/listinfo/darcs-devel

.

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic