packages feed

cabal2arch-0.7.5: scripts/manycabal2arch.hs

-- |
-- Module    : manycabal2arch: batch creation of PKGBUILDs from Hackage tarball
-- Copyright : (c) Rémy Oudompheng 2010
-- License   : BSD3
--
-- Maintainer: Arch Haskell Team <arch-haskell@haskell.org>
-- Stability : provisional
-- Portability:
--

import Distribution.ArchLinux.PkgBuild
import Distribution.ArchLinux.CabalTranslation
import Distribution.ArchLinux.HackageTranslation

import Distribution.PackageDescription
import Distribution.Text
import Text.PrettyPrint

import Data.List
import qualified Data.ByteString.Lazy as Bytes
import System.Directory
import System.FilePath

-- Input/output
import System.Environment
import System.IO
import System.Process
import System.Exit

import qualified Control.OldException as C

import Debug.Trace

import Paths_cabal2arch

exportPackage :: FilePath -> String -> GenericPackageDescription -> IO ()
exportPackage dot email p = do
  let q = preprocessCabal p
  case q of
    Nothing -> return ()
    Just p' -> do
      let (pkg, script) = cabal2pkg p'
          pkgname = trace ("Converting package " ++ arch_pkgname pkg) (arch_pkgname pkg)
      pkgbuild  <- getMD5 pkg
      let apkgbuild = AnnotatedPkgBuild { pkgBuiltWith = Just version, pkgHeader = comment, pkgBody = pkgbuild }
          rawpkgbuild = (render $ pkg2doc email apkgbuild) ++ "\n"

      createDirectoryIfMissing True (dot </> pkgname)
      writeFile (dot </> pkgname </> "PKGBUILD") rawpkgbuild
      case script of
        Nothing -> return ()
        Just s -> writeFile (dot </> pkgname </> pkgname ++ ".install") s

main :: IO ()
main = do
  argv <- getArgs
  x <- case argv of
    _:_:_:_ -> return ()
    _ -> help
  pkglist <- readFile (argv !! 0)
  tarball <- Bytes.readFile (argv !! 1)
  repo <- canonicalizePath (argv !! 2)
  email <- do
    r <- getEnvMaybe "ARCH_HASKELL"
    case r of
      Nothing -> do hPutStrLn stderr "Warning: ARCH_HASKELL environment variable not set. Set this to the maintainer contact you wish to use. \n E.g. 'Arch Haskell Team <arch-haskell@haskell.org>'"
                    return []
      Just s  -> return s
  let cabals = getSpecifiedCabalsFromTarball tarball (lines pkglist)
  mapM (exportPackage repo email) cabals
  return ()

-- Safe wrapper for getEnv                                                                                            
getEnvMaybe :: String -> IO (Maybe String)
getEnvMaybe name = C.handle (const $ return Nothing) (Just `fmap` getEnv name)

comment :: String
comment = render $ vcat
 [ text "# Note: we list all package dependencies."
 , text "# Your package tool should understand 'provides' syntax"
 , text "#"
 , text "# Keep up to date on http://archhaskell.wordpress.com/"
 , text "#"]

-- | Given an abstract pkgbuild, run "makepkg -g" to compute md5
-- of source files (possibly cached locally), and modify the PkgBuild
-- accordingly.
--
getMD5 :: PkgBuild -> IO PkgBuild
getMD5 pkg = do
   putStrLn "Feeding the PKGBUILD to `makepkg -g`..."
   eres <- readProcessWithExitCode "makepkg" ["-g"] (render $ disp pkg)
   case eres of
       (ExitFailure _,_,err) -> do
            hPutStrLn stderr err
            hPutStrLn stderr $ "makepkg encountered an error while calculating MD5."
            return pkg
       (ExitSuccess,out,err) -> do
            -- s should be "md5sums=(' ... ')"
            hPutStrLn stderr err
            if "md5sums=('" `isPrefixOf` out
               then
                 let md5sum = takeWhile (\x -> x `elem` "0123456789abcdef") $ drop 10 out
                 in return pkg { arch_md5sum = ArchList [md5sum] }
               else do
                 hPutStrLn stderr $ "Incorrect output from makepkg."
                 return pkg

--
-- | Help file
--
help :: IO a
help = do
 hPutStrLn stderr $ unlines
    [ "Usage: manycabal2arch pkglist tarball destination"
    , ""
    , "  Generate a ABS-like tree from a list of packages and the"
    , "  uncompressed Hackage tarball"
    , ""
    , "Arguments: pkglist"
    , "              A file with lines of the form \"<package-name> <version-number>\""
    , "           tarball"
    , "              The path to 00-index.tar, for example"
    , "              $HOME/.cabal/packages/hackage.haskell.org/00-index.tar"
    , "           destination"
    , "              The directory where the repository will be created"
    ]
 exitWith ExitSuccess