Ticket #1839: Main.hs.diff

File Main.hs.diff, 10.7 KB (added by guest, 5 years ago)

diff -u patch to utils/ghc-pkg/Main.hs, implementing --bulk

  • utils/ghc-pkg/Main.hs

    old new  
    4646import System ( getArgs, getProgName, getEnv, exitWith, ExitCode(..) ) 
    4747import System.IO 
    4848import System.IO.Error (try) 
    49 import Data.List ( isPrefixOf, isSuffixOf, intersperse, sortBy ) 
     49import Data.List ( isPrefixOf, isSuffixOf, intersperse, sortBy, unfoldr, break ) 
     50import Text.Regex 
    5051 
    5152#ifdef mingw32_HOST_OS 
    5253import Foreign 
     
    100101  | FlagDefinedName String String 
    101102  | FlagSimpleOutput 
    102103  | FlagNamesOnly 
     104  | FlagBulkQueries 
    103105  deriving Eq 
    104106 
    105107flags :: [OptDescr Flag] 
     
    127129  Option [] ["simple-output"] (NoArg FlagSimpleOutput) 
    128130        "print output in easy-to-parse format for some commands", 
    129131  Option [] ["names-only"] (NoArg FlagNamesOnly) 
    130         "only print package names, not versions; can only be used with list --simple-output" 
     132        "only print package names, not versions; can only be used with list --simple-output", 
     133  Option [] ["bulk"] (NoArg FlagBulkQueries) 
     134        "enable bulk queries" 
    131135  ] 
    132136 where 
    133137  toDefined str = 
     
    162166  "  $p list [pkg]\n" ++ 
    163167  "    List registered packages in the global database, and also the\n" ++ 
    164168  "    user database if --user is given. If a package name is given\n" ++ 
    165   "    all the registered versions will be listed in ascending order.\n" ++ 
     169  "    All the registered versions will be listed in ascending order.\n" ++ 
     170  "    Accepts package patterns if --bulk is given.\n" ++ 
     171  "    Accepts the --simple-output flag.\n" ++ 
     172  "\n" ++ 
     173  "  $p find-module {module}\n" ++ 
     174  "    List registered packages exposing module {module} in the global\n" ++ 
     175  "    database, and also the user database if --user is given. \n" ++ 
     176  "    All the registered versions will be listed in ascending order.\n" ++ 
     177  "    Accepts module patterns if --bulk is given.\n" ++ 
    166178  "    Accepts the --simple-output flag.\n" ++ 
    167179  "\n" ++ 
    168180  "  $p latest pkg\n" ++ 
     
    175187  "  $p describe {pkg-id}\n" ++ 
    176188  "    Give the registered description for the specified package. The\n" ++ 
    177189  "    description is returned in precisely the syntax required by $p\n" ++ 
    178   "    register.\n" ++ 
     190  "    register. Accepts package patterns if --bulk is given.\n" ++ 
    179191  "\n" ++ 
    180192  "  $p field {pkg-id} {field}\n" ++ 
    181193  "    Extract the specified field of the package description for the\n" ++ 
    182   "    specified package.\n" ++ 
     194  "    specified package. Accepts package patterns and comma-separated\n" ++ 
     195  "    multiple fields if --bulk is given.\n" ++ 
    183196  "\n" ++ 
    184197  " The following optional flags are also accepted:\n" 
    185198 
     
    193206 
    194207data Force = ForceAll | ForceFiles | NoForce 
    195208 
     209data PackageArg = Id PackageIdentifier | Pattern String 
     210 
    196211runit :: [Flag] -> [String] -> IO () 
    197212runit cli nonopts = do 
    198213  prog <- getProgramName 
     
    203218          | otherwise                   = NoForce 
    204219        auto_ghci_libs = FlagAutoGHCiLibs `elem` cli 
    205220        defines = [ (nm,val) | FlagDefinedName nm val <- cli ] 
     221        splitFields fields = unfoldr splitComma (',':fields) 
     222          where splitComma "" = Nothing 
     223                splitComma fs = Just $ break (==',') (tail fs) 
    206224  -- 
    207225  -- first, parse the command 
    208226  case nonopts of 
     
    220238        pkgid <- readGlobPkgId pkgid_str 
    221239        hidePackage pkgid cli 
    222240    ["list"] -> do 
    223         listPackages cli Nothing 
     241        listPackages cli Nothing Nothing 
     242    ["list", pkgid_pattern_str] | FlagBulkQueries `elem` cli -> do 
     243        listPackages cli (Just (Pattern pkgid_pattern_str)) Nothing 
    224244    ["list", pkgid_str] -> do 
    225245        pkgid <- readGlobPkgId pkgid_str 
    226         listPackages cli (Just pkgid) 
     246        listPackages cli (Just (Id pkgid)) Nothing 
     247    ["find-module", moduleName] -> do 
     248        listPackages cli Nothing (Just moduleName) 
    227249    ["latest", pkgid_str] -> do 
    228250        pkgid <- readGlobPkgId pkgid_str 
    229251        latestPackage cli pkgid 
     252    ["describe", pkgid_pattern_str] | FlagBulkQueries `elem` cli -> do 
     253        describePackage cli (Pattern pkgid_pattern_str) 
    230254    ["describe", pkgid_str] -> do 
    231255        pkgid <- readGlobPkgId pkgid_str 
    232         describePackage cli pkgid 
     256        describePackage cli (Id pkgid) 
     257    ["field", pkgid_pattern_str, fields] | FlagBulkQueries `elem` cli -> do 
     258        describeField cli (Pattern pkgid_pattern_str) (splitFields fields) 
    233259    ["field", pkgid_str, field] -> do 
    234260        pkgid <- readGlobPkgId pkgid_str 
    235         describeField cli pkgid field 
     261        describeField cli (Id pkgid) [field] 
    236262    ["check"] -> do 
    237263        checkConsistency cli 
    238264    [] -> do 
     
    445471modifyPackage fn pkgid flags  = do 
    446472  db_stack <- getPkgDatabases True{-modify-} flags 
    447473  let ((db_name, pkgs) : _) = db_stack 
    448   ps <- findPackages [(db_name,pkgs)] pkgid 
     474  ps <- findPackages [(db_name,pkgs)] (Id pkgid) 
    449475  let pids = map package ps 
    450476  let new_config = concat (map modify pkgs) 
    451477      modify pkg 
     
    457483-- ----------------------------------------------------------------------------- 
    458484-- Listing packages 
    459485 
    460 listPackages ::  [Flag] -> Maybe PackageIdentifier -> IO () 
    461 listPackages flags mPackageName = do 
     486listPackages ::  [Flag] -> Maybe PackageArg -> Maybe String -> IO () 
     487listPackages flags mPackageName mModuleName = do 
    462488  let simple_output = FlagSimpleOutput `elem` flags 
    463489  db_stack <- getPkgDatabases False flags 
    464490  let db_stack_filtered -- if a package is given, filter out all other packages 
    465491        | Just this <- mPackageName = 
    466492            map (\(conf,pkgs) -> (conf, filter (this `matchesPkg`) pkgs)) 
    467493                db_stack 
     494        | Just this <- mModuleName = -- packages which expose mModuleName 
     495            map (\(conf,pkgs) -> (conf, filter (this `exposedInPkg`) pkgs)) 
     496                db_stack 
    468497        | otherwise = db_stack 
    469498 
    470499      db_stack_sorted 
     
    501530          when (null pkgs) $ die "no matches" 
    502531          hPutStrLn stdout $ concat $ intersperse " " pkgs 
    503532 
     533        exposedInPkg :: String -> InstalledPackageInfo -> Bool 
     534        moduleName `exposedInPkg` pkg | FlagBulkQueries `elem` flags  
     535          = any (isJust . (mkRegex moduleName `matchRegex`)) (exposedModules pkg) 
     536        moduleName `exposedInPkg` pkg  
     537          = moduleName `elem` exposedModules pkg 
     538 
     539 
    504540-- ----------------------------------------------------------------------------- 
    505541-- Prints the highest (hidden or exposed) version of a package 
    506542 
    507543latestPackage ::  [Flag] -> PackageIdentifier -> IO () 
    508544latestPackage flags pkgid = do 
    509545  db_stack <- getPkgDatabases False flags 
    510   ps <- findPackages db_stack pkgid 
     546  ps <- findPackages db_stack (Id pkgid) 
    511547  show_pkg (sortBy compPkgIdVer (map package ps)) 
    512548  where 
    513549    show_pkg [] = die "no matches" 
     
    516552-- ----------------------------------------------------------------------------- 
    517553-- Describe 
    518554 
    519 describePackage :: [Flag] -> PackageIdentifier -> IO () 
    520 describePackage flags pkgid = do 
     555describePackage :: [Flag] -> PackageArg -> IO () 
     556describePackage flags pkgarg = do 
    521557  db_stack <- getPkgDatabases False flags 
    522   ps <- findPackages db_stack pkgid 
     558  ps <- findPackages db_stack pkgarg 
    523559  mapM_ (putStrLn . showInstalledPackageInfo) ps 
    524560 
    525561-- PackageId is can have globVersion for the version 
    526 findPackages :: PackageDBStack -> PackageIdentifier -> IO [InstalledPackageInfo] 
    527 findPackages db_stack pkgid 
    528   = case [ p | p <- all_pkgs, pkgid `matchesPkg` p ] of 
    529         []  -> die ("cannot find package " ++ showPackageId pkgid) 
     562findPackages :: PackageDBStack -> PackageArg -> IO [InstalledPackageInfo] 
     563findPackages db_stack pkgarg 
     564  = case [ p | p <- all_pkgs, pkgarg `matchesPkg` p ] of 
     565        []  -> die ("cannot find package " ++ pkg_msg pkgarg) 
    530566        ps -> return ps 
    531567  where 
    532568        all_pkgs = concat (map snd db_stack) 
     569        pkg_msg (Id pkgid)       = showPackageId pkgid 
     570        pkg_msg (Pattern pkgpat) = "matching "++pkgpat 
    533571 
    534572matches :: PackageIdentifier -> PackageIdentifier -> Bool 
    535573pid `matches` pid' 
    536574  = (pkgName pid == pkgName pid') 
    537575    && (pkgVersion pid == pkgVersion pid' || not (realVersion pid)) 
    538576 
    539 matchesPkg :: PackageIdentifier -> InstalledPackageInfo -> Bool 
    540 pid `matchesPkg` pkg = pid `matches` package pkg 
     577pat_matches :: String -> PackageIdentifier -> Bool 
     578pat `pat_matches` pid 
     579  = maybe False (const True) (mkRegex pat `matchRegex` pkgName pid) 
     580 
     581matchesPkg :: PackageArg -> InstalledPackageInfo -> Bool 
     582(Id pid)      `matchesPkg` pkg = pid `matches` package pkg 
     583(Pattern pat) `matchesPkg` pkg = pat `pat_matches` package pkg 
    541584 
    542585compPkgIdVer :: PackageIdentifier -> PackageIdentifier -> Ordering 
    543586compPkgIdVer p1 p2 = pkgVersion p1 `compare` pkgVersion p2 
     
    545588-- ----------------------------------------------------------------------------- 
    546589-- Field 
    547590 
    548 describeField :: [Flag] -> PackageIdentifier -> String -> IO () 
    549 describeField flags pkgid field = do 
     591describeField :: [Flag] -> PackageArg -> [String] -> IO () 
     592describeField flags pkgarg fields = do 
    550593  db_stack <- getPkgDatabases False flags 
    551   case toField field of 
    552     Nothing -> die ("unknown field: " ++ field) 
    553     Just fn -> do 
    554         ps <- findPackages db_stack pkgid 
    555         let top_dir = takeDirectory (fst (last db_stack)) 
    556         mapM_ (putStrLn . fn) (mungePackagePaths top_dir ps) 
     594  fns <- toFields fields 
     595  ps <- findPackages db_stack pkgarg 
     596  let top_dir = takeDirectory (fst (last db_stack)) 
     597  mapM_ (selectFields fns) (mungePackagePaths top_dir ps) 
     598  where toFields [] = return []  
     599        toFields (f:fs) = case toField f of 
     600            Nothing -> die ("unknown field: " ++ f) 
     601            Just fn -> do fns <- toFields fs 
     602                          return (fn:fns) 
     603        selectFields fns info = mapM_ (\fn->putStrLn (fn info)) fns 
    557604 
    558605mungePackagePaths :: String -> [InstalledPackageInfo] -> [InstalledPackageInfo] 
    559606-- Replace the strings "$topdir" and "$httptopdir" at the beginning of a path 
     
    947994      defines = [ (nm,val) | OF_DefinedName nm val <- clis ] 
    948995 
    949996  case [ c | c <- clis, isAction c ] of 
    950     [ OF_List ]      -> listPackages new_flags Nothing 
    951     [ OF_ListLocal ] -> listPackages new_flags Nothing 
     997    [ OF_List ]      -> listPackages new_flags Nothing Nothing 
     998    [ OF_ListLocal ] -> listPackages new_flags Nothing Nothing 
    952999    [ OF_Add upd ]   -> 
    9531000        registerPackage input_file defines new_flags auto_ghci_libs upd force 
    9541001    [ OF_Remove pkgid_str ]  -> do 
     
    9571004    [ OF_Show pkgid_str ] 
    9581005        | null fields -> do 
    9591006                pkgid <- readPkgId pkgid_str 
    960                 describePackage new_flags pkgid 
     1007                describePackage new_flags (Id pkgid) 
    9611008        | otherwise   -> do 
    9621009                pkgid <- readPkgId pkgid_str 
    963                 mapM_ (describeField new_flags pkgid) fields 
     1010                mapM_ (describeField new_flags (Id pkgid)) [fields] 
    9641011    _ -> do 
    9651012        prog <- getProgramName 
    9661013        die (usageInfo (usageHeader prog) flags)