packages feed

github (empty) → 0.1

raw patch · 83 files changed

+2908/−0 lines, 83 filesdep +HTTPdep +aesondep +attoparsecsetup-changed

Dependencies added: HTTP, aeson, attoparsec, base, bytestring, containers, failure, http-enumerator, http-types, network, old-locale, text, time, uri, vector

Files

+ Github/Data.hs view
@@ -0,0 +1,479 @@+{-# LANGUAGE DeriveDataTypeable, OverloadedStrings #-}++-- | This module re-exports the @Github.Data.Definitions@ module, adding+-- instances of @FromJSON@ to it. If you wish to use the data without the+-- instances, use the @Github.Data.Definitions@ module instead.++module Github.Data (module Github.Data.Definitions) where++import Data.Time+import Control.Applicative+import Control.Monad+import qualified Data.Map as Map+import qualified Data.Text as T+import Data.Aeson.Types+import System.Locale (defaultTimeLocale)+import Data.Attoparsec.Number (Number(..))+import qualified Data.Vector as V++import Github.Data.Definitions++instance FromJSON GithubDate where+  parseJSON (String t) =+    case parseTime defaultTimeLocale "%FT%T%Z" (T.unpack t) of+         Just d -> pure $ GithubDate d+         _      -> fail "could not parse Github datetime"+  parseJSON _          = fail "Given something besides a String"++instance FromJSON Commit where+  parseJSON (Object o) =+    Commit <$> o .: "sha"+           <*> o .: "parents"+           <*> o .: "url"+           <*> o .: "commit"+           <*> o .:? "committer"+           <*> o .:? "author"+           <*> o .:< "files"+           <*> o .:? "stats"+  parseJSON _          = fail "Could not build a Commit"++instance FromJSON Tree where+  parseJSON (Object o) =+    Tree <$> o .: "sha"+         <*> o .: "url"+         <*> o .:< "tree"+  parseJSON _          = fail "Could not build a Tree"++instance FromJSON GitTree where+  parseJSON (Object o) =+    GitTree <$> o .: "type"+         <*> o .: "sha"+         <*> o .: "url"+         <*> o .:? "size"+         <*> o .: "path"+         <*> o .: "mode"+  parseJSON _          = fail "Could not build a GitTree"++instance FromJSON GitCommit where+  parseJSON (Object o) =+    GitCommit <$> o .: "message"+              <*> o .: "url"+              <*> o .: "committer"+              <*> o .: "author"+              <*> o .: "tree"+              <*> o .:? "sha"+              <*> o .:< "parents"+  parseJSON _          = fail "Could not build a GitCommit"++instance FromJSON GithubUser where+  parseJSON (Object o) =+    GithubUser <$> o .: "avatar_url"+               <*> o .: "login"+               <*> o .: "url"+               <*> o .: "id"+               <*> o .: "gravatar_id"+  parseJSON v          = fail $ "Could not build a GithubUser out of " ++ (show v)++instance FromJSON GitUser where+  parseJSON (Object o) =+    GitUser <$> o .: "name"+            <*> o .: "email"+            <*> o .: "date"+  parseJSON _          = fail "Could not build a GitUser"++instance FromJSON File where+  parseJSON (Object o) =+    File <$> o .: "blob_url"+         <*> o .: "status"+         <*> o .: "raw_url"+         <*> o .: "additions"+         <*> o .: "sha"+         <*> o .: "changes"+         <*> o .: "patch"+         <*> o .: "filename"+         <*> o .: "deletions"+  parseJSON _          = fail "Could not build a File"++instance FromJSON Stats where+  parseJSON (Object o) =+    Stats <$> o .: "additions"+          <*> o .: "total"+          <*> o .: "deletions"+  parseJSON _          = fail "Could not build a Stats"++instance FromJSON Comment where+  parseJSON (Object o) =+    Comment <$> o .:? "position"+            <*> o .:? "line"+            <*> o .: "body"+            <*> o .: "commit_id"+            <*> o .: "updated_at"+            <*> o .:? "html_url"+            <*> o .: "url"+            <*> o .: "created_at"+            <*> o .: "path"+            <*> o .: "user"+            <*> o .: "id"+  parseJSON _          = fail "Could not build a Comment"++instance FromJSON Diff where+  parseJSON (Object o) =+    Diff <$> o .: "status"+         <*> o .: "behind_by"+         <*> o .: "patch_url"+         <*> o .: "url"+         <*> o .: "base_commit"+         <*> o .:< "commits"+         <*> o .: "total_commits"+         <*> o .: "html_url"+         <*> o .:< "files"+         <*> o .: "ahead_by"+         <*> o .: "diff_url"+         <*> o .: "permalink_url"+  parseJSON _          = fail "Could not build a Diff"++instance FromJSON Gist where+  parseJSON (Object o) =+    Gist <$> o .: "user"+         <*> o .: "git_push_url"+         <*> o .: "url"+         <*> o .:? "description"+         <*> o .: "created_at"+         <*> o .: "public"+         <*> o .: "comments"+         <*> o .: "updated_at"+         <*> o .: "html_url"+         <*> o .: "id"+         <*> o `values` "files"+         <*> o .: "git_push_url"+  parseJSON _          = fail "Could not build a Gist"++instance FromJSON GistFile where+  parseJSON (Object o) =+    GistFile <$> o .: "type"+             <*> o .: "raw_url"+             <*> o .: "size"+             <*> o .:? "language"+             <*> o .: "filename"+             <*> o .:? "content"+  parseJSON _          = fail "Could not build a GistFile"++instance FromJSON GistComment where+  parseJSON (Object o) =+    GistComment <$> o .: "user"+                <*> o .: "url"+                <*> o .: "created_at"+                <*> o .: "body"+                <*> o .: "updated_at"+                <*> o .: "id"+  parseJSON _          = fail "Could not build a GistComment"++instance FromJSON Blob where+  parseJSON (Object o) =+    Blob <$> o .: "url"+         <*> o .: "encoding"+         <*> o .: "content"+         <*> o .: "sha"+         <*> o .: "size"+  parseJSON _          = fail "Could not build a Blob"++instance FromJSON GitReference where+  parseJSON (Object o) =+    GitReference <$> o .: "object"+                 <*> o .: "url"+                 <*> o .: "ref"+  parseJSON _          = fail "Could not build a GitReference"++instance FromJSON GitObject where+  parseJSON (Object o) =+    GitObject <$> o .: "type"+           <*> o .: "sha"+           <*> o .: "url"+  parseJSON _          = fail "Could not build a GitObject"++instance FromJSON Issue where+  parseJSON (Object o) =+    Issue <$> o .:? "closed_at"+          <*> o .: "updated_at"+          <*> o .: "html_url"+          <*> o .:? "closed_by"+          <*> o .: "labels"+          <*> o .: "number"+          <*> o .:? "assignee"+          <*> o .: "user"+          <*> o .: "title"+          <*> o .: "pull_request"+          <*> o .: "url"+          <*> o .: "created_at"+          <*> o .: "body"+          <*> o .: "state"+          <*> o .: "id"+          <*> o .: "comments"+          <*> o .:? "milestone"+  parseJSON _          = fail "Could not build an Issue"++instance FromJSON Milestone where+  parseJSON (Object o) =+    Milestone <$> o .: "creator"+              <*> o .: "due_on"+              <*> o .: "open_issues"+              <*> o .: "number"+              <*> o .: "closed_issues"+              <*> o .: "description"+              <*> o .: "title"+              <*> o .: "url"+              <*> o .: "created_at"+              <*> o .: "state"+  parseJSON _          = fail "Could not build a Milestone"++instance FromJSON IssueLabel where+  parseJSON (Object o) =+    IssueLabel <$> o .: "color"+               <*> o .: "url"+               <*> o .: "name"+  parseJSON _          = fail "Could not build a Milestone"++instance FromJSON PullRequestReference where+  parseJSON (Object o) =+    PullRequestReference <$> o .:? "html_url"+                         <*> o .:? "patch_url"+                         <*> o .:? "diff_url"+  parseJSON _          = fail "Could not build a PullRequest"++instance FromJSON IssueComment where+  parseJSON (Object o) =+    IssueComment <$> o .: "updated_at"+                 <*> o .: "user"+                 <*> o .: "url"+                 <*> o .: "created_at"+                 <*> o .: "body"+                 <*> o .: "id"+  parseJSON _          = fail "Could not build an IssueComment"++instance FromJSON Event where+  parseJSON (Object o) =+    Event <$> o .: "actor"+          <*> o .: "event"+          <*> o .:? "commit_id"+          <*> o .: "url"+          <*> o .: "created_at"+          <*> o .: "id"+          <*> o .:? "issue"+  parseJSON _          = fail "Could not build an Event"++instance FromJSON EventType where+  parseJSON (String "closed") = pure Closed+  parseJSON (String "reopened") = pure Reopened+  parseJSON (String "subscribed") = pure Subscribed+  parseJSON (String "merged") = pure Merged+  parseJSON (String "referenced") = pure Referenced+  parseJSON (String "mentioned") = pure Mentioned+  parseJSON (String "assigned") = pure Assigned+  parseJSON (String "unsubscribed") = pure Unsubscribed+  parseJSON _ = fail "Could not build an EventType"++instance FromJSON SimpleOrganization where+  parseJSON (Object o) =+    SimpleOrganization <$> o .: "url"+                       <*> o .: "avatar_url"+                       <*> o .: "id"+                       <*> o .: "login"+  parseJSON _ = fail "Could not build a SimpleOrganization"++instance FromJSON Organization where+  parseJSON (Object o) =+    Organization <$> o .: "type"+                 <*> o .:? "blog"+                 <*> o .:? "location"+                 <*> o .: "login"+                 <*> o .: "followers"+                 <*> o .:? "company"+                 <*> o .: "avatar_url"+                 <*> o .: "public_gists"+                 <*> o .: "html_url"+                 <*> o .:? "email"+                 <*> o .: "following"+                 <*> o .: "public_repos"+                 <*> o .: "url"+                 <*> o .: "created_at"+                 <*> o .:? "name"+                 <*> o .: "id"+  parseJSON _ = fail "Could not build an Organization"++instance FromJSON PullRequest where+  parseJSON (Object o) =+      PullRequest+        <$> o .:? "closed_at"+        <*> o .: "created_at"+        <*> o .: "user"+        <*> o .: "patch_url"+        <*> o .: "state"+        <*> o .: "number"+        <*> o .: "html_url"+        <*> o .: "updated_at"+        <*> o .: "body"+        <*> o .: "issue_url"+        <*> o .: "diff_url"+        <*> o .: "url"+        <*> o .: "_links"+        <*> o .:? "merged_at"+        <*> o .: "title"+        <*> o .: "id"+  parseJSON _ = fail "Could not build a PullRequest"++instance FromJSON DetailedPullRequest where+  parseJSON (Object o) =+      DetailedPullRequest+        <$> o .:? "closed_at"+        <*> o .: "created_at"+        <*> o .: "user"+        <*> o .: "patch_url"+        <*> o .: "state"+        <*> o .: "number"+        <*> o .: "html_url"+        <*> o .: "updated_at"+        <*> o .: "body"+        <*> o .: "issue_url"+        <*> o .: "diff_url"+        <*> o .: "url"+        <*> o .: "_links"+        <*> o .:? "merged_at"+        <*> o .: "title"+        <*> o .: "id"+        <*> o .:? "merged_by"+        <*> o .: "changed_files"+        <*> o .: "head"+        <*> o .: "comments"+        <*> o .: "deletions"+        <*> o .: "additions"+        <*> o .: "review_comments"+        <*> o .: "base"+        <*> o .: "commits"+        <*> o .: "merged"+        <*> o .: "mergeable"+  parseJSON _ = fail "Could not build a DetailedPullRequest"++instance FromJSON PullRequestLinks where+  parseJSON (Object o) =+    PullRequestLinks <$> o <.:> ["review_comments", "href"]+                     <*> o <.:> ["comments", "href"]+                     <*> o <.:> ["html", "href"]+                     <*> o <.:> ["self", "href"]+  parseJSON _ = fail "Could not build a PullRequestLinks"++instance FromJSON PullRequestCommit where+  parseJSON (Object o) =+    return PullRequestCommit+  parseJSON _ = fail "Could not build a PullRequestCommit"++instance FromJSON Repo where+  parseJSON (Object o) =+    Repo <$> o .: "ssh_url"+         <*> o .: "description"+         <*> o .: "created_at"+         <*> o .: "html_url"+         <*> o .: "svn_url"+         <*> o .: "forks"+         <*> o .:? "homepage"+         <*> o .: "fork"+         <*> o .: "git_url"+         <*> o .: "private"+         <*> o .: "clone_url"+         <*> o .: "size"+         <*> o .: "updated_at"+         <*> o .: "watchers"+         <*> o .: "owner"+         <*> o .: "name"+         <*> o .: "language"+         <*> o .:? "master_branch"+         <*> o .: "pushed_at"+         <*> o .: "id"+         <*> o .: "url"+         <*> o .: "open_issues"+         <*> o .:? "has_wiki"+         <*> o .:? "has_issues"+         <*> o .:? "has_downloads"+  parseJSON _ = fail "Could not build a Repo"++instance FromJSON Contributor where+  parseJSON (Object o)+    | o `at` "type" == (Just "Anonymous") =+      AnonymousContributor <$> o .: "contributions"+                           <*> o .: "name"+    | otherwise =+      KnownContributor <$> o .: "contributions"+                       <*> o .: "avatar_url"+                       <*> o .: "login"+                       <*> o .: "url"+                       <*> o .: "id"+                       <*> o .: "gravatar_id"+  parseJSON _ = fail "Could not build a Contributor"++instance FromJSON Languages where+  parseJSON (Object o) =+    Languages <$>+      mapM (\name -> Language (T.unpack name) <$> o .: name)+           (Map.keys o)+  parseJSON _ = fail "Could not build Languages"++instance FromJSON Tag where+  parseJSON (Object o) =+    Tag <$> o .: "name"+        <*> o .: "zipball_url"+        <*> o .: "tarball_url"+        <*> o .: "commit"+  parseJSON _ = fail "Could not build a Tag"++instance FromJSON Branch where+  parseJSON (Object o) = Branch <$> o .: "name" <*> o .: "commit"+  parseJSON _ = fail "Could not build a Branch"++instance FromJSON BranchCommit where+  parseJSON (Object o) = BranchCommit <$> o .: "sha" <*> o .: "url"+  parseJSON _ = fail "Could not build a BranchCommit"++instance FromJSON DetailedUser where+  parseJSON (Object o) =+    DetailedUser <$> o .: "created_at"+                 <*> o .: "type"+                 <*> o .: "public_gists"+                 <*> o .: "avatar_url"+                 <*> o .: "followers"+                 <*> o .: "following"+                 <*> o .: "hireable"+                 <*> o .: "gravatar_id"+                 <*> o .:? "blog"+                 <*> o .:? "bio"+                 <*> o .: "public_repos"+                 <*> o .:? "name"+                 <*> o .:? "location"+                 <*> o .:? "company"+                 <*> o .: "email"+                 <*> o .: "url"+                 <*> o .: "id"+                 <*> o .: "html_url"+                 <*> o .: "login"+  parseJSON _ = fail "Could not build a DetailedUser"+++-- | A slightly more generic version of Aeson's @(.:?)@, using `mzero' instead+-- of `Nothing'.+(.:<) :: (FromJSON a) => Object -> T.Text -> Parser [a]+obj .:< key = case Map.lookup key obj of+                   Nothing -> pure mzero+                   Just v  -> parseJSON v++-- | Produce all values for the given key.+obj `values` key =+  let (Object children) = Map.findWithDefault (Object Map.empty) key obj in+    parseJSON $ Array $ V.fromList $ Map.elems children++-- | Produce the value for the last key by traversing.+obj <.:> [key] = obj .: key+obj <.:> (key:keys) =+  let (Object nextObj) = Map.findWithDefault (Object Map.empty) key obj in+      nextObj <.:> keys++-- | Produce the value for the given key, maybe.+at :: Object -> T.Text -> Maybe Value+obj `at` key = Map.lookup key obj
+ Github/Data/Definitions.hs view
@@ -0,0 +1,420 @@+{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}++module Github.Data.Definitions where++import Data.Time+import Data.Data+import Network.HTTP.Enumerator (HttpException(..))+import qualified Control.Exception as E++deriving instance Eq Network.HTTP.Enumerator.HttpException++-- | Errors have been tagged according to their source, so you can more easily+-- dispatch and handle them.+data Error =+    HTTPConnectionError E.IOException -- ^ A HTTP error occurred. The actual caught error is included, if available.+  | ParseError String -- ^ An error in the parser itself.+  | JsonError String -- ^ The JSON is malformed or unexpected.+  | UserError String -- ^ Incorrect input.+  deriving (Show, Eq)++-- | A date in the Github format, which is a special case of ISO-8601.+newtype GithubDate = GithubDate { fromGithubDate :: UTCTime }+  deriving (Show, Data, Typeable, Eq, Ord)++data Commit = Commit {+   commitSha       :: String+  ,commitParents   :: [Tree]+  ,commitUrl       :: String+  ,commitGitCommit :: GitCommit+  ,commitCommitter :: Maybe GithubUser+  ,commitAuthor    :: Maybe GithubUser+  ,commitFiles     :: [File]+  ,commitStats     :: Maybe Stats+} deriving (Show, Data, Typeable, Eq, Ord)++data Tree = Tree {+   treeSha :: String+  ,treeUrl :: String+  ,treeGitTrees :: [GitTree]+} deriving (Show, Data, Typeable, Eq, Ord)++data GitTree = GitTree {+  gitTreeType :: String+  ,gitTreeSha :: String+  ,gitTreeUrl :: String+  ,gitTreeSize :: Maybe Int+  ,gitTreePath :: String+  ,gitTreeMode :: String+} deriving (Show, Data, Typeable, Eq, Ord)++data GitCommit = GitCommit {+   gitCommitMessage :: String+  ,gitCommitUrl :: String+  ,gitCommitCommitter :: GitUser+  ,gitCommitAuthor :: GitUser+  ,gitCommitTree :: Tree+  ,gitCommitSha :: Maybe String+  ,gitCommitParents :: [Tree]+} deriving (Show, Data, Typeable, Eq, Ord)++data GithubUser = GithubUser {+   githubUserAvatarUrl :: String+  ,githubUserLogin :: String+  ,githubUserUrl :: String+  ,githubUserId :: Int+  ,githubUserGravatarId :: String+} deriving (Show, Data, Typeable, Eq, Ord)++data GitUser = GitUser {+   gitUserName  :: String+  ,gitUserEmail :: String+  ,gitUserDate  :: GithubDate+} deriving (Show, Data, Typeable, Eq, Ord)++data File = File {+   fileBlobUrl :: String+  ,fileStatus :: String+  ,fileRawUrl :: String+  ,fileAdditions :: Int+  ,fileSha :: String+  ,fileChanges :: Int+  ,filePatch :: String+  ,fileFilename :: String+  ,fileDeletions :: Int+} deriving (Show, Data, Typeable, Eq, Ord)++data Stats = Stats {+   statsAdditions :: Int+  ,statsTotal :: Int+  ,statsDeletions :: Int+} deriving (Show, Data, Typeable, Eq, Ord)++data Comment = Comment {+   commentPosition :: Maybe Int+  ,commentLine :: Maybe Int+  ,commentBody :: String+  ,commentCommitId :: String+  ,commentUpdatedAt :: UTCTime+  ,commentHtmlUrl :: Maybe String+  ,commentUrl :: String+  ,commentCreatedAt :: UTCTime+  ,commentPath :: Maybe String+  ,commentUser :: GithubUser+  ,commentId :: Int+} deriving (Show, Data, Typeable, Eq, Ord)++data Diff = Diff {+   diffStatus :: String+  ,diffBehindBy :: Int+  ,diffPatchUrl :: String+  ,diffUrl :: String+  ,diffBaseCommit :: Commit+  ,diffCommits :: [Commit]+  ,diffTotalCommits :: Int+  ,diffHtmlUrl :: String+  ,diffFiles :: [File]+  ,diffAheadBy :: Int+  ,diffDiffUrl :: String+  ,diffPermalinkUrl :: String+} deriving (Show, Data, Typeable, Eq, Ord)++data Gist = Gist {+   gistUser :: GithubUser+  ,gistGitPushUrl :: String+  ,gistUrl :: String+  ,gistDescription :: Maybe String+  ,gistCreatedAt :: GithubDate+  ,gistPublic :: Bool+  ,gistComments :: Int+  ,gistUpdatedAt :: GithubDate+  ,gistHtmlUrl :: String+  ,gistId :: String+  ,gistFiles :: [GistFile]+  ,gistGitPullUrl :: String+} deriving (Show, Data, Typeable, Eq, Ord)++data GistFile = GistFile {+   gistFileType :: String+  ,gistFileRawUrl :: String+  ,gistFileSize :: Int+  ,gistFileLanguage :: Maybe String+  ,gistFileFilename :: String+  ,gistFileContent :: Maybe String+} deriving (Show, Data, Typeable, Eq, Ord)++data GistComment = GistComment {+   gistCommentUser :: GithubUser+  ,gistCommentUrl :: String+  ,gistCommentCreatedAt :: GithubDate+  ,gistCommentBody :: String+  ,gistCommentUpdatedAt :: GithubDate+  ,gistCommentId :: Int+} deriving (Show, Data, Typeable, Eq, Ord)++data Blob = Blob {+   blobUrl :: String+  ,blobEncoding :: String+  ,blobContent :: String+  ,blobSha :: String+  ,blobSize :: Int+} deriving (Show, Data, Typeable, Eq, Ord)++data GitReference = GitReference {+   gitReferenceObject :: GitObject+  ,gitReferenceUrl :: String+  ,gitReferenceRef :: String+} deriving (Show, Data, Typeable, Eq, Ord)++data GitObject = GitObject {+   gitObjectType :: String+  ,gitObjectSha :: String+  ,gitObjectUrl :: String+} deriving (Show, Data, Typeable, Eq, Ord)++data Issue = Issue {+   issueClosedAt :: Maybe GithubDate+  ,issueUpdatedAt :: GithubDate+  ,issueHtmlUrl :: String+  ,issueClosedBy :: Maybe String+  ,issueLabels :: [IssueLabel]+  ,issueNumber :: Int+  ,issueAssignee :: Maybe GithubUser+  ,issueUser :: GithubUser+  ,issueTitle :: String+  ,issuePullRequest :: PullRequestReference+  ,issueUrl :: String+  ,issueCreatedAt :: GithubDate+  ,issueBody :: String+  ,issueState :: String+  ,issueId :: Int+  ,issueComments :: Int+  ,issueMilestone :: Maybe Milestone+} deriving (Show, Data, Typeable, Eq, Ord)++data Milestone = Milestone {+   milestoneCreator :: GithubUser+  ,milestoneDueOn :: GithubDate+  ,milestoneOpenIssues :: Int+  ,milestoneNumber :: Int+  ,milestoneClosedIssues :: Int+  ,milestoneDescription :: String+  ,milestoneTitle :: String+  ,milestoneUrl :: String+  ,milestoneCreatedAt :: GithubDate+  ,milestoneState :: String+} deriving (Show, Data, Typeable, Eq, Ord)++data IssueLabel = IssueLabel {+   labelColor :: String+  ,labelUrl :: String+  ,labelName :: String+} deriving (Show, Data, Typeable, Eq, Ord)++data PullRequestReference = PullRequestReference {+  pullRequestReferenceHtmlUrl :: Maybe String+  ,pullRequestReferencePatchUrl :: Maybe String+  ,pullRequestReferenceDiffUrl :: Maybe String+} deriving (Show, Data, Typeable, Eq, Ord)++data IssueComment = IssueComment {+   issueCommentUpdatedAt :: GithubDate+  ,issueCommentUser :: GithubUser+  ,issueCommentUrl :: String+  ,issueCommentCreatedAt :: GithubDate+  ,issueCommentBody :: String+  ,issueCommentId :: Int+} deriving (Show, Data, Typeable, Eq, Ord)++-- | Data describing an @Event@.+data EventType =+    Mentioned     -- ^ The actor was @mentioned in an issue body.+  | Subscribed    -- ^ The actor subscribed to receive notifications for an issue.+  | Unsubscribed  -- ^ The issue was unsubscribed from by the actor.+  | Referenced    -- ^ The issue was referenced from a commit message. The commit_id attribute is the commit SHA1 of where that happened.+  | Merged        -- ^ The issue was merged by the actor. The commit_id attribute is the SHA1 of the HEAD commit that was merged.+  | Assigned      -- ^ The issue was assigned to the actor.+  | Closed        -- ^ The issue was closed by the actor. When the commit_id is present, it identifies the commit that closed the issue using “closes / fixes #NN” syntax. +  | Reopened      -- ^ The issue was reopened by the actor.+  deriving (Show, Data, Typeable, Eq, Ord)++data Event = Event {+   eventActor :: GithubUser+  ,eventType :: EventType+  ,eventCommitId :: Maybe String+  ,eventUrl :: String+  ,eventCreatedAt :: GithubDate+  ,eventId :: Int+  ,eventIssue :: Maybe Issue+} deriving (Show, Data, Typeable, Eq, Ord)++data SimpleOrganization = SimpleOrganization {+   simpleOrganizationUrl :: String+  ,simpleOrganizationAvatarUrl :: String+  ,simpleOrganizationId :: Int+  ,simpleOrganizationLogin :: String+} deriving (Show, Data, Typeable, Eq, Ord)++data Organization = Organization {+   organizationType :: String+  ,organizationBlog :: Maybe String+  ,organizationLocation :: Maybe String+  ,organizationLogin :: String+  ,organizationFollowers :: Int+  ,organizationCompany :: Maybe String+  ,organizationAvatarUrl :: String+  ,organizationPublicGists :: Int+  ,organizationHtmlUrl :: String+  ,organizationEmail :: Maybe String+  ,organizationFollowing :: Int+  ,organizationPublicRepos :: Int+  ,organizationUrl :: String+  ,organizationCreatedAt :: GithubDate+  ,organizationName :: Maybe String+  ,organizationId :: Int+} deriving (Show, Data, Typeable, Eq, Ord)++data PullRequest = PullRequest {+   pullRequestClosedAt :: Maybe GithubDate+  ,pullRequestCreatedAt :: GithubDate+  ,pullRequestUser :: GithubUser+  ,pullRequestPatchUrl :: String+  ,pullRequestState :: String+  ,pullRequestNumber :: Int+  ,pullRequestHtmlUrl :: String+  ,pullRequestUpdatedAt :: GithubDate+  ,pullRequestBody :: String+  ,pullRequestIssueUrl :: String+  ,pullRequestDiffUrl :: String+  ,pullRequestUrl :: String+  ,pullRequestLinks :: PullRequestLinks+  ,pullRequestMergedAt :: Maybe GithubDate+  ,pullRequestTitle :: String+  ,pullRequestId :: Int+} deriving (Show, Data, Typeable, Eq, Ord)++data DetailedPullRequest = DetailedPullRequest {+  -- this is a duplication of a PullRequest+   detailedPullRequestClosedAt :: Maybe GithubDate+  ,detailedPullRequestCreatedAt :: GithubDate+  ,detailedPullRequestUser :: GithubUser+  ,detailedPullRequestPatchUrl :: String+  ,detailedPullRequestState :: String+  ,detailedPullRequestNumber :: Int+  ,detailedPullRequestHtmlUrl :: String+  ,detailedPullRequestUpdatedAt :: GithubDate+  ,detailedPullRequestBody :: String+  ,detailedPullRequestIssueUrl :: String+  ,detailedPullRequestDiffUrl :: String+  ,detailedPullRequestUrl :: String+  ,detailedPullRequestLinks :: PullRequestLinks+  ,detailedPullRequestMergedAt :: Maybe GithubDate+  ,detailedPullRequestTitle :: String+  ,detailedPullRequestId :: Int++  ,detailedPullRequestMergedBy :: Maybe GithubUser+  ,detailedPullRequestChangedFiles :: Int+  ,detailedPullRequestHead :: PullRequestCommit+  ,detailedPullRequestComments :: Int+  ,detailedPullRequestDeletions :: Int+  ,detailedPullRequestAdditions :: Int+  ,detailedPullRequestReviewComments :: Int+  ,detailedPullRequestBase :: PullRequestCommit+  ,detailedPullRequestCommits :: Int+  ,detailedPullRequestMerged :: Bool+  ,detailedPullRequestMergeable :: Bool+} deriving (Show, Data, Typeable, Eq, Ord)++data PullRequestLinks = PullRequestLinks {+   pullRequestLinksReviewComments :: String+  ,pullRequestLinksComments :: String+  ,pullRequestLinksHtml :: String+  ,pullRequestLinksSelf :: String+} deriving (Show, Data, Typeable, Eq, Ord)++data PullRequestCommit = PullRequestCommit {+} deriving (Show, Data, Typeable, Eq, Ord)++data Repo = Repo {+   repoSshUrl :: String+  ,repoDescription :: String+  ,repoCreatedAt :: GithubDate+  ,repoHtmlUrl :: String+  ,repoSvnUrl :: String+  ,repoForks :: Int+  ,repoHomepage :: Maybe String+  ,repoFork :: Bool+  ,repoGitUrl :: String+  ,repoPrivate :: Bool+  ,repoCloneUrl :: String+  ,repoSize :: Int+  ,repoUpdatedAt :: GithubDate+  ,repoWatchers :: Int+  ,repoOwner :: GithubUser+  ,repoName :: String+  ,repoLanguage :: String+  ,repoMasterBranch :: Maybe String+  ,repoPushedAt :: GithubDate+  ,repoId :: Int+  ,repoUrl :: String+  ,repoOpenIssues :: Int+  ,repoHasWiki :: Maybe Bool+  ,repoHasIssues :: Maybe Bool+  ,repoHasDownloads :: Maybe Bool+} deriving (Show, Data, Typeable, Eq, Ord)++data Contributor+  -- | An existing Github user, with their number of contributions, avatar+  -- URL, login, URL, ID, and Gravatar ID.+  = KnownContributor Int String String String Int String+  -- | An unknown Github user with their number of contributions and recorded name.+  | AnonymousContributor Int String+ deriving (Show, Data, Typeable, Eq, Ord)++-- | This is only used for the FromJSON instance.+data Languages = Languages { getLanguages :: [Language] }+  deriving (Show, Data, Typeable, Eq, Ord)++-- | A programming language with the name and number of characters written in+-- it.+data Language = Language String Int+ deriving (Show, Data, Typeable, Eq, Ord)++data Tag = Tag {+   tagName :: String+  ,tagZipballUrl :: String+  ,tagTarballUrl :: String+  ,tagCommit :: BranchCommit+} deriving (Show, Data, Typeable, Eq, Ord)++data Branch = Branch {+   branchName :: String+  ,branchCommit :: BranchCommit+} deriving (Show, Data, Typeable, Eq, Ord)++data BranchCommit = BranchCommit {+   branchCommitSha :: String+  ,branchCommitUrl :: String+} deriving (Show, Data, Typeable, Eq, Ord)++data DetailedUser = DetailedUser {+   detailedUserCreatedAt :: GithubDate+  ,detailedUserType :: String+  ,detailedUserPublicGists :: Int+  ,detailedUserAvatarUrl :: String+  ,detailedUserFollowers :: Int+  ,detailedUserFollowing :: Int+  ,detailedUserHireable :: Bool+  ,detailedUserGravatarId :: String+  ,detailedUserBlog :: Maybe String+  ,detailedUserBio :: Maybe String+  ,detailedUserPublicRepos :: Int+  ,detailedUserName :: Maybe String+  ,detailedUserLocation :: Maybe String+  ,detailedUserCompany :: Maybe String+  ,detailedUserEmail :: String+  ,detailedUserUrl :: String+  ,detailedUserId :: Int+  ,detailedUserHtmlUrl :: String+  ,detailedUserLogin :: String+} deriving (Show, Data, Typeable, Eq, Ord)
+ Github/Gists.hs view
@@ -0,0 +1,21 @@+-- | The gists API as described at <http://developer.github.com/v3/gists/>.+module Github.Gists (+ gists+,gist+,module Github.Data+) where++import Github.Data+import Github.Private++-- | The list of all public gists created by the user.+--+-- > gists "mike-burns"+gists :: String -> IO (Either Error [Gist])+gists userName = githubGet ["users", userName, "gists"]++-- | A specific gist, given its id.+--+-- > gist "225074"+gist :: String -> IO (Either Error Gist)+gist gistId = githubGet ["gists", gistId]
+ Github/Gists/Comments.hs view
@@ -0,0 +1,22 @@+-- | The loving comments people have left on Gists, described on+-- <http://developer.github.com/v3/gists/comments/>.+module Github.Gists.Comments (+ commentsOn+,comment+,module Github.Data+) where++import Github.Data+import Github.Private++-- | All the comments on a Gist, given the Gist ID.+--+-- > commentsOn "1174060"+commentsOn :: String -> IO (Either Error [GistComment])+commentsOn gistId = githubGet ["gists", gistId, "comments"]++-- | A specific comment, by the comment ID.+--+-- > comment "62449"+comment :: String -> IO (Either Error GistComment)+comment commentId = githubGet ["gists", "comments", commentId]
+ Github/GitData/Blobs.hs view
@@ -0,0 +1,16 @@+-- | The API for dealing with git blobs from Github repos, as described in+-- <http://developer.github.com/v3/git/blobs/>.+module Github.GitData.Blobs (+ blob+,module Github.Data+) where++import Github.Data+import Github.Private++-- | Get a blob by SHA1.+--+-- > blob "thoughtbot" "paperclip" "bc5c51d1ece1ee45f94b056a0f5a1674d7e8cba9"+blob :: String -> String -> String -> IO (Either Error Blob)+blob user repoName sha =+  githubGet ["repos", user, repoName, "git", "blobs", sha]
+ Github/GitData/Commits.hs view
@@ -0,0 +1,16 @@+-- | The API for underlying git commits of a Github repo, as described on+-- <http://developer.github.com/v3/git/commits/>.+module Github.GitData.Commits (+ commit+,module Github.Data+) where++import Github.Data+import Github.Private++-- | A single commit, by SHA1.+--+-- > commit "thoughtbot" "paperclip" "bc5c51d1ece1ee45f94b056a0f5a1674d7e8cba9"+commit :: String -> String -> String -> IO (Either Error GitCommit)+commit user repoName sha =+  githubGet ["repos", user, repoName, "git", "commits", sha]
+ Github/GitData/References.hs view
@@ -0,0 +1,33 @@+-- | The underlying git references on a Github repo, exposed for the world to+-- see. The git internals documentation will also prove handy for understanding+-- these. API documentation at <http://developer.github.com/v3/git/refs/>.+module Github.GitData.References (+ reference+,references+,namespacedReferences+,module Github.Data+) where++import Github.Data+import Github.Private++-- | A single reference by the ref name.+--+-- > reference "mike-burns" "github" "heads/master"+reference :: String -> String -> String -> IO (Either Error GitReference)+reference user repoName ref =+  githubGet ["repos", user, repoName, "git", "refs", ref]++-- | The history of references for a repo.+--+-- > references "mike-burns" "github"+references :: String -> String -> IO (Either Error [GitReference])+references user repoName =+  githubGet ["repos", user, repoName, "git", "refs"]++-- | Limited references by a namespace.+--+-- > namespacedReferences "thoughtbot" "paperclip" "tags"+namespacedReferences :: String -> String -> String -> IO (Either Error [GitReference])+namespacedReferences user repoName namespace =+  githubGet ["repos", user, repoName, "git", "refs", namespace]
+ Github/GitData/Trees.hs view
@@ -0,0 +1,25 @@+-- | The underlying tree of SHA1s and files that make up a git repo. The API is+-- described on <http://developer.github.com/v3/git/trees/>.+module Github.GitData.Trees (+ tree+,nestedTree+,module Github.Data+) where++import Github.Data+import Github.Private++-- | A tree for a SHA1.+--+-- > tree "thoughtbot" "paperclip" "fe114451f7d066d367a1646ca7ac10e689b46844"+tree :: String -> String -> String -> IO (Either Error Tree)+tree user repoName sha =+  githubGet ["repos", user, repoName, "git", "trees", sha]++-- | A recursively-nested tree for a SHA1.+--+-- > nestedTree "thoughtbot" "paperclip" "fe114451f7d066d367a1646ca7ac10e689b46844"+nestedTree :: String -> String -> String -> IO (Either Error Tree)+nestedTree user repoName sha =+  githubGetWithQueryString ["repos", user, repoName, "git", "trees", sha]+                           "recursive=1"
+ Github/Issues.hs view
@@ -0,0 +1,66 @@+-- | The issues API as described on <http://developer.github.com/v3/issues/>.+module Github.Issues (+ issue+,issuesForRepo+,IssueLimitation(..)+,module Github.Data+) where++import Github.Data+import Github.Private+import Data.List (intercalate)+import Data.Time.Format (formatTime)+import System.Locale (defaultTimeLocale)+import Data.Time.Clock (UTCTime(..))++-- | A data structure for describing how to filter issues. This is used by+-- @issuesForRepo@.+data IssueLimitation =+      AnyMilestone -- ^ Issues appearing in any milestone. [default]+    | NoMilestone -- ^ Issues without a milestone.+    | MilestoneId Int -- ^ Only issues that are in the milestone with the given id.+    | Open -- ^ Only open issues. [default]+    | OnlyClosed -- ^ Only closed issues.+    | Unassigned -- ^ Issues to which no one has been assigned ownership.+    | AnyAssignment -- ^ All issues regardless of assignment. [default]+    | AssignedTo String -- ^ Only issues assigned to the user with the given login.+    | Mentions String -- ^ Issues which mention the given string, taken to be a user's login.+    | Labels [String] -- ^ A list of labels to filter by.+    | Ascending -- ^ Sort ascending.+    | Descending -- ^ Sort descending. [default]+    | Since UTCTime -- ^ Only issues created since the specified date and time.++-- | Details on a specific issue, given the repo owner and name, and the issue+-- number.+--+-- > issue "thoughtbot" "paperclip" "462"+issue :: String -> String -> Int -> IO (Either Error Issue)+issue user repoName issueNumber =+  githubGet ["repos", user, repoName, "issues", show issueNumber]++-- | All issues for a repo (given the repo owner and name), with optional+-- restrictions as described in the @IssueLimitation@ data type.+--+-- > issuesForRepo "thoughtbot" "paperclip" [NoMilestone, OnlyClosed, Mentions "jyurek", Ascending]+issuesForRepo :: String -> String -> [IssueLimitation] -> IO (Either Error [Issue])+issuesForRepo user repoName issueLimitations =+  githubGetWithQueryString+    ["repos", user, repoName, "issues"]+    (queryStringFromLimitations issueLimitations)+  where+    queryStringFromLimitations = intercalate "&" . map convert++    convert AnyMilestone     = "milestone=*"+    convert NoMilestone      = "milestone=none"+    convert (MilestoneId n)  = "milestone=" ++ show n+    convert Open             = "state=open"+    convert OnlyClosed       = "state=closed"+    convert Unassigned       = "assignee=none"+    convert AnyAssignment    = "assignee=*"+    convert (AssignedTo u)   = "assignee=" ++ u+    convert (Mentions u)     = "mentioned=" ++ u+    convert (Labels l)       = "labels=" ++ intercalate "," l+    convert Ascending        = "direction=asc"+    convert Descending       = "direction=desc"+    convert (Since t)        =+      "since=" ++ formatTime defaultTimeLocale "%FT%TZ" t
+ Github/Issues/Comments.hs view
@@ -0,0 +1,24 @@+-- | The Github issue comments API from+-- <http://developer.github.com/v3/issues/comments/>.+module Github.Issues.Comments (+ comment+,comments+,module Github.Data+) where++import Github.Data+import Github.Private++-- | A specific comment, by ID.+--+-- > comment "thoughtbot" "paperclip" 1468184+comment :: String -> String -> Int -> IO (Either Error IssueComment)+comment user repoName commentId =+  githubGet ["repos", user, repoName, "issues", "comments", show commentId]++-- | All comments on an issue, by the issue's number.+--+-- > comments "thoughtbot" "paperclip" 635+comments :: String -> String -> Int -> IO (Either Error [IssueComment])+comments user repoName issueNumber =+  githubGet ["repos", user, repoName, "issues", show issueNumber, "comments"]
+ Github/Issues/Events.hs view
@@ -0,0 +1,32 @@+-- | The Github issue events API, which is described on+-- <http://developer.github.com/v3/issues/events/>+module Github.Issues.Events (+ eventsForIssue+,eventsForRepo+,event+,module Github.Data+) where++import Github.Data+import Github.Private++-- | All events that have happened on an issue.+--+-- > eventsForIssue "thoughtbot" "paperclip" 49+eventsForIssue :: String -> String -> Int -> IO (Either Error [Event])+eventsForIssue user repoName issueNumber =+  githubGet ["repos", user, repoName, "issues", show issueNumber, "events"]++-- | All the events for all issues in a repo.+--+-- > eventsForRepo "thoughtbot" "paperclip"+eventsForRepo :: String -> String -> IO (Either Error [Event])+eventsForRepo user repoName =+  githubGet ["repos", user, repoName, "issues", "events"]++-- | Details on a specific event, by the event's ID.+--+-- > event "thoughtbot" "paperclip" 5335772+event :: String -> String -> Int -> IO (Either Error Event)+event user repoName eventId =+  githubGet ["repos", user, repoName, "issues", "events", show eventId]
+ Github/Issues/Labels.hs view
@@ -0,0 +1,39 @@+-- | The API for dealing with labels on Github issues, as described on+-- <http://developer.github.com/v3/issues/labels/>.+module Github.Issues.Labels (+ label+,labelsOnRepo+,labelsOnIssue+,labelsOnMilestone+,module Github.Data+) where++import Github.Data+import Github.Private++-- | All the labels available to use on any issue in the repo.+--+-- > labelsOnRepo "thoughtbot" "paperclip"+labelsOnRepo :: String -> String -> IO (Either Error [IssueLabel])+labelsOnRepo user repoName = githubGet ["repos", user, repoName, "labels"]++-- | The labels on an issue in a repo.+--+-- > labelsOnIssue "thoughtbot" "paperclip" 585+labelsOnIssue :: String -> String -> Int ->  IO (Either Error [IssueLabel])+labelsOnIssue user repoName issueId =+  githubGet ["repos", user, repoName, "issues", show issueId, "labels"]++-- | All the labels on a repo's milestone, given the milestone ID.+--+-- > labelsOnMilestone "thoughtbot" "paperclip" 2+labelsOnMilestone :: String -> String -> Int ->  IO (Either Error [IssueLabel])+labelsOnMilestone user repoName milestoneId =+  githubGet ["repos", user, repoName, "milestones", show milestoneId, "labels"]++-- | A label, by name.+--+-- > Github.label "thoughtbot" "paperclip" "bug"+label :: String -> String -> String -> IO (Either Error IssueLabel)+label user repoName labelName =+  githubGet ["repos", user, repoName, "labels", labelName]
+ Github/Issues/Milestones.hs view
@@ -0,0 +1,23 @@+-- | The milestones API as described on+-- <http://developer.github.com/v3/issues/milestones/>.+module Github.Issues.Milestones (+ milestones+,milestone+,module Github.Data+) where++import Github.Data+import Github.Private++-- | All milestones in the repo.+--+-- > milestones "thoughtbot" "paperclip"+milestones :: String -> String -> IO (Either Error [Milestone])+milestones user repoName = githubGet ["repos", user, repoName, "milestones"]++-- | Details on a specific milestone, given it's milestone number.+--+-- > milestone "thoughtbot" "paperclip" 2+milestone :: String -> String -> Int -> IO (Either Error Milestone)+milestone user repoName milestoneNumber =+  githubGet ["repos", user, repoName, "milestones", show milestoneNumber]
+ Github/Organizations.hs view
@@ -0,0 +1,21 @@+-- | The orgs API as described on <http://developer.github.com/v3/orgs/>.+module Github.Organizations (+ publicOrganizationsFor+,publicOrganization+,module Github.Data+) where++import Github.Data+import Github.Private++-- | The public organizations for a user, given the user's login.+--+-- > publicOrganizationsFor "mike-burns"+publicOrganizationsFor :: String -> IO (Either Error [SimpleOrganization])+publicOrganizationsFor userName = githubGet ["users", userName, "orgs"]++-- | Details on a public organization. Takes the organization's login.+--+-- > publicOrganization "thoughtbot"+publicOrganization :: String -> IO (Either Error Organization)+publicOrganization organizationName = githubGet ["orgs", organizationName]
+ Github/Organizations/Members.hs view
@@ -0,0 +1,15 @@+-- | The organization members API as described on+-- <http://developer.github.com/v3/orgs/members/>.+module Github.Organizations.Members (+ membersOf+,module Github.Data+) where++import Github.Data+import Github.Private++-- | All the users who are members of the specified organization.+--+-- > membersOf "thoughtbot"+membersOf :: String -> IO (Either Error [GithubUser])+membersOf organization = githubGet ["orgs", organization, "members"]
+ Github/Private.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE OverloadedStrings, StandaloneDeriving #-}+module Github.Private where++import Github.Data+import Data.Aeson+import Data.Attoparsec+import Control.Applicative+import Data.List+import qualified Data.ByteString.Char8 as BS+import qualified Data.ByteString.Lazy.Char8 as LBS+import qualified Network.HTTP.Types as Types+import Network.HTTP.Enumerator+import Text.URI+import Control.Failure hiding (Error(..))+import qualified Control.Exception as E+import Data.Maybe (fromMaybe)++githubGet :: (FromJSON b, Show b) => [String] -> IO (Either Error b)+githubGet paths =+  githubAPI (BS.pack "GET")+            (buildUrl paths)+            (Nothing :: Maybe Value)++githubGetWithQueryString :: (FromJSON b, Show b) => [String] -> String -> IO (Either Error b)+githubGetWithQueryString paths queryString =+  githubAPI (BS.pack "GET")+            (buildUrl paths ++ "?" ++ queryString)+            (Nothing :: Maybe Value)++buildUrl :: [String] -> String+buildUrl paths = "https://api.github.com/" ++ intercalate "/" paths++githubAPI :: (ToJSON a, Show a, FromJSON b, Show b) => BS.ByteString -> String -> Maybe a -> IO (Either Error b)+githubAPI method url body = do+  result <- doHttps method url (Just encodedBody)+  return $ either (Left . HTTPConnectionError)+                  (parseJson . BS.pack . LBS.unpack . responseBody)+                  result+  where encodedBody = RequestBodyLBS $ encode $ toJSON body++parseJson :: (FromJSON b, Show b) => BS.ByteString -> Either Error b+parseJson jsonString =+  let parsed = parse (fromJSON <$> json) jsonString in+  case parsed of+       Data.Attoparsec.Done _ jsonResult -> do+         case jsonResult of+              (Success s) -> Right s+              (Error e) -> Left $ JsonError $ e ++ " on the JSON: " ++ BS.unpack jsonString+       (Fail _ _ e) -> Left $ ParseError e++doHttps :: BS.ByteString -> String -> Maybe (RequestBody IO) -> IO (Either E.IOException Response)+doHttps method url body = do+  let (Just uri) = parseURI url+      (Just host) = uriRegName uri+      requestBody = fromMaybe (RequestBodyBS $ BS.pack "") body+      queryString = Types.parseQuery $ BS.pack $ fromMaybe "" $ uriQuery uri+      request = def { method = method+                    , secure = True+                    , host = BS.pack host+                    , port = 443+                    , path = BS.pack $ uriPath uri+                    , requestBody = requestBody+                    , queryString = queryString+                    }++  (getResponse request >>= return . Right) `catch` (return . Left)+  where+    getResponse request = withManager $ \manager -> httpLbs request manager
+ Github/PullRequests.hs view
@@ -0,0 +1,43 @@+-- | The pull requests API as documented at+-- <http://developer.github.com/v3/pulls/>.+module Github.PullRequests (+ pullRequestsFor+,pullRequest+,pullRequestCommits+,pullRequestFiles+,module Github.Data+) where++import Github.Data+import Github.Private++-- | All pull requests for the repo, by owner and repo name.+--+-- > pullRequestsFor "rails" "rails"+pullRequestsFor :: String -> String -> IO (Either Error [PullRequest])+pullRequestsFor userName repoName =+  githubGet ["repos", userName, repoName, "pulls"]++-- | A detailed pull request, which has much more information. This takes the+-- repo owner and name along with the number assigned to the pull request.+--+-- > pullRequest "thoughtbot" "paperclip" 562+pullRequest :: String -> String -> Int -> IO (Either Error DetailedPullRequest)+pullRequest userName repoName number =+  githubGet ["repos", userName, repoName, "pulls", show number]++-- | All the commits on a pull request, given the repo owner, repo name, and+-- the number of the pull request.+--+-- > pullRequestCommits "thoughtbot" "paperclip" 688+pullRequestCommits :: String -> String -> Int -> IO (Either Error [Commit])+pullRequestCommits userName repoName number =+  githubGet ["repos", userName, repoName, "pulls", show number, "commits"]++-- | The individual files that a pull request patches. Takes the repo owner and+-- name, plus the number assigned to the pull request.+--+-- > pullRequestFiles "thoughtbot" "paperclip" 688+pullRequestFiles :: String -> String -> Int -> IO (Either Error [File])+pullRequestFiles userName repoName number =+  githubGet ["repos", userName, repoName, "pulls", show number, "files"]
+ Github/Repos.hs view
@@ -0,0 +1,96 @@+-- | The Github Repos API, as documented at+-- <http://developer.github.com/v3/repos/>+module Github.Repos (+ userRepos+,organizationRepos+,userRepo+,contributors+,contributorsWithAnonymous+,languagesFor+,tagsFor+,branchesFor+,module Github.Data+,RepoPublicity(..)+) where++import Github.Data+import Github.Private++-- | Filter the list of the user's repos using any of these constructors.+data RepoPublicity =+    All     -- ^ All repos accessible to the user.+  | Owner   -- ^ Only repos owned by the user.+  | Public  -- ^ Only public repos.+  | Private -- ^ Only private repos.+  | Member  -- ^ Only repos to which the user is a member but not an owner.+ deriving (Show, Eq)++-- | The repos for a user, by their login. Can be restricted to just repos they+-- own, are a member of, or publicize. Private repos are currently not+-- supported.+--+-- > userRepos "mike-burns" All+userRepos :: String -> RepoPublicity -> IO (Either Error [Repo])+userRepos userName All =+  githubGetWithQueryString ["users", userName, "repos"] "type=all"+userRepos userName Owner =+  githubGetWithQueryString ["users", userName, "repos"] "type=owner"+userRepos userName Member =+  githubGetWithQueryString ["users", userName, "repos"] "type=member"+userRepos userName Public =+  githubGetWithQueryString ["users", userName, "repos"] "type=public"+userRepos userName Private =+  return $ Left $ UserError "Cannot access private repos using userRepos"++-- | The repos for an organization, by the organization name.+--+-- > organizationRepos "thoughtbot"+organizationRepos :: String -> IO (Either Error [Repo])+organizationRepos orgName = githubGet ["orgs", orgName, "repos"]++-- | Details on a specific repo, given the owner and repo name.+--+-- > userRepo "mike-burns" "github"+userRepo :: String -> String -> IO (Either Error Repo)+userRepo userName repoName = githubGet ["repos", userName, repoName]++-- | The contributors to a repo, given the owner and repo name.+--+-- > contributors "thoughtbot" "paperclip"+contributors :: String -> String -> IO (Either Error [Contributor])+contributors userName repoName =+  githubGet ["repos", userName, repoName, "contributors"]++-- | The contributors to a repo, including anonymous contributors (such as+-- deleted users or git commits with unknown email addresses), given the owner+-- and repo name.+--+-- > contributorsWithAnonymous "thoughtbot" "paperclip"+contributorsWithAnonymous :: String -> String -> IO (Either Error [Contributor])+contributorsWithAnonymous userName repoName =+  githubGetWithQueryString+    ["repos", userName, repoName, "contributors"]+    "anon=true"++-- | The programming languages used in a repo along with the number of+-- characters written in that language. Takes the repo owner and name.+--+-- > languagesFor "mike-burns" "ohlaunch"+languagesFor :: String -> String -> IO (Either Error [Language])+languagesFor userName repoName = do+  result <- githubGet ["repos", userName, repoName, "languages"]+  return $ either Left (Right . getLanguages) result++-- | The git tags on a repo, given the repo owner and name.+--+-- > tagsFor "thoughtbot" "paperclip"+tagsFor :: String -> String -> IO (Either Error [Tag])+tagsFor userName repoName =+  githubGet ["repos", userName, repoName, "tags"]++-- | The git branches on a repo, given the repo owner and name.+--+-- > branchesFor "thoughtbot" "paperclip"+branchesFor :: String -> String -> IO (Either Error [Branch])+branchesFor userName repoName =+  githubGet ["repos", userName, repoName, "branches"]
+ Github/Repos/Collaborators.hs view
@@ -0,0 +1,34 @@+-- | The repo collaborators API as described on+-- <http://developer.github.com/v3/repos/collaborators/>.+module Github.Repos.Collaborators (+ collaboratorsOn+,isCollaboratorOn+,module Github.Data+) where++import Github.Data+import Github.Private++import Data.ByteString.Char8 (pack)+import Network.HTTP.Enumerator (statusCode)++-- | All the users who have collaborated on a repo.+--+-- > collaboratorsOn "thoughtbot" "paperclip"+collaboratorsOn :: String -> String -> IO (Either Error [GithubUser])+collaboratorsOn userName repoName =+  githubGet ["repos", userName, repoName, "collaborators"]++-- | Whether the user is collaborating on a repo. Takes the user in question,+-- the user who owns the repo, and the repo name.+--+-- > isCollaboratorOn "mike-burns" "thoughtbot" "paperclip"+-- > isCollaboratorOn "johnson" "thoughtbot" "paperclip"+isCollaboratorOn :: String -> String -> String -> IO (Either Error Bool)+isCollaboratorOn userName repoOwnerName repoName = do+  result <- doHttps (pack "GET")+                    (buildUrl ["repos", repoOwnerName, repoName, "collaborators", userName])+                    Nothing+  return $ either (Left . HTTPConnectionError)+                  (Right . (204 ==) . statusCode)+                  result
+ Github/Repos/Commits.hs view
@@ -0,0 +1,53 @@+-- | The repo commits API as described on+-- <http://developer.github.com/v3/repos/commits/>.+module Github.Repos.Commits (+ commitsFor+,commit+,commentsFor+,commitCommentsFor+,commitCommentFor+,diff+,module Github.Data+) where++import Github.Data+import Github.Private++-- | The commit history for a repo.+--+-- > commitsFor "mike-burns" "github"+commitsFor :: String -> String -> IO (Either Error [Commit])+commitsFor user repo = githubGet ["repos", user, repo, "commits"]++-- | Details on a specific SHA1 for a repo.+--+-- > commit "mike-burns" "github" "9d1a9a361266c3c890b1108ad2fdf52f824b1b81"+commit :: String -> String -> String -> IO (Either Error Commit)+commit user repo sha1 = githubGet ["repos", user, repo, "commits", sha1]++-- | All the comments on a Github repo.+--+-- > commentsFor "thoughtbot" "paperclip"+commentsFor :: String -> String -> IO (Either Error [Comment])+commentsFor user repo = githubGet ["repos", user, repo, "comments"]++-- | Just the comments on a specific SHA for a given Github repo.+--+-- > commitCommentsFor "thoughtbot" "paperclip" "41f685f6e01396936bb8cd98e7cca517e2c7d96b"+commitCommentsFor :: String -> String -> String -> IO (Either Error [Comment])+commitCommentsFor user repo sha1 =+  githubGet ["repos", user, repo, "commits", sha1, "comments"]++-- | A comment, by its ID, relative to the Github repo.+--+-- > commitCommentFor "thoughtbot" "paperclip" "669575"+commitCommentFor :: String -> String -> String -> IO (Either Error Comment)+commitCommentFor user repo commentId =+  githubGet ["repos", user, repo, "comments", commentId]++-- | The diff between two treeishes on a repo.+--+-- > diff "thoughtbot" "paperclip" "41f685f6e01396936bb8cd98e7cca517e2c7d96b" "HEAD"+diff :: String -> String -> String -> String -> IO (Either Error Diff)+diff user repo base head =+  githubGet ["repos", user, repo, "compare", base ++ "..." ++ head]
+ Github/Repos/Forks.hs view
@@ -0,0 +1,16 @@+-- | Hot forking action, as described at+-- <http://developer.github.com/v3/repos/forks/>.+module Github.Repos.Forks (+ forksFor+,module Github.Data+) where++import Github.Data+import Github.Private++-- | All the repos that are forked off the given repo.+--+-- > forksFor "thoughtbot" "paperclip"+forksFor :: String -> String -> IO (Either Error [Repo])+forksFor userName repoName =+  githubGet ["repos", userName, repoName, "forks"]
+ Github/Repos/Watching.hs view
@@ -0,0 +1,23 @@+-- | The repo watching API as described on+-- <http://developer.github.com/v3/repos/watching/>.+module Github.Repos.Watching (+ watchersFor+,reposWatchedBy+,module Github.Data+) where++import Github.Data+import Github.Private++-- | The list of users that are watching the specified Github repo.+--+-- > watchersFor "thoughtbot" "paperclip"+watchersFor :: String -> String -> IO (Either Error [GithubUser])+watchersFor userName repoName =+  githubGet ["repos", userName, repoName, "watchers"]++-- | All the public repos watched by the specified user.+--+-- > reposWatchedBy "croaky"+reposWatchedBy :: String -> IO (Either Error [Repo])+reposWatchedBy userName = githubGet ["users", userName, "watched"]
+ Github/Users.hs view
@@ -0,0 +1,15 @@+-- | The Github Users API, as described at+-- <http://developer.github.com/v3/users/>.+module Github.Users (+ userInfoFor+,module Github.Data+) where++import Github.Data+import Github.Private++-- | The information for a single user, by login name.+--+-- > userInfoFor "mike-burns"+userInfoFor :: String -> IO (Either Error DetailedUser)+userInfoFor userName = githubGet ["users", userName]
+ Github/Users/Followers.hs view
@@ -0,0 +1,22 @@+-- | The user followers API as described on+-- <http://developer.github.com/v3/users/followers/>.+module Github.Users.Followers (+ usersFollowing+,usersFollowedBy+,module Github.Data+) where++import Github.Data+import Github.Private++-- | All the users following the given user.+--+-- > usersFollowing "mike-burns"+usersFollowing :: String -> IO (Either Error [GithubUser])+usersFollowing userName = githubGet ["users", userName, "followers"]++-- | All the users that the given user follows.+--+-- > usersFollowedBy "mike-burns"+usersFollowedBy :: String -> IO (Either Error [GithubUser])+usersFollowedBy userName = githubGet ["users", userName, "following"]
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2011, ???++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 ??? 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.
+ README.md view
@@ -0,0 +1,57 @@+Github+------++The Github API v3 for Haskell.++**This is currently a read-only API.** There is a `read-write` branch with+ideas on how this can work for writing to Github, but I need ideas on how+authentication should work. *You can help* if you [let me+know](mailto:mike@mike-burns.com) how you are using this library or how you+would like to use it, and which authentication method is best for you (HTTP+basic, OAuth).++Some functions which do not require authentication are also missing; these are functions where the Github API did not work as expected. The full Github API is in beta and constantly improving.++Installation+============++In your project's cabal file:++    -- Packages needed in order to build this package.+    Build-depends:       github++Or from the command line:++    cabal install github++Example Usage+=============++See the samples in the [samples/](https://github.com/mike-burns/github/tree/master/samples) directory.++Documentation+=============++For details see the reference documentation on Hackage. Later.++Each module lines up with the hierarchy of [documentation from the Github API](http://developer.github.com/v3/).++Each function has a sample written for it.++All functions produce an `IO (Either Error a)`, where `a` is the actual thing you want. You must call the function using IO goodness, then dispatch on the possible error message. Here's an example from the samples:++    import Github.Users.Followers+    import Data.List (intercalate)+    main = do+      possibleUsers <- usersFollowing "mike-burns"+      putStrLn $ either (\error -> "Error: " ++ $ show error)+                        (intercalate "\n" . map githubUserLogin)+                        possibleUsers+++Copyright+=========++Copyright 2011 Mike Burns.++Available under the BSD 3-clause license.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ github.cabal view
@@ -0,0 +1,160 @@+-- github.cabal auto-generated by cabal init. For additional options,+-- see+-- http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#pkg-descr.+-- The name of the package.+Name:                github++-- The package version. See the Haskell package versioning policy+-- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for+-- standards guiding when and how versions should be incremented.+Version:             0.1++-- A short (one-line) description of the package.+Synopsis:            Access to the Github API, v3.++-- A longer description of the package.+Description:         The Github API provides programmatic access to the full+                     Github Web site, from Issues to Gists to repos down to the underlying git data+                     like references and trees. This library wraps all of that, exposing a basic but+                     Haskell-friendly set of functions and data structures.++-- The license under which the package is released.+License:             BSD3++-- The file containing the license text.+License-file:        LICENSE++-- The package author(s).+Author:              Mike Burns++-- An email address to which users can send suggestions, bug reports,+-- and patches.+Maintainer:          mike@mike-burns.com++-- A copyright notice.+Copyright:           Copyright 2011 Mike Burns++Category:            Network APIs++Build-type:          Simple++-- Extra files to be distributed with the package, such as examples or+-- a README.+Extra-source-files:  README.md+                    ,samples/Gists/Comments/ShowComment.hs+                    ,samples/Gists/Comments/ShowComments.hs+                    ,samples/Gists/ListGists.hs+                    ,samples/Gists/ShowGist.hs+                    ,samples/GitData/Blobs/GitHashObject.hs+                    ,samples/GitData/Commits/GitShow.hs+                    ,samples/GitData/References/GitLsRemote.hs+                    ,samples/GitData/References/GitLsRemoteTags.hs+                    ,samples/GitData/References/GitLsRemoteWithRef.hs+                    ,samples/GitData/Trees/GitLsTree.hs+                    ,samples/GitData/Trees/GitLsTreeRecursively.hs+                    ,samples/Issues/Comments/ShowComment.hs+                    ,samples/Issues/Comments/ShowComments.hs+                    ,samples/Issues/Events/ShowEvent.hs+                    ,samples/Issues/Events/ShowIssueEvents.hs+                    ,samples/Issues/Events/ShowRepoEvents.hs+                    ,samples/Issues/Labels/ShowIssueLabels.hs+                    ,samples/Issues/Labels/ShowLabel.hs+                    ,samples/Issues/Labels/ShowMilestoneLabels.hs+                    ,samples/Issues/Labels/ShowRepoLabels.hs+                    ,samples/Issues/Milestones/ShowMilestone.hs+                    ,samples/Issues/Milestones/ShowMilestones.hs+                    ,samples/Issues/ShowIssue.hs+                    ,samples/Issues/ShowRepoIssues.hs+                    ,samples/Organizations/Members/ShowMembers.hs+                    ,samples/Organizations/ShowPublicOrganization.hs+                    ,samples/Organizations/ShowPublicOrganizations.hs+                    ,samples/Pulls/Diff.hs+                    ,samples/Pulls/ListPulls.hs+                    ,samples/Pulls/ReviewComments/ListComments.hs+                    ,samples/Pulls/ReviewComments/ShowComment.hs+                    ,samples/Pulls/ShowCommits.hs+                    ,samples/Pulls/ShowPull.hs+                    ,samples/Repos/Collaborators/IsCollaborator.hs+                    ,samples/Repos/Collaborators/ListCollaborators.hs+                    ,samples/Repos/Commits/CommitComment.hs+                    ,samples/Repos/Commits/CommitComments.hs+                    ,samples/Repos/Commits/GitDiff.hs+                    ,samples/Repos/Commits/GitLog.hs+                    ,samples/Repos/Commits/GitShow.hs+                    ,samples/Repos/Commits/RepoComments.hs+                    ,samples/Repos/Forks/ListForks.hs+                    ,samples/Repos/ListBranches.hs+                    ,samples/Repos/ListContributors.hs+                    ,samples/Repos/ListContributorsWithAnonymous.hs+                    ,samples/Repos/ListLanguages.hs+                    ,samples/Repos/ListOrgRepos.hs+                    ,samples/Repos/ListTags.hs+                    ,samples/Repos/ListUserRepos.hs+                    ,samples/Repos/ShowRepo.hs+                    ,samples/Repos/Watching/ListWatched.hs+                    ,samples/Repos/Watching/ListWatchers.hs+                    ,samples/Users/Followers/ListFollowers.hs+                    ,samples/Users/Followers/ListFollowing.hs+                    ,samples/Users/ShowUser.hs+                    ,LICENSE+++-- Constraint on the version of Cabal needed to build this package.+Cabal-version:       >=1.6++source-repository head+  type: git+  location: git://github.com/mike-burns/github.git+++Library+  -- Modules exported by the library.+  Exposed-modules: Github.Data,+                   Github.Data.Definitions,++                   Github.Gists,+                   Github.Gists.Comments,+                   Github.GitData.Blobs,+                   Github.GitData.Commits,+                   Github.GitData.References,+                   Github.GitData.Trees,+                   Github.Issues,+                   Github.Issues.Comments,+                   Github.Issues.Events,+                   Github.Issues.Labels,+                   Github.Issues.Milestones,+                   Github.Organizations,+                   Github.Organizations.Members,+                   Github.PullRequests,+                   Github.Repos,+                   Github.Repos.Collaborators,+                   Github.Repos.Commits,+                   Github.Repos.Forks,+                   Github.Repos.Watching,+                   Github.Users,+                   Github.Users.Followers+++  -- Packages needed in order to build this package.+  Build-depends: base >= 4.0 && < 5.0,+                 time,+                 aeson,+                 attoparsec,+                 bytestring,+                 containers,+                 text,+                 old-locale,+                 HTTP,+                 network,+                 http-enumerator,+                 uri,+                 failure,+                 http-types,+                 vector+  +  -- Modules not exported by this package.+  Other-modules:       Github.Private+  +  -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.+  -- Build-tools:         +  
+ samples/Gists/Comments/ShowComment.hs view
@@ -0,0 +1,16 @@+module ShowComment where++import qualified Github.Gists.Comments as Github++main = do+  possibleComment <- Github.comment "62449"+  case possibleComment of+    (Left error)  -> putStrLn $ "Error: " ++ (show error)+    (Right comment) -> putStrLn $ formatComment comment++formatComment comment =+  (Github.githubUserLogin $ Github.gistCommentUser comment) ++ "\n" +++    (formatGithubDate $ Github.gistCommentUpdatedAt comment) ++ "\n\n" +++    (Github.gistCommentBody comment)++formatGithubDate = show . Github.fromGithubDate
+ samples/Gists/Comments/ShowComments.hs view
@@ -0,0 +1,17 @@+module ShowComments where++import qualified Github.Gists.Comments as Github+import Data.List (intercalate)++main = do+  possibleComments <- Github.commentsOn "1174060"+  case possibleComments of+    (Left error)  -> putStrLn $ "Error: " ++ (show error)+    (Right comments) -> putStrLn $ intercalate "\n\n" $ map formatComment comments++formatComment comment =+  (Github.githubUserLogin $ Github.gistCommentUser comment) ++ "\n" +++    (formatGithubDate $ Github.gistCommentUpdatedAt comment) ++ "\n\n" +++    (Github.gistCommentBody comment)++formatGithubDate = show . Github.fromGithubDate
+ samples/Gists/ListGists.hs view
@@ -0,0 +1,15 @@+module ListGists where++import qualified Github.Gists as Github+import Data.List (intercalate)++main = do+  possibleGists <- Github.gists "mike-burns"+  case possibleGists of+    (Left error)  -> putStrLn $ "Error: " ++ (show error)+    (Right gists) -> putStrLn $ intercalate "\n\n" $ map formatGist gists++formatGist gist =+  (Github.gistId gist) ++ "\n" +++    (maybe "indescribable" id $ Github.gistDescription gist) ++ "\n" +++    (Github.gistHtmlUrl gist)
+ samples/Gists/ShowGist.hs view
@@ -0,0 +1,20 @@+module ShowGist where++import qualified Github.Gists as Github+import Data.List (intercalate)++main = do+  possibleGist <- Github.gist "23084"+  case possibleGist of+    (Left error)  -> putStrLn $ "Error: " ++ (show error)+    (Right gist) -> putStrLn $ formatGist gist++formatGist gist =+  (Github.gistId gist) ++ "\n" +++    (maybe "indescribable" id $ Github.gistDescription gist) ++ "\n" +++    (Github.gistHtmlUrl gist) ++ "\n\n" +++    (intercalate "\n\n" $ map formatGistFile $ Github.gistFiles gist)++formatGistFile gistFile =+  (Github.gistFileFilename gistFile) ++ ":\n" +++    maybe "[empty]" id (Github.gistFileContent gistFile)
+ samples/GitData/Blobs/GitHashObject.hs view
@@ -0,0 +1,10 @@+module GitHashObject where++import qualified Github.GitData.Blobs as Github+import Data.List( intercalate)++main = do+  possibleBlob <- Github.blob "thoughtbot" "paperclip" "bc5c51d1ece1ee45f94b056a0f5a1674d7e8cba9"+  case possibleBlob of+    (Left error) -> putStrLn $ "Error: " ++ (show error)+    (Right blob) -> putStrLn $ Github.blobContent blob
+ samples/GitData/Commits/GitShow.hs view
@@ -0,0 +1,23 @@+module GitShow where++import qualified Github.GitData.Commits as Github+import Data.Maybe (fromJust)++main = do+  possibleCommit <- Github.commit "thoughtbot" "paperclip" "bc5c51d1ece1ee45f94b056a0f5a1674d7e8cba9"+  case possibleCommit of+    (Left error)    -> putStrLn $ "Error: " ++ (show error)+    (Right commit) -> putStrLn $ formatCommit commit++formatCommit :: Github.GitCommit -> String+formatCommit commit =+  "commit " ++ (fromJust $ Github.gitCommitSha commit) +++    "\nAuthor: " ++ (formatAuthor author) +++    "\nDate:   " ++ (show $ Github.fromGithubDate $ Github.gitUserDate author) +++    "\n\n\t" ++ (Github.gitCommitMessage commit) ++ "\n"+  where author = Github.gitCommitAuthor commit++formatAuthor :: Github.GitUser -> String+formatAuthor author =+  (Github.gitUserName author) ++ " <" ++ (Github.gitUserEmail author) ++ ">"+
+ samples/GitData/References/GitLsRemote.hs view
@@ -0,0 +1,16 @@+module GitLsRemote where++import qualified Github.GitData.References as Github+import Data.List (intercalate)++main = do+  possibleReferences <- Github.references "mike-burns" "github"+  case possibleReferences of+       (Left error)       -> putStrLn $ "Error: " ++ show error+       (Right references) -> do+         putStrLn "From git@github.com:mike-burns/github.git"+         putStrLn $ intercalate "\n" $ map formatReference references++formatReference reference =+  (Github.gitObjectSha $ Github.gitReferenceObject reference) +++    "\t" ++ (Github.gitReferenceRef reference)
+ samples/GitData/References/GitLsRemoteTags.hs view
@@ -0,0 +1,17 @@+module GitLsRemoteTags where++import qualified Github.GitData.References as Github+import Data.List (intercalate)++main = do+  possibleReferences <- Github.namespacedReferences "thoughtbot" "paperclip" "tags"+  case possibleReferences of+       (Left error)       -> putStrLn $ "Error: " ++ show error+       (Right references) -> do+         putStrLn "From git@github.com:thoughtbot/paperclip.git"+         putStrLn $ intercalate "\n" $ map formatReference references++formatReference reference =+  (Github.gitObjectSha $ Github.gitReferenceObject reference) +++    "\t" ++ (Github.gitReferenceRef reference)+
+ samples/GitData/References/GitLsRemoteWithRef.hs view
@@ -0,0 +1,13 @@+module GitLsRemoteWithRef where++import qualified Github.GitData.References as Github++main = do+  possibleReference <- Github.reference "mike-burns" "github" "heads/master"+  putStrLn $ either (\e -> "Error: " ++ show e)+                    formatReference+                    possibleReference++formatReference reference =+  (Github.gitObjectSha $ Github.gitReferenceObject reference) +++    "\t" ++ (Github.gitReferenceRef reference)
+ samples/GitData/Trees/GitLsTree.hs view
@@ -0,0 +1,19 @@+module GitLsTree where++import qualified Github.GitData.Trees as Github+import Data.List (intercalate)++main = do+  possibleTree <- Github.tree "thoughtbot" "paperclip" "fe114451f7d066d367a1646ca7ac10e689b46844"+  case possibleTree of+       (Left error)  -> putStrLn $ "Error: " ++ show error+       (Right tree) -> putStrLn $ formatTree tree++formatTree tree =+  intercalate "\n" $ map formatGitTree $ Github.treeGitTrees tree++formatGitTree gitTree =+  (Github.gitTreeMode gitTree) ++ " " +++    (Github.gitTreeType gitTree) ++ " " +++    (Github.gitTreeSha gitTree) ++ "\t" +++    (Github.gitTreePath gitTree)
+ samples/GitData/Trees/GitLsTreeRecursively.hs view
@@ -0,0 +1,19 @@+module GitLsTreeRecursively where++import qualified Github.GitData.Trees as Github+import Data.List (intercalate)++main = do+  possibleTree <- Github.nestedTree "thoughtbot" "paperclip" "fe114451f7d066d367a1646ca7ac10e689b46844"+  case possibleTree of+       (Left error)  -> putStrLn $ "Error: " ++ show error+       (Right tree) -> putStrLn $ formatTree tree++formatTree tree =+  intercalate "\n" $ map formatGitTree $ Github.treeGitTrees tree++formatGitTree gitTree =+  (Github.gitTreeMode gitTree) ++ " " +++    (Github.gitTreeType gitTree) ++ " " +++    (Github.gitTreeSha gitTree) ++ "\t" +++    (Github.gitTreePath gitTree)
+ samples/Issues/Comments/ShowComment.hs view
@@ -0,0 +1,15 @@+module ShowComment where++import qualified Github.Issues.Comments as Github++main = do+  possibleComment <- Github.comment "thoughtbot" "paperclip" 1468184+  putStrLn $ either (\e -> "Error: " ++ show e)+                    formatComment+                    possibleComment++formatComment comment =+  (Github.githubUserLogin $ Github.issueCommentUser comment) +++    " commented " +++    (show $ Github.fromGithubDate $ Github.issueCommentUpdatedAt comment) +++    "\n" ++ (Github.issueCommentBody comment)
+ samples/Issues/Comments/ShowComments.hs view
@@ -0,0 +1,17 @@+module ShowComments where++import qualified Github.Issues.Comments as Github+import Data.List (intercalate)++main = do+  possibleComments <- Github.comments "thoughtbot" "paperclip" 635+  case possibleComments of+       (Left error) -> putStrLn $ "Error: " ++ show error+       (Right issues) ->+         putStrLn $ intercalate "\n\n" $ map formatComment issues++formatComment comment =+  (Github.githubUserLogin $ Github.issueCommentUser comment) +++    " commented " +++    (show $ Github.fromGithubDate $ Github.issueCommentUpdatedAt comment) +++    "\n" ++ (Github.issueCommentBody comment)
+ samples/Issues/Events/ShowEvent.hs view
@@ -0,0 +1,38 @@+module ShowEvents where++import qualified Github.Issues.Events as Github+import Data.List (intercalate)+import Data.Maybe (fromJust)++main = do+  possibleEvent <- Github.event "thoughtbot" "paperclip" 5335772+  case possibleEvent of+       (Left error) -> putStrLn $ "Error: " ++ show error+       (Right event) -> do+         putStrLn $ formatEvent event++formatEvent event = formatEvent' event (Github.eventType event)+  where+  formatEvent' event Github.Closed =+    "Closed on " ++ createdAt event ++ " by " ++ loginName event +++      withCommitId event (\commitId -> " in the commit " ++ commitId)+  formatEvent' event Github.Reopened =+    "Reopened on " ++ createdAt event ++ " by " ++ loginName event+  formatEvent' event Github.Subscribed =+    loginName event ++ " is subscribed to receive notifications"+  formatEvent' event Github.Unsubscribed =+    loginName event ++ " is unsubscribed from notifications"+  formatEvent' event Github.Merged =+    "Issue merged by " ++ loginName event ++ " on " ++ createdAt event +++      (withCommitId event $ \commitId -> " in the commit " ++ commitId)+  formatEvent' event Github.Referenced =+    withCommitId event $ \commitId ->+      "Issue referenced from " ++ commitId ++ " by " ++ loginName event+  formatEvent' event Github.Mentioned =+    loginName event ++ " was mentioned in the issue's body"+  formatEvent' event Github.Assigned =+    "Issue assigned to " ++ loginName event ++ " on " ++ createdAt event++loginName = Github.githubUserLogin . Github.eventActor+createdAt = show . Github.fromGithubDate . Github.eventCreatedAt+withCommitId event f = maybe "" f (Github.eventCommitId event)
+ samples/Issues/Events/ShowIssueEvents.hs view
@@ -0,0 +1,38 @@+module ShowIssueEvents where++import qualified Github.Issues.Events as Github+import Data.List (intercalate)++main = do+  possibleEvents <- Github.eventsForIssue "thoughtbot" "paperclip" 49+  case possibleEvents of+       (Left error) -> putStrLn $ "Error: " ++ show error+       (Right events) -> do+         putStrLn "Issue #49:\n"+         putStrLn $ intercalate "\n" $ map formatEvent events++formatEvent event = formatEvent' event (Github.eventType event)+  where+  formatEvent' event Github.Closed =+    "Closed on " ++ createdAt event ++ " by " ++ loginName event +++      withCommitId event (\commitId -> " in the commit " ++ commitId)+  formatEvent' event Github.Reopened =+    "Reopened on " ++ createdAt event ++ " by " ++ loginName event+  formatEvent' event Github.Subscribed =+    loginName event ++ " is subscribed to receive notifications"+  formatEvent' event Github.Unsubscribed =+    loginName event ++ " is unsubscribed from notifications"+  formatEvent' event Github.Merged =+    "Issue merged by " ++ loginName event ++ " on " ++ createdAt event +++      (withCommitId event $ \commitId -> " in the commit " ++ commitId)+  formatEvent' event Github.Referenced =+    withCommitId event $ \commitId ->+      "Issue referenced from " ++ commitId ++ " by " ++ loginName event+  formatEvent' event Github.Mentioned =+    loginName event ++ " was mentioned in the issue's body"+  formatEvent' event Github.Assigned =+    "Issue assigned to " ++ loginName event ++ " on " ++ createdAt event++loginName = Github.githubUserLogin . Github.eventActor+createdAt = show . Github.fromGithubDate . Github.eventCreatedAt+withCommitId event f = maybe "" f (Github.eventCommitId event)
+ samples/Issues/Events/ShowRepoEvents.hs view
@@ -0,0 +1,41 @@+module ShowRepoEvents where++import qualified Github.Issues.Events as Github+import Data.List (intercalate)+import Data.Maybe (fromJust)++main = do+  possibleEvents <- Github.eventsForRepo "thoughtbot" "paperclip"+  case possibleEvents of+       (Left error) -> putStrLn $ "Error: " ++ show error+       (Right events) -> do+         putStrLn $ intercalate "\n" $ map formatEvent events++formatEvent event =+  "Issue #" ++ issueNumber event ++ ": " +++    formatEvent' event (Github.eventType event)+  where+  formatEvent' event Github.Closed =+    "closed on " ++ createdAt event ++ " by " ++ loginName event +++      withCommitId event (\commitId -> " in the commit " ++ commitId)+  formatEvent' event Github.Reopened =+    "reopened on " ++ createdAt event ++ " by " ++ loginName event+  formatEvent' event Github.Subscribed =+    loginName event ++ " is subscribed to receive notifications"+  formatEvent' event Github.Unsubscribed =+    loginName event ++ " is unsubscribed from notifications"+  formatEvent' event Github.Merged =+    "merged by " ++ loginName event ++ " on " ++ createdAt event +++      (withCommitId event $ \commitId -> " in the commit " ++ commitId)+  formatEvent' event Github.Referenced =+    withCommitId event $ \commitId ->+      "referenced from " ++ commitId ++ " by " ++ loginName event+  formatEvent' event Github.Mentioned =+    loginName event ++ " was mentioned in the issue's body"+  formatEvent' event Github.Assigned =+    "assigned to " ++ loginName event ++ " on " ++ createdAt event++loginName = Github.githubUserLogin . Github.eventActor+createdAt = show . Github.fromGithubDate . Github.eventCreatedAt+withCommitId event f = maybe "" f (Github.eventCommitId event)+issueNumber = show . Github.issueNumber . fromJust . Github.eventIssue
+ samples/Issues/Labels/ShowIssueLabels.hs view
@@ -0,0 +1,14 @@+module ShowIssueLabels where++import qualified Github.Issues.Labels as Github+import Data.List (intercalate)++main = do+  possibleLabels <- Github.labelsOnIssue "thoughtbot" "paperclip" 585+  case possibleLabels of+       (Left error) -> putStrLn $ "Error: " ++ show error+       (Right labels) -> do+         putStrLn $ intercalate "\n" $ map formatLabel labels++formatLabel label =+  (Github.labelName label) ++ ", colored " ++ (Github.labelColor label)
+ samples/Issues/Labels/ShowLabel.hs view
@@ -0,0 +1,13 @@+module ShowLabel where++import qualified Github.Issues.Labels as Github++main = do+  possibleLabel <- Github.label "thoughtbot" "paperclip" "bug"+  case possibleLabel of+       (Left error) -> putStrLn $ "Error: " ++ show error+       (Right label) -> putStrLn $ formatLabel label++formatLabel label =+  (Github.labelName label) ++ ", colored " ++ (Github.labelColor label)+
+ samples/Issues/Labels/ShowMilestoneLabels.hs view
@@ -0,0 +1,15 @@+module ShowMilestoneLabels where++import qualified Github.Issues.Labels as Github+import Data.List (intercalate)++main = do+  possibleLabels <- Github.labelsOnMilestone "thoughtbot" "paperclip" 2+  case possibleLabels of+       (Left error) -> putStrLn $ "Error: " ++ show error+       (Right labels) -> do+         putStrLn $ intercalate "\n" $ map formatLabel labels++formatLabel label =+  (Github.labelName label) ++ ", colored " ++ (Github.labelColor label)+
+ samples/Issues/Labels/ShowRepoLabels.hs view
@@ -0,0 +1,14 @@+module ShowRepoLabels where++import qualified Github.Issues.Labels as Github+import Data.List (intercalate)++main = do+  possibleLabels <- Github.labelsOnRepo "thoughtbot" "paperclip"+  case possibleLabels of+       (Left error) -> putStrLn $ "Error: " ++ show error+       (Right labels) -> do+         putStrLn $ intercalate "\n" $ map formatLabel labels++formatLabel label =+  (Github.labelName label) ++ ", colored " ++ (Github.labelColor label)
+ samples/Issues/Milestones/ShowMilestone.hs view
@@ -0,0 +1,22 @@+module ShowMilestone where++import qualified Github.Issues.Milestones as Github+import Data.List (intercalate)++main = do+  possibleMilestone <- Github.milestone "thoughtbot" "paperclip" 2+  case possibleMilestone of+       (Left error) -> putStrLn $ "Error: " ++ show error+       (Right milestone) ->+         putStrLn $ formatMilestone milestone++formatMilestone milestone =+  (Github.milestoneTitle milestone) ++ ", as created by " +++    (loginName milestone) ++ " on " ++ (createdAt milestone) +++    ", is due on " ++ (dueOn milestone) ++ " and has the " +++    (Github.milestoneState milestone) ++ " status"++loginName = Github.githubUserLogin . Github.milestoneCreator+createdAt = show . Github.fromGithubDate . Github.milestoneCreatedAt+dueOn = show . Github.fromGithubDate . Github.milestoneDueOn+
+ samples/Issues/Milestones/ShowMilestones.hs view
@@ -0,0 +1,21 @@+module ShowMilestones where++import qualified Github.Issues.Milestones as Github+import Data.List (intercalate)++main = do+  possibleMilestones <- Github.milestones "thoughtbot" "paperclip"+  case possibleMilestones of+       (Left error) -> putStrLn $ "Error: " ++ show error+       (Right milestones) ->+         putStrLn $ intercalate "\n\n" $ map formatMilestone milestones++formatMilestone milestone =+  (Github.milestoneTitle milestone) ++ ", as created by " +++    (loginName milestone) ++ " on " ++ (createdAt milestone) +++    ", is due on " ++ (dueOn milestone) ++ " and has the " +++    (Github.milestoneState milestone) ++ " status"++loginName = Github.githubUserLogin . Github.milestoneCreator+createdAt = show . Github.fromGithubDate . Github.milestoneCreatedAt+dueOn = show . Github.fromGithubDate . Github.milestoneDueOn
+ samples/Issues/ShowIssue.hs view
@@ -0,0 +1,17 @@+module ShowIssue where++import qualified Github.Issues as Github++main = do+  possibleIssue <- Github.issue "thoughtbot" "paperclip" 549+  putStrLn $ either (\e -> "Error: " ++ show e)+                    formatIssue+                    possibleIssue++formatIssue issue =+  (Github.githubUserLogin $ Github.issueUser issue) +++    " opened this issue " +++    (show $ Github.fromGithubDate $ Github.issueCreatedAt issue) ++ "\n" +++    (Github.issueState issue) ++ " with " +++    (show $ Github.issueComments issue) ++ " comments" ++ "\n\n" +++    (Github.issueTitle issue)
+ samples/Issues/ShowRepoIssues.hs view
@@ -0,0 +1,21 @@+module ShowRepoIssue where++import qualified Github.Issues as Github+import Data.List (intercalate)++main = do+  let limitations = [Github.OnlyClosed, Github.Mentions "mike-burns", Github.AssignedTo "jyurek"]+  possibleIssues <- Github.issuesForRepo "thoughtbot" "paperclip" limitations+  case possibleIssues of+       (Left error) -> putStrLn $ "Error: " ++ show error+       (Right issues) ->+         putStrLn $ intercalate "\n\n" $ map formatIssue issues++formatIssue issue =+  (Github.githubUserLogin $ Github.issueUser issue) +++    " opened this issue " +++    (show $ Github.fromGithubDate $ Github.issueCreatedAt issue) ++ "\n" +++    (Github.issueState issue) ++ " with " +++    (show $ Github.issueComments issue) ++ " comments" ++ "\n\n" +++    (Github.issueTitle issue)+
+ samples/Organizations/Members/ShowMembers.hs view
@@ -0,0 +1,11 @@+module ShowMembers where++import qualified Github.Organizations.Members as Github+import Data.List (intercalate)++main = do+  possibleMembers <- Github.membersOf "thoughtbot"+  case possibleMembers of+       (Left error)  -> putStrLn $ "Error: " ++ (show error)+       (Right members) ->+         putStrLn $ intercalate "\n" $ map Github.githubUserLogin members
+ samples/Organizations/ShowPublicOrganization.hs view
@@ -0,0 +1,15 @@+module ShowPublicOrganization where++import qualified Github.Organizations as Github++main = do+  possibleOrganization <- Github.publicOrganization "thoughtbot"+  case possibleOrganization of+       (Left error)  -> putStrLn $ "Error: " ++ (show error)+       (Right organization) ->+         putStrLn $ formatOrganization organization++formatOrganization organization =+  (maybe "" (\s -> s ++ "\n") (Github.organizationName organization)) +++    (Github.organizationHtmlUrl organization) +++    (maybe "" (\s -> "\n" ++ s) (Github.organizationBlog organization))
+ samples/Organizations/ShowPublicOrganizations.hs view
@@ -0,0 +1,13 @@+module ShowPublicOrganizations where++import qualified Github.Organizations as Github+import Data.List (intercalate)++main = do+  possibleOrganizations <- Github.publicOrganizationsFor "mike-burns"+  case possibleOrganizations of+       (Left error)  -> putStrLn $ "Error: " ++ (show error)+       (Right organizations) ->+         putStrLn $ intercalate "\n" $ map formatOrganization organizations++formatOrganization = Github.simpleOrganizationLogin
+ samples/Pulls/Diff.hs view
@@ -0,0 +1,13 @@+module Diff where++import qualified Github.PullRequests as Github+import Data.List++main = do+  possiblePullRequestFiles <- Github.pullRequestFiles "thoughtbot" "paperclip" 575+  case possiblePullRequestFiles of+       (Left error)    -> putStrLn $ "Error: " ++ (show error)+       (Right files) -> putStrLn $ intercalate "\n\n" $ map formatFile files++formatFile file =+  Github.fileFilename file ++ "\n" ++ Github.filePatch file
+ samples/Pulls/ListPulls.hs view
@@ -0,0 +1,23 @@+module ListPulls where++import qualified Github.PullRequests as Github+import Data.List++main = do+  possiblePullRequests <- Github.pullRequestsFor "thoughtbot" "paperclip"+  case possiblePullRequests of+       (Left error) -> putStrLn $ "Error: " ++ (show error)+       (Right pullRequests) ->+         putStrLn $ intercalate "\n\n" $ map formatPullRequest pullRequests++formatPullRequest pullRequest =+  (Github.pullRequestTitle pullRequest) ++ "\n" +++    (take 80 $ Github.pullRequestBody pullRequest) ++ "\n" +++    (Github.githubUserLogin $ Github.pullRequestUser pullRequest) +++    " submitted to thoughtbot/paperclip " +++    (formatGithubDate $ Github.pullRequestCreatedAt pullRequest) +++    " updated " +++    (formatGithubDate $ Github.pullRequestUpdatedAt pullRequest) ++ "\n" +++    (Github.pullRequestHtmlUrl pullRequest)++formatGithubDate = show . Github.fromGithubDate
+ samples/Pulls/ReviewComments/ListComments.hs view
@@ -0,0 +1,21 @@+module ListComments where++import qualified Github.PullRequests.ReviewComments as Github+import Data.List++main = do+  possiblePullRequestComments <- Github.pullRequestReviewComments "thoughtbot" "factory_girl" 256+  case possiblePullRequestComments of+       (Left error)     -> putStrLn $ "Error: " ++ (show error)+       (Right comments) -> putStrLn $ intercalate "\n\n" $ map formatComment comments++formatComment :: Github.Comment -> String+formatComment comment =+  "Author: " ++ (formatAuthor $ Github.commentUser comment) +++    "\nUpdated: " ++ (show $ Github.commentUpdatedAt comment) +++    (maybe "" ("\nURL: "++) $ Github.commentHtmlUrl comment) +++    "\n\n" ++ (Github.commentBody comment)++formatAuthor :: Github.GithubUser -> String+formatAuthor user =+  (Github.githubUserLogin user) ++ " (" ++ (Github.githubUserUrl user) ++ ")"
+ samples/Pulls/ReviewComments/ShowComment.hs view
@@ -0,0 +1,22 @@+module ShowComments where++import qualified Github.PullRequests.ReviewComments as Github+import Data.List++main = do+  possiblePullRequestComment <- Github.pullRequestReviewComment "thoughtbot" "factory_girl" 301819+  case possiblePullRequestComment of+       (Left error)     -> putStrLn $ "Error: " ++ (show error)+       (Right comment) -> putStrLn $ formatComment comment++formatComment :: Github.Comment -> String+formatComment comment =+  "Author: " ++ (formatAuthor $ Github.commentUser comment) +++    "\nUpdated: " ++ (show $ Github.commentUpdatedAt comment) +++    (maybe "" ("\nURL: "++) $ Github.commentHtmlUrl comment) +++    "\n\n" ++ (Github.commentBody comment)++formatAuthor :: Github.GithubUser -> String+formatAuthor user =+  (Github.githubUserLogin user) ++ " (" ++ (Github.githubUserUrl user) ++ ")"+
+ samples/Pulls/ShowCommits.hs view
@@ -0,0 +1,21 @@+module ShowCommits where++import qualified Github.PullRequests as Github+import Data.List+import Data.Maybe++main = do+  possiblePullRequestCommits <- Github.pullRequestCommits "thoughtbot" "paperclip" 575+  case possiblePullRequestCommits of+       (Left error)    -> putStrLn $ "Error: " ++ (show error)+       (Right commits) -> putStrLn $ intercalate "\n" $ map formatCommit commits++formatCommit commit =+  (formatAuthor $ Github.gitCommitAuthor gitCommit) ++ "\n" +++    (maybe "unknown SHA" id $ Github.gitCommitSha gitCommit) ++ "\n" +++    (Github.gitCommitMessage gitCommit)+  where gitCommit = Github.commitGitCommit commit++formatAuthor :: Github.GitUser -> String+formatAuthor author =+  (Github.gitUserName author) ++ " <" ++ (Github.gitUserEmail author) ++ ">"
+ samples/Pulls/ShowPull.hs view
@@ -0,0 +1,24 @@+module ShowPull where++import qualified Github.PullRequests as Github+import Data.List++main = do+  possiblePullRequest <- Github.pullRequest "thoughtbot" "paperclip" 575+  case possiblePullRequest of+       (Left error) -> putStrLn $ "Error: " ++ (show error)+       (Right pullRequest) -> putStrLn $ formatPullRequest pullRequest++formatPullRequest p =+  (Github.githubUserLogin $ Github.detailedPullRequestUser p) +++    " opened this pull request " +++    (formatGithubDate $ Github.detailedPullRequestCreatedAt p) ++ "\n" +++    (Github.detailedPullRequestTitle p) ++ "\n" +++    (Github.detailedPullRequestBody p) ++ "\n" +++    (Github.detailedPullRequestState p) ++ "\n" +++    "+" ++ (show $ Github.detailedPullRequestAdditions p) ++ " additions\n" +++    "-" ++ (show $ Github.detailedPullRequestDeletions p) ++ " deletions\n" +++    (show $ Github.detailedPullRequestComments p) ++ " comments\n" +++    (Github.detailedPullRequestHtmlUrl p)++formatGithubDate = show . Github.fromGithubDate
+ samples/Repos/Collaborators/IsCollaborator.hs view
@@ -0,0 +1,14 @@+module IsCollaborator where++import qualified Github.Repos.Collaborators as Github+import Data.List++main = do+  let userName = "ubuwaits"+  possiblyIsCollaborator <- Github.isCollaboratorOn userName "thoughtbot" "paperclip"+  case possiblyIsCollaborator of+    (Left error) -> putStrLn $ "Error: " ++ (show error)+    (Right True) ->+      putStrLn $ userName ++ " is a collaborator on thoughtbot's paperclip"+    (Right False) ->+      putStrLn $ userName ++ " does not collaborate on thoughtbot's paperclip"
+ samples/Repos/Collaborators/ListCollaborators.hs view
@@ -0,0 +1,15 @@+module ListCollaborators where++import qualified Github.Repos.Collaborators as Github+import Data.List++main = do+  possibleCollaborators <- Github.collaboratorsOn "thoughtbot" "paperclip"+  case possibleCollaborators of+    (Left error) -> putStrLn $ "Error: " ++ (show error)+    (Right collaborators) ->+      putStrLn $ intercalate "\n" $ map formatAuthor collaborators++formatAuthor :: Github.GithubUser -> String+formatAuthor user =+  (Github.githubUserLogin user) ++ " (" ++ (Github.githubUserUrl user) ++ ")"
+ samples/Repos/Commits/CommitComment.hs view
@@ -0,0 +1,21 @@+module CommitComment where++import qualified Github.Repos.Commits as Github+import Data.Maybe (maybe)++main = do+  possibleComment <- Github.commitCommentFor "thoughtbot" "paperclip" "669575"+  case possibleComment of+    (Left error)    -> putStrLn $ "Error: " ++ (show error)+    (Right comment) -> putStrLn $ formatComment comment++formatComment :: Github.Comment -> String+formatComment comment =+  "Author: " ++ (formatAuthor $ Github.commentUser comment) +++    "\nUpdated: " ++ (show $ Github.commentUpdatedAt comment) +++    (maybe "" ("\nURL: "++) $ Github.commentHtmlUrl comment) +++    "\n\n" ++ (Github.commentBody comment)++formatAuthor :: Github.GithubUser -> String+formatAuthor user =+  (Github.githubUserLogin user) ++ " (" ++ (Github.githubUserUrl user) ++ ")"
+ samples/Repos/Commits/CommitComments.hs view
@@ -0,0 +1,22 @@+module CommitComments where++import qualified Github.Repos.Commits as Github+import Data.List+import Data.Maybe (maybe)++main = do+  possibleComments <- Github.commitCommentsFor "thoughtbot" "paperclip" "41f685f6e01396936bb8cd98e7cca517e2c7d96b"+  case possibleComments of+    (Left error)    -> putStrLn $ "Error: " ++ (show error)+    (Right comments) -> putStrLn $ intercalate "\n\n" $  map formatComment comments++formatComment :: Github.Comment -> String+formatComment comment =+  "Author: " ++ (formatAuthor $ Github.commentUser comment) +++    "\nUpdated: " ++ (show $ Github.commentUpdatedAt comment) +++    (maybe "" ("\nURL: "++) $ Github.commentHtmlUrl comment) +++    "\n\n" ++ (Github.commentBody comment)++formatAuthor :: Github.GithubUser -> String+formatAuthor user =+  (Github.githubUserLogin user) ++ " (" ++ (Github.githubUserUrl user) ++ ")"
+ samples/Repos/Commits/GitDiff.hs view
@@ -0,0 +1,13 @@+module GitDiff where++import qualified Github.Repos.Commits as Github+import Data.List++main = do+  possibleDiff <- Github.diff "thoughtbot" "paperclip" "41f685f6e01396936bb8cd98e7cca517e2c7d96b" "HEAD"+  either (\error -> putStrLn $ "Error: " ++ (show error))+         (putStrLn . showDiff)+         possibleDiff++showDiff diff =+ intercalate "\n\n" $ map Github.filePatch $ Github.diffFiles diff
+ samples/Repos/Commits/GitLog.hs view
@@ -0,0 +1,23 @@+module GitLog where++import qualified Github.Repos.Commits as Github+import Data.List++main = do+  possibleCommits <- Github.commitsFor "thoughtbot" "paperclip"+  case possibleCommits of+    (Left error)    -> putStrLn $ "Error: " ++ (show error)+    (Right commits) -> putStrLn $ intercalate "\n\n" $ map formatCommit commits++formatCommit :: Github.Commit -> String+formatCommit commit =+  "commit " ++ (Github.commitSha commit) +++    "\nAuthor: " ++ (formatAuthor author) +++    "\nDate:   " ++ (show $ Github.fromGithubDate $ Github.gitUserDate author) +++    "\n\n\t" ++ (Github.gitCommitMessage gitCommit)+  where author = Github.gitCommitAuthor gitCommit+        gitCommit = Github.commitGitCommit commit++formatAuthor :: Github.GitUser -> String+formatAuthor author =+  (Github.gitUserName author) ++ " <" ++ (Github.gitUserEmail author) ++ ">"
+ samples/Repos/Commits/GitShow.hs view
@@ -0,0 +1,27 @@+module GitShow where++import qualified Github.Repos.Commits as Github+import Data.List++main = do+  possibleCommit <- Github.commit "thoughtbot" "paperclip" "bc5c51d1ece1ee45f94b056a0f5a1674d7e8cba9"+  case possibleCommit of+    (Left error)    -> putStrLn $ "Error: " ++ (show error)+    (Right commit) -> putStrLn $ formatCommit commit++formatCommit :: Github.Commit -> String+formatCommit commit =+  "commit " ++ (Github.commitSha commit) +++    "\nAuthor: " ++ (formatAuthor author) +++    "\nDate:   " ++ (show $ Github.fromGithubDate $ Github.gitUserDate author) +++    "\n\n\t" ++ (Github.gitCommitMessage gitCommit) ++ "\n" +++    patches+  where author = Github.gitCommitAuthor gitCommit+        gitCommit = Github.commitGitCommit commit+        patches = +          intercalate "\n" $ map Github.filePatch $ Github.commitFiles commit++formatAuthor :: Github.GitUser -> String+formatAuthor author =+  (Github.gitUserName author) ++ " <" ++ (Github.gitUserEmail author) ++ ">"+
+ samples/Repos/Commits/RepoComments.hs view
@@ -0,0 +1,22 @@+module RepoComments where++import qualified Github.Repos.Commits as Github+import Data.List+import Data.Maybe (maybe)++main = do+  possibleComments <- Github.commentsFor "thoughtbot" "paperclip"+  case possibleComments of+    (Left error)    -> putStrLn $ "Error: " ++ (show error)+    (Right comments) -> putStrLn $ intercalate "\n\n" $  map formatComment comments++formatComment :: Github.Comment -> String+formatComment comment =+  "Author: " ++ (formatAuthor $ Github.commentUser comment) +++    "\nUpdated: " ++ (show $ Github.commentUpdatedAt comment) +++    (maybe "" ("\nURL: "++) $ Github.commentHtmlUrl comment) +++    "\n\n" ++ (Github.commentBody comment)++formatAuthor :: Github.GithubUser -> String+formatAuthor user =+  (Github.githubUserLogin user) ++ " (" ++ (Github.githubUserUrl user) ++ ")"
+ samples/Repos/Forks/ListForks.hs view
@@ -0,0 +1,15 @@+module ListForks where++import qualified Github.Repos.Forks as Github+import Data.List++main = do+  possibleForks <- Github.forksFor "thoughtbot" "paperclip"+  putStrLn $ either (("Error: "++) . show)+                    (intercalate "\n\n" . map formatFork)+                    possibleForks++formatFork fork =+  (Github.githubUserLogin $ Github.repoOwner fork) ++ "\t" +++  (show $ Github.fromGithubDate $ Github.repoPushedAt fork) ++ "\n" +++  (Github.repoCloneUrl fork)
+ samples/Repos/ListBranches.hs view
@@ -0,0 +1,11 @@+module ListBranches where++import qualified Github.Repos as Github+import Data.List++main = do+  possibleBranches <- Github.branchesFor "thoughtbot" "paperclip"+  case possibleBranches of+       (Left error) -> putStrLn $ "Error: " ++ (show error)+       (Right branches) ->+         putStrLn $ intercalate "\n" $ map Github.branchName branches
+ samples/Repos/ListContributors.hs view
@@ -0,0 +1,16 @@+module ListContributors where++import qualified Github.Repos as Github+import Data.List++main = do+  possibleContributors <- Github.contributors "thoughtbot" "paperclip"+  case possibleContributors of+       (Left error) -> putStrLn $ "Error: " ++ (show error)+       (Right contributors) ->+         putStrLn $ intercalate "\n" $ map formatContributor contributors++formatContributor (Github.KnownContributor contributions _ login _ _ _) =+  (show $ contributions) ++ "\t" ++ login+formatContributor (Github.AnonymousContributor contributions name) =+  (show $ contributions) ++ "\t" ++ name
+ samples/Repos/ListContributorsWithAnonymous.hs view
@@ -0,0 +1,16 @@+module ListContributorsWithAnonymous where++import qualified Github.Repos as Github+import Data.List++main = do+  possibleContributors <- Github.contributorsWithAnonymous "thoughtbot" "paperclip"+  case possibleContributors of+       (Left error) -> putStrLn $ "Error: " ++ (show error)+       (Right contributors) ->+         putStrLn $ intercalate "\n" $ map formatContributor contributors++formatContributor (Github.KnownContributor contributions _ login _ _ _) =+  (show $ contributions) ++ "\t" ++ login+formatContributor (Github.AnonymousContributor contributions name) =+  (show $ contributions) ++ "\t" ++ name
+ samples/Repos/ListLanguages.hs view
@@ -0,0 +1,14 @@+module ListLanguages where++import qualified Github.Repos as Github+import Data.List++main = do+  possibleLanguages <- Github.languagesFor "mike-burns" "ohlaunch"+  case possibleLanguages of+       (Left error) -> putStrLn $ "Error: " ++ (show error)+       (Right languages) ->+         putStrLn $ intercalate "\n" $ map formatLanguage languages++formatLanguage (Github.Language name characterCount) =+  name ++ "\t" ++ show characterCount
+ samples/Repos/ListOrgRepos.hs view
@@ -0,0 +1,23 @@+module ListOrgRepos where++import qualified Github.Repos as Github+import Data.List++main = do+  possibleRepos <- Github.organizationRepos "thoughtbot"+  case possibleRepos of+       (Left error)  -> putStrLn $ "Error: " ++ (show error)+       (Right repos) -> putStrLn $ intercalate "\n\n" $ map formatRepo repos++formatRepo repo =+  (Github.repoName repo) ++ "\t" +++    (Github.repoDescription repo) ++ "\n" +++    (Github.repoHtmlUrl repo) ++ "\n" +++    (Github.repoCloneUrl repo) ++ "\t" +++    (formatDate $ Github.repoUpdatedAt repo) ++ "\n" +++    "language: " ++ (Github.repoLanguage repo) ++ "\t" +++    "watchers: " ++ (show $ Github.repoWatchers repo) ++ "\t" +++    "forks: " ++ (show $ Github.repoForks repo)++formatDate = show . Github.fromGithubDate+
+ samples/Repos/ListTags.hs view
@@ -0,0 +1,11 @@+module ListTags where++import qualified Github.Repos as Github+import Data.List++main = do+  possibleTags <- Github.tagsFor "thoughtbot" "paperclip"+  case possibleTags of+       (Left error) -> putStrLn $ "Error: " ++ (show error)+       (Right tags) ->+         putStrLn $ intercalate "\n" $ map Github.tagName tags
+ samples/Repos/ListUserRepos.hs view
@@ -0,0 +1,22 @@+module ListUserRepos where++import qualified Github.Repos as Github+import Data.List++main = do+  possibleRepos <- Github.userRepos "mike-burns" Github.Owner+  case possibleRepos of+       (Left error)  -> putStrLn $ "Error: " ++ (show error)+       (Right repos) -> putStrLn $ intercalate "\n\n" $ map formatRepo repos++formatRepo repo =+  (Github.repoName repo) ++ "\t" +++    (Github.repoDescription repo) ++ "\n" +++    (Github.repoHtmlUrl repo) ++ "\n" +++    (Github.repoCloneUrl repo) ++ "\t" +++    (formatDate $ Github.repoUpdatedAt repo) ++ "\n" +++    "language: " ++ (Github.repoLanguage repo) ++ "\t" +++    "watchers: " ++ (show $ Github.repoWatchers repo) ++ "\t" +++    "forks: " ++ (show $ Github.repoForks repo)++formatDate = show . Github.fromGithubDate
+ samples/Repos/ShowRepo.hs view
@@ -0,0 +1,22 @@+module ShowRepo where++import qualified Github.Repos as Github+import Data.List++main = do+  possibleRepo <- Github.userRepo "mike-burns" "trylambda"+  case possibleRepo of+       (Left error) -> putStrLn $ "Error: " ++ (show error)+       (Right repo) -> putStrLn $ formatRepo repo++formatRepo repo =+  (Github.repoName repo) ++ "\t" +++    (Github.repoDescription repo) ++ "\n" +++    (Github.repoHtmlUrl repo) ++ "\n" +++    (Github.repoCloneUrl repo) ++ "\t" +++    (formatDate $ Github.repoUpdatedAt repo) ++ "\n" +++    "language: " ++ (Github.repoLanguage repo) ++ "\t" +++    "watchers: " ++ (show $ Github.repoWatchers repo) ++ "\t" +++    "forks: " ++ (show $ Github.repoForks repo)++formatDate = show . Github.fromGithubDate
+ samples/Repos/Watching/ListWatched.hs view
@@ -0,0 +1,22 @@+module ListWatched where++import qualified Github.Repos.Watching as Github+import Data.List (intercalate)++main = do+  possibleRepos <- Github.reposWatchedBy "mike-burns"+  putStrLn $ either (("Error: "++) . show)+                    (intercalate "\n\n" . map formatRepo)+                    possibleRepos++formatRepo repo =+  (Github.repoName repo) ++ "\t" +++    (Github.repoDescription repo) ++ "\n" +++    (Github.repoHtmlUrl repo) ++ "\n" +++    (Github.repoCloneUrl repo) ++ "\t" +++    (formatDate $ Github.repoUpdatedAt repo) ++ "\n" +++    "language: " ++ (Github.repoLanguage repo) ++ "\t" +++    "watchers: " ++ (show $ Github.repoWatchers repo) ++ "\t" +++    "forks: " ++ (show $ Github.repoForks repo)++formatDate = show . Github.fromGithubDate
+ samples/Repos/Watching/ListWatchers.hs view
@@ -0,0 +1,14 @@+module ListWatchers where++import qualified Github.Repos.Watching as Github+import Data.List (intercalate)++main = do+  possibleWatchers <- Github.watchersFor "thoughtbot" "paperclip"+  putStrLn $ either (("Error: "++) . show)+                    (intercalate "\n" . map formatWatcher)+                    possibleWatchers++formatWatcher :: Github.GithubUser -> String+formatWatcher user =+  (Github.githubUserLogin user) ++ " (" ++ (Github.githubUserUrl user) ++ ")"
+ samples/Users/Followers/ListFollowers.hs view
@@ -0,0 +1,12 @@+module ListFollowers where++import qualified Github.Users.Followers as Github+import Data.List (intercalate)++main = do+  possibleUsers <- Github.usersFollowing "mike-burns"+  putStrLn $ either (("Error: "++) . show)+                    (intercalate "\n" . map formatUser)+                    possibleUsers++formatUser = Github.githubUserLogin
+ samples/Users/Followers/ListFollowing.hs view
@@ -0,0 +1,13 @@+module ListFollowing where++import qualified Github.Users.Followers as Github+import Data.List (intercalate)++main = do+  possibleUsers <- Github.usersFollowedBy "mike-burns"+  putStrLn $ either (("Error: "++) . show)+                    (intercalate "\n" . map formatUser)+                    possibleUsers++formatUser = Github.githubUserLogin+
+ samples/Users/ShowUser.hs view
@@ -0,0 +1,35 @@+module ShowUser where++import qualified Github.Users as Github+import Data.Maybe (fromMaybe)++main = do+  possibleUser <- Github.userInfoFor "mike-burns"+  putStrLn $ either (("Error: "++) . show) formatUser possibleUser++formatUser user =+  (formatName userName login) ++ "\t" ++ (fromMaybe "" company) ++ "\t" +++    (fromMaybe "" location) ++ "\n" +++    (fromMaybe "" blog) ++ "\t" ++ "<" ++ email ++ ">" ++ "\n" +++    htmlUrl ++ "\t" ++ (formatDate createdAt) ++ "\n" +++    "hireable: " ++ (formatHireable isHireable) ++ "\n\n" +++    (fromMaybe "" bio)+  where+    userName = Github.detailedUserName user+    login = Github.detailedUserLogin user+    company = Github.detailedUserCompany user+    location = Github.detailedUserLocation user+    blog = Github.detailedUserBlog user+    email = Github.detailedUserEmail user +    htmlUrl = Github.detailedUserHtmlUrl user+    createdAt = Github.detailedUserCreatedAt user+    isHireable = Github.detailedUserHireable user+    bio = Github.detailedUserBio user++formatName Nothing login = login+formatName (Just name) login = name ++ "(" ++ login ++ ")"++formatHireable True = "yes"+formatHireable False = "no"++formatDate = show . Github.fromGithubDate