hunk ./Graph.hs 18 -import Data.ByteString.Char8 (ByteString,append,pack,unpack) +import Data.ByteString.Char8 (ByteString,pack,unpack) hunk ./Graph.hs 25 -import Foreign.C.Error -import Foreign.Storable (peek) -import Foreign.Ptr (Ptr, nullPtr) -import Foreign.Marshal (alloca) - hunk ./Graph.hs 27 -import System.Posix.Internals -import System.IO.Error (modifyIOError, ioeSetFileName) hunk ./Graph.hs 29 -import System.Time hunk ./Graph.hs 31 +import System.Exit +import Data.Time +import System.Locale hunk ./Graph.hs 64 -getFilter :: [Flag] -> Maybe ByteString +getFilter :: [Flag] -> Maybe Day--ByteString hunk ./Graph.hs 67 - in if null l' then Nothing else Just . pack . head $ l' + in if null l' then Nothing else parseTime defaultTimeLocale "%Y%m%d" (head l') hunk ./Graph.hs 104 - -- read patches dir, count patch dates, and write to temp file - ps <- readDir (path `append` pack "/_darcs/patches/") + changes <- darcsChanges (unpack path) hunk ./Graph.hs 106 - let stats' = uniq . sort . map (C.take 8) . filter ignore $ ps + let stats' = uniq $ sort $ parseChanges changes hunk ./Graph.hs 116 - let days = enumDates (toClock . fst . head $ stats) (toClock . fst . last $ stats) + let days = enumDates (fst . head $ stats) (fst . last $ stats) hunk ./Graph.hs 154 - readFst (a,b) = ((fst . fromJust . C.readInt) a, b) + readFst (a,b) = (toInt a, b) hunk ./Graph.hs 157 - fmt (s,n) = joinWithSpace s (pack . show $ n) - fmt' (n,d) = joinWithSpace (pack.show $ n) (pack.show $ d) + fmtCT c = formatTime defaultTimeLocale "%Y%m%d" c + fmt (s,n) = joinWithSpace (fmtCT s) (show n) + fmt' (n,d) = joinWithSpace (show n) (show d) hunk ./Graph.hs 161 - ignore f = f /= pack "unrevert" - && not (pack "pending" `C.isPrefixOf` f) - && not (pack "." `C.isPrefixOf` f) + joinWithSpace s t = B.intercalate (B.singleton 32) [pack s,pack t] hunk ./Graph.hs 163 - joinWithSpace s t = B.intercalate (B.singleton 32) [s,t] +parseChanges :: ByteString -> [Day] +parseChanges chs + = worker (C.lines chs) + where worker [] = [] + worker (c:cs) | Just utcTime <- parseTime defaultTimeLocale "%a %b %e %X %Z %Y" (unwords $ take 6 $ words $ C.unpack c) + = utcTime:worker cs + worker (_:cs) = worker cs hunk ./Graph.hs 171 +darcsChanges :: FilePath -> IO ByteString +darcsChanges path + = do (inh,outh,errh,pid) <- runInteractiveProcess "darcs" ["changes","--repo="++path] Nothing Nothing + hClose inh + hClose errh + out <- B.hGetContents outh + code <- waitForProcess pid + case code of + ExitFailure c -> do hPutStrLn stderr "`darcs --changes` failed." + exitWith (ExitFailure c) + ExitSuccess -> return out hunk ./Graph.hs 189 -enumDates :: ClockTime -> ClockTime -> [ClockTime] -enumDates d0 dn = map (\d -> addToClockTime (TimeDiff 0 0 d 0 0 0 0) d0) [0 .. days] +enumDates :: Day -> Day -> [Day] +enumDates d0 dn = map (\d -> addDays d d0) [0 .. days] hunk ./Graph.hs 192 - t = diffClockTimes dn d0 - days = floor (((fromIntegral $ tdSec t) / 60 / 60 / 24) :: Double) - --- --- convert a date packed in a bytestring to a ClockTime --- yyyymmdd format. --- -toClock :: ByteString -> ClockTime -toClock x = toClockTime $ CalendarTime { - ctYear = y, - ctMonth = toEnum (m-1) :: Month, - ctDay = d, - ctHour = 0, ctMin = 0, ctSec = 0, ctPicosec = 0, - ctWDay = undefined, ctYDay = undefined, - ctTZName = "GMT", ctTZ = 0 , ctIsDST = False - } - where (y,m,d) = split x - - -- read the bytestring as a triple of yyyymmdd - split s = let a = fst . fromJust . C.readInt . C.take 4 $ s - b = fst . fromJust . C.readInt . C.drop 4 . C.take 6 $ s - c = fst . fromJust . C.readInt . C.drop 6 . C.take 8 $ s - in (a,b,c) + days = diffDays dn d0 hunk ./Graph.hs 197 -toInt :: ClockTime -> Int -toInt ct = read $ show yyyy ++ show0 mm ++ show0 dd - where yyyy = ctYear cl - mm = fromEnum (ctMonth cl) + 1 - dd = ctDay cl - - cl = unsafePerformIO (toCalendarTime ct) - show0 n | n < 10 && n >= 0 = '0' : show n - | otherwise = show n +toInt :: Day -> Int +toInt ct = read $ formatTime defaultTimeLocale "%Y%m%d" ct hunk ./Graph.hs 266 --- --- | Packed version of get directory contents. super fast --- -readDir :: ByteString -> IO [ByteString] -readDir path = do - modifyIOError (`ioeSetFileName` (unpack path)) $ - alloca $ \ ptr_dEnt -> - bracket - (C.useAsCString path $ \s -> - throwErrnoIfNullRetry desc (c_opendir s)) - (\p -> throwErrnoIfMinus1_ desc (c_closedir p)) - (\p -> loop ptr_dEnt p) - where - desc = "readDir" - - loop :: Ptr (Ptr CDirent) -> Ptr CDir -> IO [ByteString] - loop ptr_dEnt dir = do - resetErrno - r <- readdir dir ptr_dEnt - if (r == 0) - then do dEnt <- peek ptr_dEnt - if (dEnt == nullPtr) - then return [] - else do -- copy entry out before we free: - entry <- C.packCString =<< d_name dEnt - C.length entry `seq` return () -- strictify - freeDirEnt dEnt - entries <- loop ptr_dEnt dir - return $! (entry:entries) - - else do errno <- getErrno - if (errno == eINTR) - then loop ptr_dEnt dir - else do let (Errno eo) = errno - if (eo == end_of_dir) - then return [] - else throwErrno desc - hunk ./darcs-graph.cabal 20 - + + build-depends: time hunk ./darcs-graph.cabal 27 + old-locale, hunk ./darcs-graph.cabal 23 - build-depends: base >= 3, + build-depends: base >= 3 && < 4, hunk ./darcs-graph.cabal 2 -Version: 0.3.2 +Version: 0.3.3 hunk ./darcs-graph.cabal 2 -Version: 0.3.3 +Version: 1.0