packages feed

thank-you-stars 0.1.0 → 0.2.0

raw patch · 5 files changed

+87/−68 lines, 5 files

Files

README.md view
@@ -2,9 +2,10 @@ ===============  [![Build Status](https://travis-ci.org/y-taka-23/thank-you-stars.svg?branch=master)](https://travis-ci.org/y-taka-23/thank-you-stars)+[![Hackage](https://img.shields.io/hackage/v/thank-you-stars.svg)](https://hackage.haskell.org/package/thank-you-stars)  A tool for starring GitHub repositories. It detects dependent libraries-which are hosted on GitHub via `package.cabal` file,+which are hosted on GitHub via `.cabal` file, and stars the repositories all at once.  Setup@@ -34,7 +35,8 @@ -----  Run `thank-you-stars` in the root directory of your project.-Then it scans the `package.cabal` and the local Hackage DB,+Then it scans all `.cabal` files under the current directory+and metadata of the packages from the local Stackage DB, stars your dependent libraries if they are hosted on GitHub.  ```console
app/Main.hs view
@@ -3,29 +3,24 @@ import Utils.ThankYouStars.GitHub import Utils.ThankYouStars.Package -import           Control.Exception ( SomeException, catch )-import           Data.Maybe        ( catMaybes ) import qualified Data.Set          as S import           System.Exit       ( die ) import           System.Directory  ( getHomeDirectory )-import           System.FilePath   ( joinPath, (<.>) )+import           System.FilePath   ( joinPath )  main :: IO () main = do     homeDir <- getHomeDirectory-    thisPkg <- getThisPackageName     let tokenFile = joinPath [homeDir, ".thank-you-stars.json"]-        cabalFile = unPackageName thisPkg <.> "cabal"     eToken <- readToken tokenFile     case eToken of         Left  _ -> do             die ("Cannot parse " ++ show tokenFile ++ " into a token")-        Right token  -> do-            desc <- readCabalFile cabalFile-            db   <- readHackage-            let pkgs   = S.delete thisPkg $ allBuildDepends desc-                mRepos = S.map (flip lookupRepo $ db) pkgs-                repos  = catMaybes $ S.toList mRepos+        Right token -> do+            db     <- readStackIndex+            cabals <- getCabalFiles+            descs  <- mapM readCabalFile $ S.toList cabals+            let repos = S.unions $ map (dependentRepos db) descs             mapM_ (starAction token) repos  starAction :: Token -> GitHubRepo -> IO ()
src/Utils/ThankYouStars/Package.hs view
@@ -1,26 +1,32 @@ module Utils.ThankYouStars.Package (-      getThisPackageName-    , allBuildDepends-    , readHackage-    , lookupRepo+      dependentRepos+    , getCabalFiles     , readCabalFile-    , unPackageName+    , readStackIndex     ) where  import Utils.ThankYouStars.GitHub -import           Data.List                             ( isInfixOf )+import           Data.List                             ( isInfixOf, isPrefixOf ) import           Data.List.Split                       ( splitOneOf ) import qualified Data.Map                              as M import qualified Data.Set                              as S import           Data.Maybe-import           Distribution.Hackage.DB               ( Hackage, readHackage )+import           Distribution.Hackage.DB               ( Hackage, readHackage' ) import           Distribution.Package import           Distribution.PackageDescription import           Distribution.PackageDescription.Parse ( readPackageDescription ) import           Distribution.Verbosity                ( normal )-import           System.Directory                      ( getCurrentDirectory )-import           System.FilePath                       ( takeBaseName )+import           System.Directory                      ( getCurrentDirectory+                                                       , getAppUserDataDirectory+                                                       , getPermissions+                                                       , searchable+                                                       , listDirectory+                                                       )+import           System.FilePath                       ( joinPath+                                                       , combine+                                                       , takeExtension+                                                       )  allBuildDepends :: GenericPackageDescription -> S.Set PackageName allBuildDepends desc =@@ -33,12 +39,33 @@ depends :: BuildInfo -> [PackageName] depends = map toPackageName . targetBuildDepends -getThisPackageName :: IO PackageName-getThisPackageName = (PackageName . takeBaseName) <$> getCurrentDirectory+getCabalFiles :: IO (S.Set FilePath)+getCabalFiles = getCurrentDirectory >>= searchCabalFiles +searchCabalFiles :: FilePath -> IO (S.Set FilePath)+searchCabalFiles fp = do+    p <- getPermissions fp+    if searchable p+        then do+            children <- map (combine fp) . filter visible <$> listDirectory fp+            S.unions <$> mapM searchCabalFiles children+        else do+            if takeExtension fp == ".cabal"+                then return $ S.singleton fp+                else return $ S.empty++visible :: FilePath -> Bool+visible fp = not $ "." `isPrefixOf` fp+ readCabalFile :: FilePath -> IO GenericPackageDescription readCabalFile = readPackageDescription normal +dependentRepos :: Hackage -> GenericPackageDescription -> S.Set GitHubRepo+dependentRepos db desc = S.map fromJust $ S.filter isJust mRepos+    where+        pkgs    = S.delete (packageName desc) (allBuildDepends desc)+        mRepos  = S.map (flip lookupRepo $ db) pkgs+ toPackageName :: Dependency -> PackageName toPackageName (Dependency name _) = name @@ -62,3 +89,11 @@     where         isGitHub = isInfixOf "github.com" loc         ps       = splitOneOf "/." loc++readStackIndex :: IO Hackage+readStackIndex = getStackIndexPath >>= readHackage'++getStackIndexPath :: IO FilePath+getStackIndexPath = do+    stackDir <- getAppUserDataDirectory "stack"+    return $ joinPath [ stackDir, "indices", "Hackage", "00-index.tar" ]
test/Utils/ThankYouStars/PackageSpec.hs view
@@ -1,52 +1,38 @@-{-# LANGUAGE OverloadedStrings  #-} module Utils.ThankYouStars.PackageSpec (spec) where  import Utils.ThankYouStars.GitHub import Utils.ThankYouStars.Package -import qualified Data.Set                as S-import qualified Data.Map                as M-import           Distribution.Hackage.DB ( readHackage )-import           Distribution.Package-import           Distribution.Version+import qualified Data.Set         as S+import           System.Directory ( getCurrentDirectory )+import           System.FilePath  ( joinPath ) import           Test.Hspec  spec :: Spec spec = do-    describe "getThisPackageName" $ do-        it "returns the name of project root directory" $ do-            getThisPackageName `shouldReturn`-                PackageName { unPackageName = "thank-you-stars" }--    describe "allBuildDepends" $ do-        it "returns all packages which are listed in build-depends" $ do-            desc <- readCabalFile "thank-you-stars.cabal"-            allBuildDepends desc `shouldBe` S.fromList (map PackageName [-                  "aeson"-                , "base"-                , "bytestring"-                , "Cabal"-                , "containers"-                , "directory"-                , "filepath"-                , "hackage-db"-                , "hspec"-                , "req"-                , "split"-                , "text"-                , "thank-you-stars"-                ])+    describe "getCabalFiles" $ do+        it "returns the set of all .cabal files in the subdirectories" $ do+            curr <- getCurrentDirectory+            getCabalFiles `shouldReturn` S.fromList [+                  joinPath [curr, "thank-you-stars.cabal"]+                , joinPath [curr, "test", "Fixture", "dummy.cabal"]+                ] -    describe "lookupRepo" $ do-        it "extracts source-repository from the package description" $ do+    -- TODO: too fragile. mock the stack DB+    describe "dependentRepos" $ do+        it "returns the set of all GitHub repos listed in build-depends" $ do+            db   <- readStackIndex             desc <- readCabalFile "thank-you-stars.cabal"-            let ver = Version [] []-                db  = M.singleton "thank-you-stars" (M.singleton ver desc)-            lookupRepo (PackageName { unPackageName = "thank-you-stars" }) db-                `shouldBe` Just GitHubRepo {-                      owner = "y-taka-23"-                    , repo  = "thank-you-stars"-                    }-        it "returns Nothing if the package is not found" $ do-            lookupRepo (PackageName { unPackageName = "hspec" }) M.empty-                `shouldBe` Nothing+            dependentRepos db desc `shouldBe` S.fromList [+                  GitHubRepo "bos" "aeson"+                , GitHubRepo "haskell" "bytestring"+                , GitHubRepo "haskell" "cabal"+                , GitHubRepo "haskell" "containers"+                , GitHubRepo "haskell" "directory"+                , GitHubRepo "haskell" "filepath"+                , GitHubRepo "peti" "hackage-db"+                , GitHubRepo "hspec" "hspec"+                , GitHubRepo "mrkkrp" "req"+                , GitHubRepo "byorgey" "split"+                , GitHubRepo "bos" "text"+                ]
thank-you-stars.cabal view
@@ -1,9 +1,9 @@ name:                thank-you-stars-version:             0.1.0+version:             0.2.0 synopsis:            Give your dependencies stars on GitHub! description:     A tool for starring GitHub repositories. It detects dependent libraries-    which are hosted on GitHub via package.cabal file,+    which are hosted on GitHub via .cabal files,     and stars the repositories all at once. homepage:            https://github.com/y-taka-23/thank-you-stars#readme license:             BSD3@@ -54,7 +54,8 @@   build-depends:       base                      , Cabal                      , containers-                     , hackage-db+                     , directory+                     , filepath                      , hspec                      , thank-you-stars   ghc-options:         -threaded -rtsopts -with-rtsopts=-N