{"action":"created","comment":{"url":"https://api.github.com/repos/haskell/cabal/pulls/comments/27778189","id":27778189,"diff_hunk":"@@ -0,0 +1,106 @@\n+module Distribution.Utils.Glob.Match where\n+\n+import Control.Monad\n+    ( (>=>) )\n+import Data.Maybe\n+    ( listToMaybe )\n+import Data.List\n+    ( stripPrefix )\n+import Distribution.Utils.Glob.Type\n+\n+isMatch :: Glob -> FilePath -> Bool\n+isMatch (Glob realGlob) fp = realIsMatch realGlob fp\n+isMatch (NoGlob fp') fp = fp' == fp\n+\n+realIsMatch :: RealGlob -> FilePath -> Bool\n+realIsMatch (RealGlob parts) fp = isMatch' True parts (toSegments fp)\n+\n+toSegments :: FilePath -> [String]\n+toSegments = filter (not . null) . splitOn '/'\n+\n+-- Not quite the same as the function from Data.List.Split, but this allows\n+-- for a simpler implementation\n+splitOn :: Eq a => a -> [a] -> [[a]]\n+splitOn _ [] = []\n+splitOn splitter list =\n+  let (next, rest) = span (/= splitter) list\n+  in  next : splitOn splitter (drop 1 rest)\n+\n+-- | Given:\n+-- * A Bool which records whether we are at the beginning of the current\n+-- segment\n+-- * A list of GlobParts\n+-- * A list of path segments in a file path\n+-- Return whether the glob parts list matches the file path.\n+isMatch' :: Bool -> [GlobPart] -> [String] -> Bool\n+isMatch' _ (Literal l : parts) (seg : segs) =\n+  case stripPrefix l seg of\n+    Just seg' -> isMatch' False parts (seg' : segs)\n+    Nothing -> False\n+isMatch' _ (PathSeparator : parts) (seg : segs)\n+  | seg == \"\" = isMatch' True parts segs\n+  | otherwise = False\n+isMatch' _ (CharList cs : parts) ((h:tl) : segs) =\n+  if charListIsMatch cs h\n+    then isMatch' False parts (tl : segs)\n+    else False\n+isMatch' _ (CharListComplement cs : parts) ((h:tl) : segs) =\n+  if charListIsMatch cs h\n+    then False\n+    else isMatch' False parts (tl : segs)\n+isMatch' startSegment (WildOne : parts) ((h:tl) : segs)\n+  | startSegment && h == '.' = False\n+  | otherwise = isMatch' False parts (tl : segs)\n+isMatch' startSegment (WildMany : parts) segs\n+  | startSegment && (listToMaybe >=> listToMaybe) segs == Just '.' = False\n+  | otherwise =\n+    case segs of\n+      first : rest ->\n+        let candidates = map (:rest) (iterateWhile drop1 first)\n+        in  any (isMatch' False parts) candidates\n+      [] ->\n+        isMatch' startSegment parts segs\n+isMatch' startSegment (WildManyRecursive : parts) segs\n+   | startSegment && (listToMaybe >=> listToMaybe) segs == Just '.' = False\n+   | otherwise =\n+     anyCandidates || handlePathSep\n+     where\n+     anyCandidates =\n+       any (\\(start, segs') -> isMatch' start parts segs') candidates\n+     candidates = iterateWhile (drop1' . snd) (False, segs)\n+     handlePathSep =\n+       case parts of\n+         PathSeparator : parts' -> isMatch' startSegment parts' segs\n+         _ -> False\n+\n+isMatch' startSegment (Choice gs : parts) segs =\n+  any (\\g -> isMatch' startSegment (g ++ parts) segs) gs\n+isMatch' _ [] [\"\"] = True\n+isMatch' _ _ _ = False\n+\n+charListIsMatch :: [CharListPart] -> Char -> Bool\n+charListIsMatch parts c = any (matches c) parts\n+  where\n+  matches x (CharLiteral y) = x == y\n+  matches x (Range start end) = start <= x && x <= end\n+\n+-- | A safe version of 'tail'.","path":"Cabal/Distribution/Utils/Glob/Match.hs","position":87,"original_position":87,"commit_id":"2bb20faaaa9315e39499292617c2342dd53262c7","original_commit_id":"2bb20faaaa9315e39499292617c2342dd53262c7","user":{"login":"23Skidoo","id":47439,"avatar_url":"https://avatars.githubusercontent.com/u/47439?v=3","gravatar_id":"","url":"https://api.github.com/users/23Skidoo","html_url":"https://github.com/23Skidoo","followers_url":"https://api.github.com/users/23Skidoo/followers","following_url":"https://api.github.com/users/23Skidoo/following{/other_user}","gists_url":"https://api.github.com/users/23Skidoo/gists{/gist_id}","starred_url":"https://api.github.com/users/23Skidoo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/23Skidoo/subscriptions","organizations_url":"https://api.github.com/users/23Skidoo/orgs","repos_url":"https://api.github.com/users/23Skidoo/repos","events_url":"https://api.github.com/users/23Skidoo/events{/privacy}","received_events_url":"https://api.github.com/users/23Skidoo/received_events","type":"User","site_admin":false},"body":"This is `tailMay` from the `safe` library. Since we can't add a dependency on `safe`, let's rename it to `tailMay` and move to `Distribution.Simple.Utils`.","created_at":"2015-04-05T15:43:21Z","updated_at":"2015-04-05T15:43:21Z","html_url":"https://github.com/haskell/cabal/pull/2522#discussion_r27778189","pull_request_url":"https://api.github.com/repos/haskell/cabal/pulls/2522","_links":{"self":{"href":"https://api.github.com/repos/haskell/cabal/pulls/comments/27778189"},"html":{"href":"https://github.com/haskell/cabal/pull/2522#discussion_r27778189"},"pull_request":{"href":"https://api.github.com/repos/haskell/cabal/pulls/2522"}}},"pull_request":{"url":"https://api.github.com/repos/haskell/cabal/pulls/2522","id":32638469,"html_url":"https://github.com/haskell/cabal/pull/2522","diff_url":"https://github.com/haskell/cabal/pull/2522.diff","patch_url":"https://github.com/haskell/cabal/pull/2522.patch","issue_url":"https://api.github.com/repos/haskell/cabal/issues/2522","number":2522,"state":"open","locked":false,"title":"Implement bash (with globstar) style globbing","user":{"login":"hdgarrood","id":1270186,"avatar_url":"https://avatars.githubusercontent.com/u/1270186?v=3","gravatar_id":"","url":"https://api.github.com/users/hdgarrood","html_url":"https://github.com/hdgarrood","followers_url":"https://api.github.com/users/hdgarrood/followers","following_url":"https://api.github.com/users/hdgarrood/following{/other_user}","gists_url":"https://api.github.com/users/hdgarrood/gists{/gist_id}","starred_url":"https://api.github.com/users/hdgarrood/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hdgarrood/subscriptions","organizations_url":"https://api.github.com/users/hdgarrood/orgs","repos_url":"https://api.github.com/users/hdgarrood/repos","events_url":"https://api.github.com/users/hdgarrood/events{/privacy}","received_events_url":"https://api.github.com/users/hdgarrood/received_events","type":"User","site_admin":false},"body":"Fixes #784, resolves #713, subsumes #1343, #1344. Picks up where #1975 left off.\r\n\r\nImplement a reduced form of GNU bash style globbing. The supported\r\nfeatures should account for 99% of use cases.\r\n\r\nStill to do: minimum cabal-version constraint. This seems to be\r\nnecessary because, for example, this commit changes the meaning of *.js,\r\nwhich previously would not have matched jquery.cookie.js, and now does.","created_at":"2015-04-04T19:39:17Z","updated_at":"2015-04-05T15:43:21Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d3fd0de36165a5cdcfdb87e151993ff42179161f","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/haskell/cabal/pulls/2522/commits","review_comments_url":"https://api.github.com/repos/haskell/cabal/pulls/2522/comments","review_comment_url":"https://api.github.com/repos/haskell/cabal/pulls/comments{/number}","comments_url":"https://api.github.com/repos/haskell/cabal/issues/2522/comments","statuses_url":"https://api.github.com/repos/haskell/cabal/statuses/2bb20faaaa9315e39499292617c2342dd53262c7","head":{"label":"hdgarrood:bash-globbing","ref":"bash-globbing","sha":"2bb20faaaa9315e39499292617c2342dd53262c7","user":{"login":"hdgarrood","id":1270186,"avatar_url":"https://avatars.githubusercontent.com/u/1270186?v=3","gravatar_id":"","url":"https://api.github.com/users/hdgarrood","html_url":"https://github.com/hdgarrood","followers_url":"https://api.github.com/users/hdgarrood/followers","following_url":"https://api.github.com/users/hdgarrood/following{/other_user}","gists_url":"https://api.github.com/users/hdgarrood/gists{/gist_id}","starred_url":"https://api.github.com/users/hdgarrood/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hdgarrood/subscriptions","organizations_url":"https://api.github.com/users/hdgarrood/orgs","repos_url":"https://api.github.com/users/hdgarrood/repos","events_url":"https://api.github.com/users/hdgarrood/events{/privacy}","received_events_url":"https://api.github.com/users/hdgarrood/received_events","type":"User","site_admin":false},"repo":{"id":10203624,"name":"cabal","full_name":"hdgarrood/cabal","owner":{"login":"hdgarrood","id":1270186,"avatar_url":"https://avatars.githubusercontent.com/u/1270186?v=3","gravatar_id":"","url":"https://api.github.com/users/hdgarrood","html_url":"https://github.com/hdgarrood","followers_url":"https://api.github.com/users/hdgarrood/followers","following_url":"https://api.github.com/users/hdgarrood/following{/other_user}","gists_url":"https://api.github.com/users/hdgarrood/gists{/gist_id}","starred_url":"https://api.github.com/users/hdgarrood/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hdgarrood/subscriptions","organizations_url":"https://api.github.com/users/hdgarrood/orgs","repos_url":"https://api.github.com/users/hdgarrood/repos","events_url":"https://api.github.com/users/hdgarrood/events{/privacy}","received_events_url":"https://api.github.com/users/hdgarrood/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/hdgarrood/cabal","description":"Official upstream development repository for Cabal and cabal-install","fork":true,"url":"https://api.github.com/repos/hdgarrood/cabal","forks_url":"https://api.github.com/repos/hdgarrood/cabal/forks","keys_url":"https://api.github.com/repos/hdgarrood/cabal/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hdgarrood/cabal/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hdgarrood/cabal/teams","hooks_url":"https://api.github.com/repos/hdgarrood/cabal/hooks","issue_events_url":"https://api.github.com/repos/hdgarrood/cabal/issues/events{/number}","events_url":"https://api.github.com/repos/hdgarrood/cabal/events","assignees_url":"https://api.github.com/repos/hdgarrood/cabal/assignees{/user}","branches_url":"https://api.github.com/repos/hdgarrood/cabal/branches{/branch}","tags_url":"https://api.github.com/repos/hdgarrood/cabal/tags","blobs_url":"https://api.github.com/repos/hdgarrood/cabal/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hdgarrood/cabal/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hdgarrood/cabal/git/refs{/sha}","trees_url":"https://api.github.com/repos/hdgarrood/cabal/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hdgarrood/cabal/statuses/{sha}","languages_url":"https://api.github.com/repos/hdgarrood/cabal/languages","stargazers_url":"https://api.github.com/repos/hdgarrood/cabal/stargazers","contributors_url":"https://api.github.com/repos/hdgarrood/cabal/contributors","subscribers_url":"https://api.github.com/repos/hdgarrood/cabal/subscribers","subscription_url":"https://api.github.com/repos/hdgarrood/cabal/subscription","commits_url":"https://api.github.com/repos/hdgarrood/cabal/commits{/sha}","git_commits_url":"https://api.github.com/repos/hdgarrood/cabal/git/commits{/sha}","comments_url":"https://api.github.com/repos/hdgarrood/cabal/comments{/number}","issue_comment_url":"https://api.github.com/repos/hdgarrood/cabal/issues/comments{/number}","contents_url":"https://api.github.com/repos/hdgarrood/cabal/contents/{+path}","compare_url":"https://api.github.com/repos/hdgarrood/cabal/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hdgarrood/cabal/merges","archive_url":"https://api.github.com/repos/hdgarrood/cabal/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hdgarrood/cabal/downloads","issues_url":"https://api.github.com/repos/hdgarrood/cabal/issues{/number}","pulls_url":"https://api.github.com/repos/hdgarrood/cabal/pulls{/number}","milestones_url":"https://api.github.com/repos/hdgarrood/cabal/milestones{/number}","notifications_url":"https://api.github.com/repos/hdgarrood/cabal/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hdgarrood/cabal/labels{/name}","releases_url":"https://api.github.com/repos/hdgarrood/cabal/releases{/id}","created_at":"2013-05-21T19:25:14Z","updated_at":"2015-04-04T22:57:25Z","pushed_at":"2015-04-05T00:25:29Z","git_url":"git://github.com/hdgarrood/cabal.git","ssh_url":"git@github.com:hdgarrood/cabal.git","clone_url":"https://github.com/hdgarrood/cabal.git","svn_url":"https://github.com/hdgarrood/cabal","homepage":"http://haskell.org/cabal","size":25271,"stargazers_count":0,"watchers_count":0,"language":"Haskell","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"haskell:master","ref":"master","sha":"5574dfff89a2dba18b2ce1c799803fbaf3eca82c","user":{"login":"haskell","id":450574,"avatar_url":"https://avatars.githubusercontent.com/u/450574?v=3","gravatar_id":"","url":"https://api.github.com/users/haskell","html_url":"https://github.com/haskell","followers_url":"https://api.github.com/users/haskell/followers","following_url":"https://api.github.com/users/haskell/following{/other_user}","gists_url":"https://api.github.com/users/haskell/gists{/gist_id}","starred_url":"https://api.github.com/users/haskell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/haskell/subscriptions","organizations_url":"https://api.github.com/users/haskell/orgs","repos_url":"https://api.github.com/users/haskell/repos","events_url":"https://api.github.com/users/haskell/events{/privacy}","received_events_url":"https://api.github.com/users/haskell/received_events","type":"Organization","site_admin":false},"repo":{"id":3728161,"name":"cabal","full_name":"haskell/cabal","owner":{"login":"haskell","id":450574,"avatar_url":"https://avatars.githubusercontent.com/u/450574?v=3","gravatar_id":"","url":"https://api.github.com/users/haskell","html_url":"https://github.com/haskell","followers_url":"https://api.github.com/users/haskell/followers","following_url":"https://api.github.com/users/haskell/following{/other_user}","gists_url":"https://api.github.com/users/haskell/gists{/gist_id}","starred_url":"https://api.github.com/users/haskell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/haskell/subscriptions","organizations_url":"https://api.github.com/users/haskell/orgs","repos_url":"https://api.github.com/users/haskell/repos","events_url":"https://api.github.com/users/haskell/events{/privacy}","received_events_url":"https://api.github.com/users/haskell/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/haskell/cabal","description":"Official upstream development repository for Cabal and cabal-install","fork":false,"url":"https://api.github.com/repos/haskell/cabal","forks_url":"https://api.github.com/repos/haskell/cabal/forks","keys_url":"https://api.github.com/repos/haskell/cabal/keys{/key_id}","collaborators_url":"https://api.github.com/repos/haskell/cabal/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/haskell/cabal/teams","hooks_url":"https://api.github.com/repos/haskell/cabal/hooks","issue_events_url":"https://api.github.com/repos/haskell/cabal/issues/events{/number}","events_url":"https://api.github.com/repos/haskell/cabal/events","assignees_url":"https://api.github.com/repos/haskell/cabal/assignees{/user}","branches_url":"https://api.github.com/repos/haskell/cabal/branches{/branch}","tags_url":"https://api.github.com/repos/haskell/cabal/tags","blobs_url":"https://api.github.com/repos/haskell/cabal/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/haskell/cabal/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/haskell/cabal/git/refs{/sha}","trees_url":"https://api.github.com/repos/haskell/cabal/git/trees{/sha}","statuses_url":"https://api.github.com/repos/haskell/cabal/statuses/{sha}","languages_url":"https://api.github.com/repos/haskell/cabal/languages","stargazers_url":"https://api.github.com/repos/haskell/cabal/stargazers","contributors_url":"https://api.github.com/repos/haskell/cabal/contributors","subscribers_url":"https://api.github.com/repos/haskell/cabal/subscribers","subscription_url":"https://api.github.com/repos/haskell/cabal/subscription","commits_url":"https://api.github.com/repos/haskell/cabal/commits{/sha}","git_commits_url":"https://api.github.com/repos/haskell/cabal/git/commits{/sha}","comments_url":"https://api.github.com/repos/haskell/cabal/comments{/number}","issue_comment_url":"https://api.github.com/repos/haskell/cabal/issues/comments{/number}","contents_url":"https://api.github.com/repos/haskell/cabal/contents/{+path}","compare_url":"https://api.github.com/repos/haskell/cabal/compare/{base}...{head}","merges_url":"https://api.github.com/repos/haskell/cabal/merges","archive_url":"https://api.github.com/repos/haskell/cabal/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/haskell/cabal/downloads","issues_url":"https://api.github.com/repos/haskell/cabal/issues{/number}","pulls_url":"https://api.github.com/repos/haskell/cabal/pulls{/number}","milestones_url":"https://api.github.com/repos/haskell/cabal/milestones{/number}","notifications_url":"https://api.github.com/repos/haskell/cabal/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/haskell/cabal/labels{/name}","releases_url":"https://api.github.com/repos/haskell/cabal/releases{/id}","created_at":"2012-03-15T12:53:38Z","updated_at":"2015-04-05T12:06:57Z","pushed_at":"2015-04-05T14:01:35Z","git_url":"git://github.com/haskell/cabal.git","ssh_url":"git@github.com:haskell/cabal.git","clone_url":"https://github.com/haskell/cabal.git","svn_url":"https://github.com/haskell/cabal","homepage":"http://haskell.org/cabal","size":34771,"stargazers_count":461,"watchers_count":461,"language":"Haskell","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":240,"mirror_url":null,"open_issues_count":627,"forks":240,"open_issues":627,"watchers":461,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/haskell/cabal/pulls/2522"},"html":{"href":"https://github.com/haskell/cabal/pull/2522"},"issue":{"href":"https://api.github.com/repos/haskell/cabal/issues/2522"},"comments":{"href":"https://api.github.com/repos/haskell/cabal/issues/2522/comments"},"review_comments":{"href":"https://api.github.com/repos/haskell/cabal/pulls/2522/comments"},"review_comment":{"href":"https://api.github.com/repos/haskell/cabal/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/haskell/cabal/pulls/2522/commits"},"statuses":{"href":"https://api.github.com/repos/haskell/cabal/statuses/2bb20faaaa9315e39499292617c2342dd53262c7"}}}}