@@ -1,44 +1,84 @@
11import Distribution.Simple
22import Distribution.PackageDescription ( emptyHookedBuildInfo )
33import Control.Exception ( bracket_ )
4−import System.Process ( runCommand, waitForProcess )
5−import System.FilePath ( (</>) )
6−import System.Directory ( getCurrentDirectory, setCurrentDirectory, findExecutable, doesFileExist )
4+import System.Process ( runCommand, runProcess, waitForProcess )
5+import System.FilePath ( (</>), (<.>) )
6+import System.Directory
77import System.IO ( stderr )
88import System.Exit
9−import Data.Maybe ( fromJust )
9+import System.Time
10+import System.IO.Error ( isDoesNotExistError )
11+import Data.Maybe ( fromJust, isNothing, catMaybes )
1012
11−main = defaultMainWithHooks (simpleUserHooks {runTests = runTestSuite, preConf = checkReferenceODT})
13+main = defaultMainWithHooks $
14+ simpleUserHooks { runTests = runTestSuite
15+ , preConf = checkReferenceODT
16+ , postBuild = makeManPages }
1217
1318-- | Run test suite.
1419runTestSuite _ _ _ _ = do
1520 inDirectory "tests" $ runCommand "runhaskell RunTests.hs" >>= waitForProcess
1621 return ()
1722
18−-- | If reference.odt does not exist, build it.
19−checkReferenceODT _ _ = do
20− refODTexists <- doesFileExist ("odt-styles" </> "reference.odt")
21− if refODTexists
23+-- | If reference.odt needs rebuilding, build it.
24+checkReferenceODT _ _ = inDirectory "odt-styles" $ do
25+ let refodt = "reference.odt"
26+ let deps = [ "meta.xml", "content.xml", "settings.xml", "META-INF/manifest.xml",
27+ "Thumbnails/thumbnail.png", "styles.xml", "mimetype" ]
28+ modifiedDeps <- modifiedDependencies refodt deps
29+ if null modifiedDeps
2230 then return ()
23− else makeReferenceODT
31+ else makeReferenceODT modifiedDeps
2432 return emptyHookedBuildInfo
2533
2634-- | Create reference.odt by zipping up sources in odt-styles directory.
27−makeReferenceODT :: IO ()
28−makeReferenceODT = do
35+makeReferenceODT :: [FilePath] -> IO ()
36+makeReferenceODT sources = do
2937 zipPathMaybe <- findExecutable "zip"
30− if zipPathMaybe == Nothing
38+ if isNothing zipPathMaybe
3139 then error $ "The 'zip' command, which is needed to build reference.odt\n" ++
3240 "from sources in the odt-styles directory, was not found.\n" ++
3341 "Try again after installing zip (http://www.info-zip.org/Zip.html).\n" ++
3442 "Or use the pandoc source tarball, which contains a prebuilt reference.odt."
3543 else do
3644 putStrLn "Creating reference.odt:"
37− inDirectory "odt-styles" $ do
38− ec <- runCommand "zip -9 -r reference.odt *" >>= waitForProcess
39− case ec of
40− ExitSuccess -> putStrLn "Done."
41− _ -> error "Error creating ODT."
45+ ec <- runProcess (fromJust zipPathMaybe) (["-9", "-r", "reference.odt"] ++ sources)
46+ Nothing Nothing Nothing Nothing (Just stderr) >>= waitForProcess
47+ case ec of
48+ ExitSuccess -> return ()
49+ _ -> error "Error creating ODT."
50+
51+-- | Build man pages from markdown sources in man/man1/.
52+makeManPages _ _ _ _ = do
53+ mapM makeManPage ["pandoc.1", "hsmarkdown.1", "markdown2pdf.1", "html2markdown.1"]
54+ return ()
55+
56+-- | Build a man page from markdown source in man/man1.
57+makeManPage manpage = do
58+ let manDir = "man" </> "man1"
59+ let pandoc = "dist" </> "build" </> "pandoc" </> "pandoc"
60+ let page = manDir </> manpage
61+ let source = manDir </> manpage <.> "md"
62+ modifiedDeps <- modifiedDependencies page [source]
63+ if null modifiedDeps
64+ then return ()
65+ else do
66+ ec <- runProcess pandoc ["-s", "-r", "markdown", "-w", "man", "-o", page, source]
67+ Nothing Nothing Nothing Nothing (Just stderr) >>= waitForProcess
68+ case ec of
69+ ExitSuccess -> putStrLn $ "Created " ++ manDir </> manpage
70+ _ -> error $ "Error creating " ++ manDir </> manpage
71+
72+-- | Returns a list of 'dependencies' that have been modified after 'file'.
73+modifiedDependencies :: FilePath -> [FilePath] -> IO [FilePath]
74+modifiedDependencies file dependencies = do
75+ fileModTime <- catch (getModificationTime file) $
76+ \e -> if isDoesNotExistError e
77+ then return (TOD 0 0) -- the minimum ClockTime
78+ else ioError e
79+ depModTimes <- mapM getModificationTime dependencies
80+ let modified = zipWith (\dep time -> if time > fileModTime then Just dep else Nothing) dependencies depModTimes
81+ return $ catMaybes modified
4282
4383-- | Perform an IO action in a directory.
4484inDirectory :: FilePath -> IO a -> IO a