{"action":"created","comment":{"url":"https://api.github.com/repos/open-policy-agent/opa/pulls/comments/60104801","id":60104801,"diff_hunk":"@@ -0,0 +1,540 @@\n+// Copyright 2016 The OPA Authors.  All rights reserved.\n+// Use of this source code is governed by an Apache2\n+// license that can be found in the LICENSE file.\n+\n+package eval\n+\n+import \"testing\"\n+import \"fmt\"\n+import \"encoding/json\"\n+import \"reflect\"\n+import \"sort\"\n+\n+import \"github.com/open-policy-agent/opa/opalog\"\n+\n+func TestEvalRef(t *testing.T) {\n+\n+\tvar tests = []struct {\n+\t\tref      string\n+\t\texpected interface{}\n+\t}{\n+\t\t{\"c[i][j]\", `[\n+            {\"i\": 0, \"j\": \"x\"},\n+            {\"i\": 0, \"j\": \"y\"},\n+            {\"i\": 0, \"j\": \"z\"}\n+         ]`},\n+\t\t{\"c[i][j][k]\", `[\n+            {\"i\": 0, \"j\": \"x\", \"k\": 0},\n+            {\"i\": 0, \"j\": \"x\", \"k\": 1},\n+            {\"i\": 0, \"j\": \"x\", \"k\": 2},\n+            {\"i\": 0, \"j\": \"y\", \"k\": 0},\n+            {\"i\": 0, \"j\": \"y\", \"k\": 1},\n+            {\"i\": 0, \"j\": \"z\", \"k\": \"p\"},\n+            {\"i\": 0, \"j\": \"z\", \"k\": \"q\"}\n+        ]`},\n+\t\t{\"d[x][y]\", `[\n+            {\"x\": \"e\", \"y\": 0},\n+            {\"x\": \"e\", \"y\": 1}\n+        ]`},\n+\t\t{`c[i][\"x\"][k]`, `[\n+            {\"i\": 0, \"k\": 0},\n+            {\"i\": 0, \"k\": 1},\n+            {\"i\": 0, \"k\": 2}\n+        ]`},\n+\t\t{\"c[i][j][i]\", `[\n+            {\"i\": 0, \"j\": \"x\"},\n+            {\"i\": 0, \"j\": \"y\"}\n+        ]`},\n+\t\t{`c[i][\"deadbeef\"][k]`, nil},\n+\t\t{`c[999]`, nil},\n+\t}\n+\n+\tdata := loadSmallTestData()\n+\n+\tctx := &TopDownContext{\n+\t\tStore:    NewStorageFromJSONObject(data),\n+\t\tBindings: make(map[opalog.Var]opalog.Value),\n+\t}\n+\n+\tfor i, tc := range tests {\n+\n+\t\tswitch e := tc.expected.(type) {\n+\t\tcase nil:\n+\t\t\tvar tmp *TopDownContext\n+\t\t\terr := evalRef(ctx, parseRef(tc.ref), func(ctx *TopDownContext) error {\n+\t\t\t\ttmp = ctx\n+\t\t\t\treturn nil\n+\t\t\t})\n+\t\t\tif err != nil {\n+\t\t\t\tt.Errorf(\"Test case (%d): unexpected error: %v\", i+1, err)\n+\t\t\t\tcontinue\n+\t\t\t}\n+\t\t\tif tmp != nil {\n+\t\t\t\tt.Errorf(\"Test case (%d): expected no bindings (nil) but got: %v\", i+1, tmp)\n+\t\t\t}\n+\t\tcase string:\n+\t\t\texpected := loadExpectedBindings(e)\n+\t\t\terr := evalRef(ctx, parseRef(tc.ref), func(ctx *TopDownContext) error {\n+\t\t\t\tif len(expected) > 0 {\n+\t\t\t\t\tfor j, exp := range expected {\n+\t\t\t\t\t\tif reflect.DeepEqual(exp, ctx.Bindings) {\n+\t\t\t\t\t\t\ttmp := expected[:j]\n+\t\t\t\t\t\t\texpected = append(tmp, expected[j+1:]...)\n+\t\t\t\t\t\t\treturn nil\n+\t\t\t\t\t\t}\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t\t// If there was not a matching expected binding, treat this case as a failure.\n+\t\t\t\treturn fmt.Errorf(\"unexpected bindings: %v\", ctx.Bindings)\n+\t\t\t})\n+\t\t\tif err != nil {\n+\t\t\t\tt.Errorf(\"Test case %d: expected success but got error: %v\", i+1, err)\n+\t\t\t\tcontinue\n+\t\t\t}\n+\t\t\tif len(expected) > 0 {\n+\t\t\t\tt.Errorf(\"Test case %d: missing expected bindings: %v\", i+1, expected)\n+\t\t\t}\n+\t\t}\n+\n+\t}\n+}\n+\n+func TestEvalTerms(t *testing.T) {\n+\n+\ttests := []struct {\n+\t\trule     string\n+\t\texpected string\n+\t}{\n+\t\t{\"p[x] :- c[i][j][k] = x\", `[\n+            {\"i\": 0, \"j\": \"x\", \"k\": 0},\n+            {\"i\": 0, \"j\": \"x\", \"k\": 1},\n+            {\"i\": 0, \"j\": \"x\", \"k\": 2},\n+            {\"i\": 0, \"j\": \"y\", \"k\": 0},\n+            {\"i\": 0, \"j\": \"y\", \"k\": 1},\n+            {\"i\": 0, \"j\": \"z\", \"k\": \"p\"},\n+            {\"i\": 0, \"j\": \"z\", \"k\": \"q\"}\n+        ]`},\n+\t\t{\"p[x] :- d[x][y] = a[i]\", `[\n+            {\"x\": \"e\", \"y\": 0, \"i\": 0},\n+            {\"x\": \"e\", \"y\": 0, \"i\": 1},\n+            {\"x\": \"e\", \"y\": 0, \"i\": 2},\n+            {\"x\": \"e\", \"y\": 0, \"i\": 3},\n+            {\"x\": \"e\", \"y\": 1, \"i\": 0},\n+            {\"x\": \"e\", \"y\": 1, \"i\": 1},\n+            {\"x\": \"e\", \"y\": 1, \"i\": 2},\n+            {\"x\": \"e\", \"y\": 1, \"i\": 3}\n+        ]`},\n+\t\t{\"p[x] :- d[x][y] = z[i]\", `[]`},\n+\t}\n+\n+\tdata := loadSmallTestData()\n+\n+\tfor i, tc := range tests {\n+\n+\t\tctx := &TopDownContext{\n+\t\t\tRule:     parseRule(tc.rule),\n+\t\t\tStore:    NewStorageFromJSONObject(data),\n+\t\t\tBindings: make(map[opalog.Var]opalog.Value),\n+\t\t}\n+\n+\t\texpected := loadExpectedBindings(tc.expected)\n+\n+\t\terr := evalTerms(ctx, func(ctx *TopDownContext) error {\n+\t\t\tif len(expected) > 0 {\n+\t\t\t\tfor j, exp := range expected {\n+\t\t\t\t\tif reflect.DeepEqual(exp, ctx.Bindings) {\n+\t\t\t\t\t\ttmp := expected[:j]\n+\t\t\t\t\t\texpected = append(tmp, expected[j+1:]...)\n+\t\t\t\t\t\treturn nil\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\t// If there was not a matching expected binding, treat this case as a failure.\n+\t\t\treturn fmt.Errorf(\"unexpected bindings: %v\", ctx.Bindings)\n+\t\t})\n+\t\tif err != nil {\n+\t\t\tt.Errorf(\"Test case %d: expected success but got error: %v\", i+1, err)\n+\t\t\tcontinue\n+\t\t}\n+\t\tif len(expected) > 0 {\n+\t\t\tt.Errorf(\"Test case %d: missing expected bindings: %v\", i+1, expected)\n+\t\t}\n+\t}\n+}\n+\n+func TestPlugValue(t *testing.T) {\n+\n+\ta := opalog.Var(\"a\")\n+\tb := opalog.Var(\"b\")\n+\tc := opalog.Var(\"c\")\n+\tk := opalog.Var(\"k\")\n+\tv := opalog.Var(\"v\")\n+\tcs := parseTerm(\"[c]\").Value\n+\tks := parseTerm(`{k: \"world\"}`).Value\n+\tvs := parseTerm(`{\"hello\": v}`).Value\n+\thello := opalog.String(\"hello\")\n+\tworld := opalog.String(\"world\")\n+\n+\tctx1 := &TopDownContext{Bindings: make(Bindings)}\n+\tctx1 = ctx1.Bind(a, b)\n+\tctx1 = ctx1.Bind(b, cs)\n+\tctx1 = ctx1.Bind(c, ks)\n+\tctx1 = ctx1.Bind(k, hello)\n+\n+\tctx2 := &TopDownContext{Bindings: make(Bindings)}\n+\tctx2 = ctx2.Bind(a, b)\n+\tctx2 = ctx2.Bind(b, cs)\n+\tctx2 = ctx2.Bind(c, vs)\n+\tctx2 = ctx2.Bind(v, world)\n+\n+\texpected := parseTerm(`[{\"hello\": \"world\"}]`).Value\n+\n+\tr1 := plugValue(a, ctx1.Bindings)\n+\n+\tif !expected.Equal(r1) {\n+\t\tt.Errorf(\"Expected %v but got %v\", expected, r1)\n+\t\treturn\n+\t}\n+\n+\tr2 := plugValue(a, ctx2.Bindings)\n+\n+\tif !expected.Equal(r2) {\n+\t\tt.Errorf(\"Expected %v but got %v\", expected, r2)\n+\t}\n+}\n+\n+func TestTopDownScalarDoc(t *testing.T) {\n+\ttests := []struct {\n+\t\tnote     string\n+\t\trule     string\n+\t\texpected string\n+\t}{\n+\t\t{\"undefined\", \"p = null :- false\", \"\"}, // \"\" will be converted to Undefined\n+\t\t{\"null\", \"p = null :- true\", \"null\"},\n+\t\t{\"bool: true\", \"p = true :- true\", \"true\"},\n+\t\t{\"bool: false\", \"p = false :- true\", \"false\"},\n+\t\t{\"number: 3\", \"p = 3 :- true\", \"3\"},\n+\t\t{\"number: 3.0\", \"p = 3.0 :- true\", \"3.0\"},\n+\t\t{\"number: 66.66667\", \"p = 66.66667 :- true\", \"66.66667\"},\n+\t\t{`string: \"hello\"`, `p = \"hello\" :- true`, `\"hello\"`},\n+\t\t{`string: \"\"`, `p = \"\" :- true`, `\"\"`},\n+\t\t{\"array: [1,2,3,4]\", \"p = [1,2,3,4] :- true\", \"[1,2,3,4]\"},\n+\t\t{\"array: []\", \"p = [] :- true\", \"[]\"},\n+\t\t{`object/nested composites: {\"a\": [1], \"b\": [2], \"c\": [3]}`,\n+\t\t\t`p = {\"a\": [1], \"b\": [2], \"c\": [3]} :- true`,\n+\t\t\t`{\"a\": [1], \"b\": [2], \"c\": [3]}`},","path":"eval/topdown_test.go","position":225,"original_position":225,"commit_id":"881b2afef863db2f93728e81f605bcd52ccd50cb","original_commit_id":"881b2afef863db2f93728e81f605bcd52ccd50cb","user":{"login":"tim-styra","id":12769017,"avatar_url":"https://avatars.githubusercontent.com/u/12769017?v=3","gravatar_id":"","url":"https://api.github.com/users/tim-styra","html_url":"https://github.com/tim-styra","followers_url":"https://api.github.com/users/tim-styra/followers","following_url":"https://api.github.com/users/tim-styra/following{/other_user}","gists_url":"https://api.github.com/users/tim-styra/gists{/gist_id}","starred_url":"https://api.github.com/users/tim-styra/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tim-styra/subscriptions","organizations_url":"https://api.github.com/users/tim-styra/orgs","repos_url":"https://api.github.com/users/tim-styra/repos","events_url":"https://api.github.com/users/tim-styra/events{/privacy}","received_events_url":"https://api.github.com/users/tim-styra/received_events","type":"User","site_admin":false},"body":"Need a _set_ test?","created_at":"2016-04-18T18:00:58Z","updated_at":"2016-04-18T18:00:59Z","html_url":"https://github.com/open-policy-agent/opa/pull/26#discussion_r60104801","pull_request_url":"https://api.github.com/repos/open-policy-agent/opa/pulls/26","_links":{"self":{"href":"https://api.github.com/repos/open-policy-agent/opa/pulls/comments/60104801"},"html":{"href":"https://github.com/open-policy-agent/opa/pull/26#discussion_r60104801"},"pull_request":{"href":"https://api.github.com/repos/open-policy-agent/opa/pulls/26"}}},"pull_request":{"url":"https://api.github.com/repos/open-policy-agent/opa/pulls/26","id":66564445,"html_url":"https://github.com/open-policy-agent/opa/pull/26","diff_url":"https://github.com/open-policy-agent/opa/pull/26.diff","patch_url":"https://github.com/open-policy-agent/opa/pull/26.patch","issue_url":"https://api.github.com/repos/open-policy-agent/opa/issues/26","number":26,"state":"open","locked":false,"title":"Add beginning of top down evaluation","user":{"login":"tsandall","id":238885,"avatar_url":"https://avatars.githubusercontent.com/u/238885?v=3","gravatar_id":"","url":"https://api.github.com/users/tsandall","html_url":"https://github.com/tsandall","followers_url":"https://api.github.com/users/tsandall/followers","following_url":"https://api.github.com/users/tsandall/following{/other_user}","gists_url":"https://api.github.com/users/tsandall/gists{/gist_id}","starred_url":"https://api.github.com/users/tsandall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tsandall/subscriptions","organizations_url":"https://api.github.com/users/tsandall/orgs","repos_url":"https://api.github.com/users/tsandall/repos","events_url":"https://api.github.com/users/tsandall/events{/privacy}","received_events_url":"https://api.github.com/users/tsandall/received_events","type":"User","site_admin":false},"body":"See the commit message for what's included and what's not done yet.\r\n\r\nI felt like this was a good place to stop and review the current implementation. The missing pieces may trigger some refactoring but hopefully they will be mostly additive.","created_at":"2016-04-14T22:29:17Z","updated_at":"2016-04-18T18:00:59Z","closed_at":null,"merged_at":null,"merge_commit_sha":"286bc7653c928f1764f548a0b31b9347c4f03db4","assignee":{"login":"timothyhinrichs","id":10049579,"avatar_url":"https://avatars.githubusercontent.com/u/10049579?v=3","gravatar_id":"","url":"https://api.github.com/users/timothyhinrichs","html_url":"https://github.com/timothyhinrichs","followers_url":"https://api.github.com/users/timothyhinrichs/followers","following_url":"https://api.github.com/users/timothyhinrichs/following{/other_user}","gists_url":"https://api.github.com/users/timothyhinrichs/gists{/gist_id}","starred_url":"https://api.github.com/users/timothyhinrichs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/timothyhinrichs/subscriptions","organizations_url":"https://api.github.com/users/timothyhinrichs/orgs","repos_url":"https://api.github.com/users/timothyhinrichs/repos","events_url":"https://api.github.com/users/timothyhinrichs/events{/privacy}","received_events_url":"https://api.github.com/users/timothyhinrichs/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/open-policy-agent/opa/pulls/26/commits","review_comments_url":"https://api.github.com/repos/open-policy-agent/opa/pulls/26/comments","review_comment_url":"https://api.github.com/repos/open-policy-agent/opa/pulls/comments{/number}","comments_url":"https://api.github.com/repos/open-policy-agent/opa/issues/26/comments","statuses_url":"https://api.github.com/repos/open-policy-agent/opa/statuses/881b2afef863db2f93728e81f605bcd52ccd50cb","head":{"label":"tsandall:initial-topdown","ref":"initial-topdown","sha":"881b2afef863db2f93728e81f605bcd52ccd50cb","user":{"login":"tsandall","id":238885,"avatar_url":"https://avatars.githubusercontent.com/u/238885?v=3","gravatar_id":"","url":"https://api.github.com/users/tsandall","html_url":"https://github.com/tsandall","followers_url":"https://api.github.com/users/tsandall/followers","following_url":"https://api.github.com/users/tsandall/following{/other_user}","gists_url":"https://api.github.com/users/tsandall/gists{/gist_id}","starred_url":"https://api.github.com/users/tsandall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tsandall/subscriptions","organizations_url":"https://api.github.com/users/tsandall/orgs","repos_url":"https://api.github.com/users/tsandall/repos","events_url":"https://api.github.com/users/tsandall/events{/privacy}","received_events_url":"https://api.github.com/users/tsandall/received_events","type":"User","site_admin":false},"repo":{"id":51776679,"name":"opa","full_name":"tsandall/opa","owner":{"login":"tsandall","id":238885,"avatar_url":"https://avatars.githubusercontent.com/u/238885?v=3","gravatar_id":"","url":"https://api.github.com/users/tsandall","html_url":"https://github.com/tsandall","followers_url":"https://api.github.com/users/tsandall/followers","following_url":"https://api.github.com/users/tsandall/following{/other_user}","gists_url":"https://api.github.com/users/tsandall/gists{/gist_id}","starred_url":"https://api.github.com/users/tsandall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tsandall/subscriptions","organizations_url":"https://api.github.com/users/tsandall/orgs","repos_url":"https://api.github.com/users/tsandall/repos","events_url":"https://api.github.com/users/tsandall/events{/privacy}","received_events_url":"https://api.github.com/users/tsandall/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/tsandall/opa","description":"An open source project to policy enable any application.","fork":true,"url":"https://api.github.com/repos/tsandall/opa","forks_url":"https://api.github.com/repos/tsandall/opa/forks","keys_url":"https://api.github.com/repos/tsandall/opa/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tsandall/opa/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tsandall/opa/teams","hooks_url":"https://api.github.com/repos/tsandall/opa/hooks","issue_events_url":"https://api.github.com/repos/tsandall/opa/issues/events{/number}","events_url":"https://api.github.com/repos/tsandall/opa/events","assignees_url":"https://api.github.com/repos/tsandall/opa/assignees{/user}","branches_url":"https://api.github.com/repos/tsandall/opa/branches{/branch}","tags_url":"https://api.github.com/repos/tsandall/opa/tags","blobs_url":"https://api.github.com/repos/tsandall/opa/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tsandall/opa/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tsandall/opa/git/refs{/sha}","trees_url":"https://api.github.com/repos/tsandall/opa/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tsandall/opa/statuses/{sha}","languages_url":"https://api.github.com/repos/tsandall/opa/languages","stargazers_url":"https://api.github.com/repos/tsandall/opa/stargazers","contributors_url":"https://api.github.com/repos/tsandall/opa/contributors","subscribers_url":"https://api.github.com/repos/tsandall/opa/subscribers","subscription_url":"https://api.github.com/repos/tsandall/opa/subscription","commits_url":"https://api.github.com/repos/tsandall/opa/commits{/sha}","git_commits_url":"https://api.github.com/repos/tsandall/opa/git/commits{/sha}","comments_url":"https://api.github.com/repos/tsandall/opa/comments{/number}","issue_comment_url":"https://api.github.com/repos/tsandall/opa/issues/comments{/number}","contents_url":"https://api.github.com/repos/tsandall/opa/contents/{+path}","compare_url":"https://api.github.com/repos/tsandall/opa/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tsandall/opa/merges","archive_url":"https://api.github.com/repos/tsandall/opa/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tsandall/opa/downloads","issues_url":"https://api.github.com/repos/tsandall/opa/issues{/number}","pulls_url":"https://api.github.com/repos/tsandall/opa/pulls{/number}","milestones_url":"https://api.github.com/repos/tsandall/opa/milestones{/number}","notifications_url":"https://api.github.com/repos/tsandall/opa/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tsandall/opa/labels{/name}","releases_url":"https://api.github.com/repos/tsandall/opa/releases{/id}","deployments_url":"https://api.github.com/repos/tsandall/opa/deployments","created_at":"2016-02-15T18:37:20Z","updated_at":"2016-03-17T18:52:09Z","pushed_at":"2016-04-14T22:27:16Z","git_url":"git://github.com/tsandall/opa.git","ssh_url":"git@github.com:tsandall/opa.git","clone_url":"https://github.com/tsandall/opa.git","svn_url":"https://github.com/tsandall/opa","homepage":"","size":9065,"stargazers_count":0,"watchers_count":0,"language":"Go","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":"open-policy-agent:master","ref":"master","sha":"8f8280546336857858bb44f193bbf0134d74672d","user":{"login":"open-policy-agent","id":16468693,"avatar_url":"https://avatars.githubusercontent.com/u/16468693?v=3","gravatar_id":"","url":"https://api.github.com/users/open-policy-agent","html_url":"https://github.com/open-policy-agent","followers_url":"https://api.github.com/users/open-policy-agent/followers","following_url":"https://api.github.com/users/open-policy-agent/following{/other_user}","gists_url":"https://api.github.com/users/open-policy-agent/gists{/gist_id}","starred_url":"https://api.github.com/users/open-policy-agent/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/open-policy-agent/subscriptions","organizations_url":"https://api.github.com/users/open-policy-agent/orgs","repos_url":"https://api.github.com/users/open-policy-agent/repos","events_url":"https://api.github.com/users/open-policy-agent/events{/privacy}","received_events_url":"https://api.github.com/users/open-policy-agent/received_events","type":"Organization","site_admin":false},"repo":{"id":48714685,"name":"opa","full_name":"open-policy-agent/opa","owner":{"login":"open-policy-agent","id":16468693,"avatar_url":"https://avatars.githubusercontent.com/u/16468693?v=3","gravatar_id":"","url":"https://api.github.com/users/open-policy-agent","html_url":"https://github.com/open-policy-agent","followers_url":"https://api.github.com/users/open-policy-agent/followers","following_url":"https://api.github.com/users/open-policy-agent/following{/other_user}","gists_url":"https://api.github.com/users/open-policy-agent/gists{/gist_id}","starred_url":"https://api.github.com/users/open-policy-agent/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/open-policy-agent/subscriptions","organizations_url":"https://api.github.com/users/open-policy-agent/orgs","repos_url":"https://api.github.com/users/open-policy-agent/repos","events_url":"https://api.github.com/users/open-policy-agent/events{/privacy}","received_events_url":"https://api.github.com/users/open-policy-agent/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/open-policy-agent/opa","description":"An open source project to policy enable any application.","fork":false,"url":"https://api.github.com/repos/open-policy-agent/opa","forks_url":"https://api.github.com/repos/open-policy-agent/opa/forks","keys_url":"https://api.github.com/repos/open-policy-agent/opa/keys{/key_id}","collaborators_url":"https://api.github.com/repos/open-policy-agent/opa/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/open-policy-agent/opa/teams","hooks_url":"https://api.github.com/repos/open-policy-agent/opa/hooks","issue_events_url":"https://api.github.com/repos/open-policy-agent/opa/issues/events{/number}","events_url":"https://api.github.com/repos/open-policy-agent/opa/events","assignees_url":"https://api.github.com/repos/open-policy-agent/opa/assignees{/user}","branches_url":"https://api.github.com/repos/open-policy-agent/opa/branches{/branch}","tags_url":"https://api.github.com/repos/open-policy-agent/opa/tags","blobs_url":"https://api.github.com/repos/open-policy-agent/opa/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/open-policy-agent/opa/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/open-policy-agent/opa/git/refs{/sha}","trees_url":"https://api.github.com/repos/open-policy-agent/opa/git/trees{/sha}","statuses_url":"https://api.github.com/repos/open-policy-agent/opa/statuses/{sha}","languages_url":"https://api.github.com/repos/open-policy-agent/opa/languages","stargazers_url":"https://api.github.com/repos/open-policy-agent/opa/stargazers","contributors_url":"https://api.github.com/repos/open-policy-agent/opa/contributors","subscribers_url":"https://api.github.com/repos/open-policy-agent/opa/subscribers","subscription_url":"https://api.github.com/repos/open-policy-agent/opa/subscription","commits_url":"https://api.github.com/repos/open-policy-agent/opa/commits{/sha}","git_commits_url":"https://api.github.com/repos/open-policy-agent/opa/git/commits{/sha}","comments_url":"https://api.github.com/repos/open-policy-agent/opa/comments{/number}","issue_comment_url":"https://api.github.com/repos/open-policy-agent/opa/issues/comments{/number}","contents_url":"https://api.github.com/repos/open-policy-agent/opa/contents/{+path}","compare_url":"https://api.github.com/repos/open-policy-agent/opa/compare/{base}...{head}","merges_url":"https://api.github.com/repos/open-policy-agent/opa/merges","archive_url":"https://api.github.com/repos/open-policy-agent/opa/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/open-policy-agent/opa/downloads","issues_url":"https://api.github.com/repos/open-policy-agent/opa/issues{/number}","pulls_url":"https://api.github.com/repos/open-policy-agent/opa/pulls{/number}","milestones_url":"https://api.github.com/repos/open-policy-agent/opa/milestones{/number}","notifications_url":"https://api.github.com/repos/open-policy-agent/opa/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/open-policy-agent/opa/labels{/name}","releases_url":"https://api.github.com/repos/open-policy-agent/opa/releases{/id}","deployments_url":"https://api.github.com/repos/open-policy-agent/opa/deployments","created_at":"2015-12-28T22:08:25Z","updated_at":"2016-03-17T18:51:54Z","pushed_at":"2016-04-14T22:29:17Z","git_url":"git://github.com/open-policy-agent/opa.git","ssh_url":"git@github.com:open-policy-agent/opa.git","clone_url":"https://github.com/open-policy-agent/opa.git","svn_url":"https://github.com/open-policy-agent/opa","homepage":"","size":9051,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":1,"forks":2,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/open-policy-agent/opa/pulls/26"},"html":{"href":"https://github.com/open-policy-agent/opa/pull/26"},"issue":{"href":"https://api.github.com/repos/open-policy-agent/opa/issues/26"},"comments":{"href":"https://api.github.com/repos/open-policy-agent/opa/issues/26/comments"},"review_comments":{"href":"https://api.github.com/repos/open-policy-agent/opa/pulls/26/comments"},"review_comment":{"href":"https://api.github.com/repos/open-policy-agent/opa/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/open-policy-agent/opa/pulls/26/commits"},"statuses":{"href":"https://api.github.com/repos/open-policy-agent/opa/statuses/881b2afef863db2f93728e81f605bcd52ccd50cb"}}}}