gitignore (empty) → 1.0.0
raw patch · 4 files changed
+145/−0 lines, 4 filesdep +aesondep +basedep +base64-bytestringsetup-changed
Dependencies added: aeson, base, base64-bytestring, bytestring, http-conduit, network, safe, text
Files
- LICENSE +30/−0
- Setup.hs +2/−0
- gitignore.cabal +24/−0
- gitignore.hs +89/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2013, Ricky Elrod++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Ricky Elrod nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ gitignore.cabal view
@@ -0,0 +1,24 @@+-- Initial gitignore.cabal generated by cabal init. For further+-- documentation, see http://haskell.org/cabal/users-guide/++name: gitignore+version: 1.0.0+synopsis: Apply GitHub .gitignore templates to already existing repositories.+description: Apply GitHub .gitignore templates to already existing repositories.+homepage: https://github.com/CodeBlock/gitignore+license: BSD3+license-file: LICENSE+author: Ricky Elrod+maintainer: ricky@elrod.me+copyright: 2013 Ricky Elrod+category: Development+build-type: Simple+cabal-version: >=1.8++source-repository head+ type: git+ location: git://github.com:CodeBlock/gitignore.git++executable gitignore+ main-is: gitignore.hs+ build-depends: aeson ==0.6.*, base >=4.6 && <4.7, base64-bytestring ==1.0.*, bytestring ==0.10.*, http-conduit ==1.9.5.*, network ==2.4.*, safe ==0.3.*, text ==0.11.*
+ gitignore.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE OverloadedStrings #-}++module Main where++import Control.Applicative+import Data.Aeson+import Data.Char (toLower)+import Data.List (dropWhileEnd, find, sort)+import qualified Data.ByteString as B+import qualified Data.ByteString.Base64 as Base64+import qualified Data.ByteString.Char8 as C8+import Network (withSocketsDo)+import Network.HTTP.Conduit hiding (path)+import Safe (headMay)+import System.Environment (getArgs)++data GitIgnoreIndex = GitIgnoreIndex {+ gitIgnores :: [GitIgnore]+ } deriving Show++data GitIgnore = GitIgnore {+ path :: String+ , url :: String+} deriving Show++data GitIgnoreFile = GitIgnoreFile {+ content :: B.ByteString+}++instance FromJSON GitIgnoreIndex where+ parseJSON (Object v) = GitIgnoreIndex <$>+ v .: "tree"++instance FromJSON GitIgnore where+ parseJSON (Object v) = GitIgnore <$>+ v .: "path" <*>+ v .: "url"++instance FromJSON GitIgnoreFile where+ parseJSON (Object v) = GitIgnoreFile <$>+ v .: "content"++-- | Get the current list of gitignore templates from the github/gitignore+-- repository, via the GitHub API.+getIgnoresIndex :: IO [GitIgnore]+getIgnoresIndex = withSocketsDo $ do+ x <- parseUrl "https://api.github.com/repos/github/gitignore/git/trees/master"+ let r = x { requestHeaders = [("User-Agent", "gitignore-hs")] }+ l <- withManager $ httpLbs r+ let decodedBody = decode (responseBody l) :: Maybe GitIgnoreIndex+ case decodedBody of+ Nothing -> error "JSON decode failed"+ Just g -> return $ gitIgnores g++-- | Given a URL obtained from the gitignores index, get the contents of the+-- file, after decoding (base64) its contents.+getIgnoreFile :: String -> IO B.ByteString+getIgnoreFile url = withSocketsDo $ do+ x <- parseUrl url+ let r = x { requestHeaders = [("User-Agent", "gitignore-hs")] }+ l <- withManager $ httpLbs r+ let decodedBody = decode (responseBody l) :: Maybe GitIgnoreFile+ case decodedBody of+ Nothing -> error "JSON decode failed"+ Just g -> return $ Base64.decodeLenient $ content g++main :: IO ()+main = do+ a <- getArgs+ case headMay a of+ Nothing -> do+ putStrLn "Get gitignore files from GitHub's gitignore repository."+ error "Usage: gitignore [<language> | list] > .gitignore"+ Just s -> do+ x <- getIgnoresIndex+ let ignores =+ fmap (\x -> x { Main.path = fmap toLower (init $ Main.path x) }) $+ filter ((/= "") . Main.path) $+ fmap (\x -> x { Main.path = dropWhileEnd (/= '.') (Main.path x) }) x+ case s of+ "list" ->+ mapM_ putStrLn $ sort $ fmap path ignores+ _ -> do+ let selected = find (\y -> fmap toLower (Main.path y) == s) ignores+ case selected of+ Nothing -> error "No such gitignore was found. Use 'list' for all possible gitignores."+ Just f -> do+ decoded <- getIgnoreFile $ url f+ putStr $ C8.unpack decoded