GitHub PullRequestReviewCommentEvent at 2014-10-31 22:41:55
Repository: etcd
Actor: unihorn
Payload: {"action":"created","comment":{"url":"https://api.github.com/repos/coreos/etcd/pulls/comments/19697616","id":19697616,"diff_hunk":"@@ -379,8 +379,380 @@ func testNonleadersElectionTimeoutNonconflict(t *testing.T, state StateType) {\n \t}\n }\n \n+// TestLeaderStartReplication tests that when receiving client requests,\n+// the leader appends the command to its log as a new entry, then issues\n+// AppendEntries RPCs in parallel to each of the other servers to replicate\n+// the entry. Also, when sending an AppendEntries RPC, the leader includes\n+// the index and term of the entry in its log that immediately precedes\n+// the new entries.\n+// Also, it writes the new entry into stable storage.\n+// Reference: section 5.3\n+func TestLeaderStartReplication(t *testing.T) {\n+\tr := newRaft(1, []uint64{1, 2, 3}, 10, 1)\n+\tr.becomeCandidate()\n+\tr.becomeLeader()\n+\tcommitPendingEntries(r)\n+\tli := r.raftLog.lastIndex()\n+\n+\tents := []pb.Entry{{Data: []byte(\"uno\")}}\n+\tr.Step(pb.Message{From: 1, To: 1, Type: pb.MsgProp, Entries: ents})\n+\n+\tif g := r.raftLog.lastIndex(); g != li+1 {\n+\t\tt.Errorf(\"lastIndex = %d, want %d\", g, li+1)\n+\t}\n+\tif g := r.raftLog.committed; g != li {\n+\t\tt.Errorf(\"committed = %d, want %d\", g, li)\n+\t}\n+\tmsgs := r.readMessages()\n+\tsort.Sort(messageSlice(msgs))\n+\twents := []pb.Entry{{Index: li + 1, Term: 1, Data: []byte(\"uno\")}}\n+\twmsgs := []pb.Message{\n+\t\t{From: 1, To: 2, Term: 1, Type: pb.MsgApp, Index: li, LogTerm: 1, Entries: wents, Commit: li},\n+\t\t{From: 1, To: 3, Term: 1, Type: pb.MsgApp, Index: li, LogTerm: 1, Entries: wents, Commit: li},\n+\t}\n+\tif !reflect.DeepEqual(msgs, wmsgs) {\n+\t\tt.Errorf(\"msgs = %+v, want %+v\", msgs, wmsgs)\n+\t}\n+\tif g := r.raftLog.unstableEnts(); !reflect.DeepEqual(g, wents) {\n+\t\tt.Errorf(\"ents = %+v, want %+v\", g, wents)\n+\t}\n+}\n+\n+// TestLeaderCommitEntry tests that when the entry has been safely replicated,\n+// the leader applies the entry to its state machine and returns the result\n+// of that execution to the client.\n+// Also, the leader keeps track of the highest index it knows to be committed,\n+// and it includes that index in future AppendEntries RPCs so that the other\n+// servers eventually find out.\n+// Reference: section 5.3\n+func TestLeaderCommitEntry(t *testing.T) {\n+\tr := newRaft(1, []uint64{1, 2, 3}, 10, 1)\n+\tr.becomeCandidate()\n+\tr.becomeLeader()\n+\tcommitPendingEntries(r)\n+\tli := r.raftLog.lastIndex()\n+\tr.Step(pb.Message{From: 1, To: 1, Type: pb.MsgProp, Entries: []pb.Entry{{Data: []byte(\"abc\")}}})\n+\n+\tfor _, m := range r.readMessages() {\n+\t\tr.Step(genMsgAppResp(m))\n+\t}\n+\n+\tif g := r.raftLog.committed; g != li+1 {\n+\t\tt.Errorf(\"committed = %d, want %d\", g, li+1)\n+\t}\n+\twents := []pb.Entry{{Index: li + 1, Term: 1, Data: []byte(\"abc\")}}\n+\tif g := r.raftLog.nextEnts(); !reflect.DeepEqual(g, wents) {\n+\t\tt.Errorf(\"nextEnts = %+v, want %+v\", g, wents)\n+\t}\n+\tmsgs := r.readMessages()\n+\tsort.Sort(messageSlice(msgs))\n+\tfor i, m := range msgs {\n+\t\tif w := uint64(i + 2); m.To != w {\n+\t\t\tt.Errorf(\"to = %x, want %x\", m.To, w)\n+\t\t}\n+\t\tif m.Type != pb.MsgApp {\n+\t\t\tt.Errorf(\"type = %s, want %s\", m.Type, pb.MsgApp)\n+\t\t}\n+\t\tif m.Commit != li+1 {\n+\t\t\tt.Errorf(\"commit = %d, want %d\", m.Commit, li+1)\n+\t\t}\n+\t}\n+}\n+\n+// TestLeaderAcknowledgeCommit tests that a log entry is committed once the\n+// leader that created the entry has replicated it on a majority of the servers.\n+// Reference: section 5.3\n+func TestLeaderAcknowledgeCommit(t *testing.T) {\n+\ttests := []struct {\n+\t\tsize int\n+\t\tresp map[uint64]bool\n+\t\twack bool\n+\t}{\n+\t\t{1, nil, true},\n+\t\t{3, nil, false},\n+\t\t{3, map[uint64]bool{2: true}, true},\n+\t\t{3, map[uint64]bool{2: true, 3: true}, true},\n+\t\t{5, nil, false},\n+\t\t{5, map[uint64]bool{2: true}, false},\n+\t\t{5, map[uint64]bool{2: true, 3: true}, true},\n+\t\t{5, map[uint64]bool{2: true, 3: true, 4: true}, true},\n+\t\t{5, map[uint64]bool{2: true, 3: true, 4: true, 5: true}, true},\n+\t}\n+\tfor i, tt := range tests {\n+\t\tr := newRaft(1, idsBySize(tt.size), 10, 1)\n+\t\tr.becomeCandidate()\n+\t\tr.becomeLeader()\n+\t\tcommitPendingEntries(r)\n+\t\tli := r.raftLog.lastIndex()\n+\t\tr.Step(pb.Message{From: 1, To: 1, Type: pb.MsgProp, Entries: []pb.Entry{{Data: []byte(\"abc\")}}})\n+\n+\t\tfor _, m := range r.readMessages() {\n+\t\t\tif tt.resp[m.To] {\n+\t\t\t\tr.Step(genMsgAppResp(m))\n+\t\t\t}\n+\t\t}\n+\n+\t\tif g := r.raftLog.committed > li; g != tt.wack {\n+\t\t\tt.Errorf(\"#%d: ack commit = %v, want %v\", i, g, tt.wack)\n+\t\t}\n+\t}\n+}\n+\n+// TestLeaderCommitPrecedingEntries tests that when leader commits a log entry,\n+// it also commits all preceding entries in the leader’s log, including\n+// entries created by previous leaders.\n+// Also, it applies the entry to its local state machine (in log order).\n+// Reference: section 5.3\n+func TestLeaderCommitPrecedingEntries(t *testing.T) {\n+\ttests := [][]pb.Entry{\n+\t\t{},\n+\t\t{{Term: 2, Index: 1}},\n+\t\t{{Term: 1, Index: 1}, {Term: 2, Index: 2}},\n+\t\t{{Term: 1, Index: 1}},\n+\t}\n+\tfor i, tt := range tests {\n+\t\tr := newRaft(1, []uint64{1, 2, 3}, 10, 1)\n+\t\tr.loadEnts(append([]pb.Entry{{}}, tt...))\n+\t\tr.loadState(pb.HardState{Term: 2})\n+\t\tr.becomeCandidate()\n+\t\t// this implies to append a nop entry with the latest term\n+\t\tr.becomeLeader()\n+\t\tr.bcastAppend()\n+\n+\t\tfor _, m := range r.readMessages() {\n+\t\t\tr.Step(genMsgAppResp(m))\n+\t\t}\n+\n+\t\twents := append(tt, pb.Entry{Term: 3, Index: uint64(len(tt) + 1)})\n+\t\tif g := r.raftLog.nextEnts(); !reflect.DeepEqual(g, wents) {\n+\t\t\tt.Errorf(\"#%d: ents = %+v, want %+v\", i, g, wents)\n+\t\t}\n+\t}\n+}\n+\n+// TestFollowerCommitEntry tests that once a follower learns that a log entry\n+// is committed, it applies the entry to its local state machine (in log order).\n+// Reference: section 5.3\n+func TestFollowerCommitEntry(t *testing.T) {\n+\ttests := [][]pb.Entry{\n+\t\t{\n+\t\t\t{Term: 1, Index: 1, Data: []byte(\"abc\")},\n+\t\t},\n+\t\t{\n+\t\t\t{Term: 1, Index: 1, Data: []byte(\"abc\")},\n+\t\t\t{Term: 1, Index: 2, Data: []byte(\"def\")},\n+\t\t},\n+\t\t{\n+\t\t\t{Term: 1, Index: 1, Data: []byte(\"def\")},\n+\t\t\t{Term: 1, Index: 2, Data: []byte(\"abc\")},\n+\t\t},\n+\t}\n+\tfor i, tt := range tests {\n+\t\tr := newRaft(1, []uint64{1, 2, 3}, 10, 1)\n+\t\tr.becomeFollower(1, 2)\n+\n+\t\tr.Step(pb.Message{From: 2, To: 1, Type: pb.MsgApp, Term: 1, Entries: tt, Commit: uint64(len(tt))})","path":"raft/raft_paper_test.go","position":176,"original_position":176,"commit_id":"517036134a9fc55401266cad0e4a9490aa4a8c76","original_commit_id":"517036134a9fc55401266cad0e4a9490aa4a8c76","user":{"login":"unihorn","id":2976232,"avatar_url":"https://avatars.githubusercontent.com/u/2976232?v=2","gravatar_id":"","url":"https://api.github.com/users/unihorn","html_url":"https://github.com/unihorn","followers_url":"https://api.github.com/users/unihorn/followers","following_url":"https://api.github.com/users/unihorn/following{/other_user}","gists_url":"https://api.github.com/users/unihorn/gists{/gist_id}","starred_url":"https://api.github.com/users/unihorn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/unihorn/subscriptions","organizations_url":"https://api.github.com/users/unihorn/orgs","repos_url":"https://api.github.com/users/unihorn/repos","events_url":"https://api.github.com/users/unihorn/events{/privacy}","received_events_url":"https://api.github.com/users/unihorn/received_events","type":"User","site_admin":false},"body":"added","created_at":"2014-10-31T22:41:55Z","updated_at":"2014-10-31T22:41:55Z","html_url":"https://github.com/coreos/etcd/pull/1528#discussion_r19697616","pull_request_url":"https://api.github.com/repos/coreos/etcd/pulls/1528","_links":{"self":{"href":"https://api.github.com/repos/coreos/etcd/pulls/comments/19697616"},"html":{"href":"https://github.com/coreos/etcd/pull/1528#discussion_r19697616"},"pull_request":{"href":"https://api.github.com/repos/coreos/etcd/pulls/1528"}}},"pull_request":{"url":"https://api.github.com/repos/coreos/etcd/pulls/1528","id":23623399,"html_url":"https://github.com/coreos/etcd/pull/1528","diff_url":"https://github.com/coreos/etcd/pull/1528.diff","patch_url":"https://github.com/coreos/etcd/pull/1528.patch","issue_url":"https://api.github.com/repos/coreos/etcd/issues/1528","number":1528,"state":"open","locked":false,"title":"raft: add tests based on section 5.3 in raft paper","user":{"login":"unihorn","id":2976232,"avatar_url":"https://avatars.githubusercontent.com/u/2976232?v=2","gravatar_id":"","url":"https://api.github.com/users/unihorn","html_url":"https://github.com/unihorn","followers_url":"https://api.github.com/users/unihorn/followers","following_url":"https://api.github.com/users/unihorn/following{/other_user}","gists_url":"https://api.github.com/users/unihorn/gists{/gist_id}","starred_url":"https://api.github.com/users/unihorn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/unihorn/subscriptions","organizations_url":"https://api.github.com/users/unihorn/orgs","repos_url":"https://api.github.com/users/unihorn/repos","events_url":"https://api.github.com/users/unihorn/events{/privacy}","received_events_url":"https://api.github.com/users/unihorn/received_events","type":"User","site_admin":false},"body":"for #1408 ","created_at":"2014-10-30T17:38:13Z","updated_at":"2014-10-31T22:41:55Z","closed_at":null,"merged_at":null,"merge_commit_sha":"622998caeb9bd3f75485cbaf7023165023a37a28","assignee":{"login":"unihorn","id":2976232,"avatar_url":"https://avatars.githubusercontent.com/u/2976232?v=2","gravatar_id":"","url":"https://api.github.com/users/unihorn","html_url":"https://github.com/unihorn","followers_url":"https://api.github.com/users/unihorn/followers","following_url":"https://api.github.com/users/unihorn/following{/other_user}","gists_url":"https://api.github.com/users/unihorn/gists{/gist_id}","starred_url":"https://api.github.com/users/unihorn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/unihorn/subscriptions","organizations_url":"https://api.github.com/users/unihorn/orgs","repos_url":"https://api.github.com/users/unihorn/repos","events_url":"https://api.github.com/users/unihorn/events{/privacy}","received_events_url":"https://api.github.com/users/unihorn/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/coreos/etcd/milestones/10","labels_url":"https://api.github.com/repos/coreos/etcd/milestones/10/labels","id":845848,"number":10,"title":"v0.5.0-alpha.2","description":"","creator":{"login":"xiangli-cmu","id":4479947,"avatar_url":"https://avatars.githubusercontent.com/u/4479947?v=2","gravatar_id":"","url":"https://api.github.com/users/xiangli-cmu","html_url":"https://github.com/xiangli-cmu","followers_url":"https://api.github.com/users/xiangli-cmu/followers","following_url":"https://api.github.com/users/xiangli-cmu/following{/other_user}","gists_url":"https://api.github.com/users/xiangli-cmu/gists{/gist_id}","starred_url":"https://api.github.com/users/xiangli-cmu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xiangli-cmu/subscriptions","organizations_url":"https://api.github.com/users/xiangli-cmu/orgs","repos_url":"https://api.github.com/users/xiangli-cmu/repos","events_url":"https://api.github.com/users/xiangli-cmu/events{/privacy}","received_events_url":"https://api.github.com/users/xiangli-cmu/received_events","type":"User","site_admin":false},"open_issues":21,"closed_issues":4,"state":"open","created_at":"2014-10-29T21:40:10Z","updated_at":"2014-10-31T22:08:51Z","due_on":"2014-11-07T08:00:00Z"},"commits_url":"https://api.github.com/repos/coreos/etcd/pulls/1528/commits","review_comments_url":"https://api.github.com/repos/coreos/etcd/pulls/1528/comments","review_comment_url":"https://api.github.com/repos/coreos/etcd/pulls/comments/{number}","comments_url":"https://api.github.com/repos/coreos/etcd/issues/1528/comments","statuses_url":"https://api.github.com/repos/coreos/etcd/statuses/517036134a9fc55401266cad0e4a9490aa4a8c76","head":{"label":"unihorn:191","ref":"191","sha":"517036134a9fc55401266cad0e4a9490aa4a8c76","user":{"login":"unihorn","id":2976232,"avatar_url":"https://avatars.githubusercontent.com/u/2976232?v=2","gravatar_id":"","url":"https://api.github.com/users/unihorn","html_url":"https://github.com/unihorn","followers_url":"https://api.github.com/users/unihorn/followers","following_url":"https://api.github.com/users/unihorn/following{/other_user}","gists_url":"https://api.github.com/users/unihorn/gists{/gist_id}","starred_url":"https://api.github.com/users/unihorn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/unihorn/subscriptions","organizations_url":"https://api.github.com/users/unihorn/orgs","repos_url":"https://api.github.com/users/unihorn/repos","events_url":"https://api.github.com/users/unihorn/events{/privacy}","received_events_url":"https://api.github.com/users/unihorn/received_events","type":"User","site_admin":false},"repo":{"id":16744058,"name":"etcd","full_name":"unihorn/etcd","owner":{"login":"unihorn","id":2976232,"avatar_url":"https://avatars.githubusercontent.com/u/2976232?v=2","gravatar_id":"","url":"https://api.github.com/users/unihorn","html_url":"https://github.com/unihorn","followers_url":"https://api.github.com/users/unihorn/followers","following_url":"https://api.github.com/users/unihorn/following{/other_user}","gists_url":"https://api.github.com/users/unihorn/gists{/gist_id}","starred_url":"https://api.github.com/users/unihorn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/unihorn/subscriptions","organizations_url":"https://api.github.com/users/unihorn/orgs","repos_url":"https://api.github.com/users/unihorn/repos","events_url":"https://api.github.com/users/unihorn/events{/privacy}","received_events_url":"https://api.github.com/users/unihorn/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/unihorn/etcd","description":"A highly-available key value store for shared configuration and service discovery","fork":true,"url":"https://api.github.com/repos/unihorn/etcd","forks_url":"https://api.github.com/repos/unihorn/etcd/forks","keys_url":"https://api.github.com/repos/unihorn/etcd/keys{/key_id}","collaborators_url":"https://api.github.com/repos/unihorn/etcd/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/unihorn/etcd/teams","hooks_url":"https://api.github.com/repos/unihorn/etcd/hooks","issue_events_url":"https://api.github.com/repos/unihorn/etcd/issues/events{/number}","events_url":"https://api.github.com/repos/unihorn/etcd/events","assignees_url":"https://api.github.com/repos/unihorn/etcd/assignees{/user}","branches_url":"https://api.github.com/repos/unihorn/etcd/branches{/branch}","tags_url":"https://api.github.com/repos/unihorn/etcd/tags","blobs_url":"https://api.github.com/repos/unihorn/etcd/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/unihorn/etcd/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/unihorn/etcd/git/refs{/sha}","trees_url":"https://api.github.com/repos/unihorn/etcd/git/trees{/sha}","statuses_url":"https://api.github.com/repos/unihorn/etcd/statuses/{sha}","languages_url":"https://api.github.com/repos/unihorn/etcd/languages","stargazers_url":"https://api.github.com/repos/unihorn/etcd/stargazers","contributors_url":"https://api.github.com/repos/unihorn/etcd/contributors","subscribers_url":"https://api.github.com/repos/unihorn/etcd/subscribers","subscription_url":"https://api.github.com/repos/unihorn/etcd/subscription","commits_url":"https://api.github.com/repos/unihorn/etcd/commits{/sha}","git_commits_url":"https://api.github.com/repos/unihorn/etcd/git/commits{/sha}","comments_url":"https://api.github.com/repos/unihorn/etcd/comments{/number}","issue_comment_url":"https://api.github.com/repos/unihorn/etcd/issues/comments/{number}","contents_url":"https://api.github.com/repos/unihorn/etcd/contents/{+path}","compare_url":"https://api.github.com/repos/unihorn/etcd/compare/{base}...{head}","merges_url":"https://api.github.com/repos/unihorn/etcd/merges","archive_url":"https://api.github.com/repos/unihorn/etcd/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/unihorn/etcd/downloads","issues_url":"https://api.github.com/repos/unihorn/etcd/issues{/number}","pulls_url":"https://api.github.com/repos/unihorn/etcd/pulls{/number}","milestones_url":"https://api.github.com/repos/unihorn/etcd/milestones{/number}","notifications_url":"https://api.github.com/repos/unihorn/etcd/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/unihorn/etcd/labels{/name}","releases_url":"https://api.github.com/repos/unihorn/etcd/releases{/id}","created_at":"2014-02-11T20:18:23Z","updated_at":"2014-09-12T22:41:09Z","pushed_at":"2014-10-31T21:53:36Z","git_url":"git://github.com/unihorn/etcd.git","ssh_url":"git@github.com:unihorn/etcd.git","clone_url":"https://github.com/unihorn/etcd.git","svn_url":"https://github.com/unihorn/etcd","homepage":"","size":16709,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":false,"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":"coreos:master","ref":"master","sha":"6087e2b2f61ffb9dd5a540b53f40de3ed8803fe3","user":{"login":"coreos","id":3730757,"avatar_url":"https://avatars.githubusercontent.com/u/3730757?v=2","gravatar_id":"","url":"https://api.github.com/users/coreos","html_url":"https://github.com/coreos","followers_url":"https://api.github.com/users/coreos/followers","following_url":"https://api.github.com/users/coreos/following{/other_user}","gists_url":"https://api.github.com/users/coreos/gists{/gist_id}","starred_url":"https://api.github.com/users/coreos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coreos/subscriptions","organizations_url":"https://api.github.com/users/coreos/orgs","repos_url":"https://api.github.com/users/coreos/repos","events_url":"https://api.github.com/users/coreos/events{/privacy}","received_events_url":"https://api.github.com/users/coreos/received_events","type":"Organization","site_admin":false},"repo":{"id":11225014,"name":"etcd","full_name":"coreos/etcd","owner":{"login":"coreos","id":3730757,"avatar_url":"https://avatars.githubusercontent.com/u/3730757?v=2","gravatar_id":"","url":"https://api.github.com/users/coreos","html_url":"https://github.com/coreos","followers_url":"https://api.github.com/users/coreos/followers","following_url":"https://api.github.com/users/coreos/following{/other_user}","gists_url":"https://api.github.com/users/coreos/gists{/gist_id}","starred_url":"https://api.github.com/users/coreos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coreos/subscriptions","organizations_url":"https://api.github.com/users/coreos/orgs","repos_url":"https://api.github.com/users/coreos/repos","events_url":"https://api.github.com/users/coreos/events{/privacy}","received_events_url":"https://api.github.com/users/coreos/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/coreos/etcd","description":"A highly-available key value store for shared configuration and service discovery","fork":false,"url":"https://api.github.com/repos/coreos/etcd","forks_url":"https://api.github.com/repos/coreos/etcd/forks","keys_url":"https://api.github.com/repos/coreos/etcd/keys{/key_id}","collaborators_url":"https://api.github.com/repos/coreos/etcd/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/coreos/etcd/teams","hooks_url":"https://api.github.com/repos/coreos/etcd/hooks","issue_events_url":"https://api.github.com/repos/coreos/etcd/issues/events{/number}","events_url":"https://api.github.com/repos/coreos/etcd/events","assignees_url":"https://api.github.com/repos/coreos/etcd/assignees{/user}","branches_url":"https://api.github.com/repos/coreos/etcd/branches{/branch}","tags_url":"https://api.github.com/repos/coreos/etcd/tags","blobs_url":"https://api.github.com/repos/coreos/etcd/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/coreos/etcd/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/coreos/etcd/git/refs{/sha}","trees_url":"https://api.github.com/repos/coreos/etcd/git/trees{/sha}","statuses_url":"https://api.github.com/repos/coreos/etcd/statuses/{sha}","languages_url":"https://api.github.com/repos/coreos/etcd/languages","stargazers_url":"https://api.github.com/repos/coreos/etcd/stargazers","contributors_url":"https://api.github.com/repos/coreos/etcd/contributors","subscribers_url":"https://api.github.com/repos/coreos/etcd/subscribers","subscription_url":"https://api.github.com/repos/coreos/etcd/subscription","commits_url":"https://api.github.com/repos/coreos/etcd/commits{/sha}","git_commits_url":"https://api.github.com/repos/coreos/etcd/git/commits{/sha}","comments_url":"https://api.github.com/repos/coreos/etcd/comments{/number}","issue_comment_url":"https://api.github.com/repos/coreos/etcd/issues/comments/{number}","contents_url":"https://api.github.com/repos/coreos/etcd/contents/{+path}","compare_url":"https://api.github.com/repos/coreos/etcd/compare/{base}...{head}","merges_url":"https://api.github.com/repos/coreos/etcd/merges","archive_url":"https://api.github.com/repos/coreos/etcd/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/coreos/etcd/downloads","issues_url":"https://api.github.com/repos/coreos/etcd/issues{/number}","pulls_url":"https://api.github.com/repos/coreos/etcd/pulls{/number}","milestones_url":"https://api.github.com/repos/coreos/etcd/milestones{/number}","notifications_url":"https://api.github.com/repos/coreos/etcd/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/coreos/etcd/labels{/name}","releases_url":"https://api.github.com/repos/coreos/etcd/releases{/id}","created_at":"2013-07-06T21:57:21Z","updated_at":"2014-10-31T19:48:23Z","pushed_at":"2014-10-31T22:39:22Z","git_url":"git://github.com/coreos/etcd.git","ssh_url":"git@github.com:coreos/etcd.git","clone_url":"https://github.com/coreos/etcd.git","svn_url":"https://github.com/coreos/etcd","homepage":"","size":28773,"stargazers_count":4523,"watchers_count":4523,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":457,"mirror_url":null,"open_issues_count":117,"forks":457,"open_issues":117,"watchers":4523,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/coreos/etcd/pulls/1528"},"html":{"href":"https://github.com/coreos/etcd/pull/1528"},"issue":{"href":"https://api.github.com/repos/coreos/etcd/issues/1528"},"comments":{"href":"https://api.github.com/repos/coreos/etcd/issues/1528/comments"},"review_comments":{"href":"https://api.github.com/repos/coreos/etcd/pulls/1528/comments"},"review_comment":{"href":"https://api.github.com/repos/coreos/etcd/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/coreos/etcd/pulls/1528/commits"},"statuses":{"href":"https://api.github.com/repos/coreos/etcd/statuses/517036134a9fc55401266cad0e4a9490aa4a8c76"}}}}