{"action":"created","comment":{"url":"https://api.github.com/repos/coreos/etcd/pulls/comments/23878685","id":23878685,"diff_hunk":"@@ -0,0 +1,336 @@\n+// Copyright 2015 CoreOS, Inc.\n+//\n+// Licensed under the Apache License, Version 2.0 (the \"License\");\n+// you may not use this file except in compliance with the License.\n+// You may obtain a copy of the License at\n+//\n+//     http://www.apache.org/licenses/LICENSE-2.0\n+//\n+// Unless required by applicable law or agreed to in writing, software\n+// distributed under the License is distributed on an \"AS IS\" BASIS,\n+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+// See the License for the specific language governing permissions and\n+// limitations under the License.\n+\n+package client\n+\n+import (\n+\t\"errors\"\n+\t\"fmt\"\n+\t\"io/ioutil\"\n+\t\"net\"\n+\t\"net/http\"\n+\t\"net/url\"\n+\t\"sync\"\n+\t\"time\"\n+\n+\t\"github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context\"\n+)\n+\n+var (\n+\tErrNoEndpoints      = errors.New(\"client: no endpoints available\")\n+\tErrTooManyRedirects = errors.New(\"client: too many redirects\")\n+)\n+\n+var DefaultRequestTimeout = 5 * time.Second\n+\n+var DefaultTransport CancelableTransport = &http.Transport{\n+\tProxy: http.ProxyFromEnvironment,\n+\tDial: (&net.Dialer{\n+\t\tTimeout:   30 * time.Second,\n+\t\tKeepAlive: 30 * time.Second,\n+\t}).Dial,\n+\tTLSHandshakeTimeout: 10 * time.Second,\n+}\n+\n+type Config struct {\n+\t// Endpoints defines a set of URLs (schemes, hosts and ports only)\n+\t// that can be used to communicate with a logical etcd cluster. For\n+\t// example, a three-node cluster could be provided like so:\n+\t//\n+\t// \tEndpoints: []string{\n+\t//\t\t\"http://node1.example.com:4001\",\n+\t//\t\t\"http://node2.example.com:2379\",\n+\t//\t\t\"http://node3.example.com:4001\",\n+\t//\t}\n+\t//\n+\t// If multiple endpoints are provided, the Client will attempt to\n+\t// use them all in the event that one or more of them are unusable.\n+\t//\n+\t// If Client.Sync is ever called, the Client may cache an alternate\n+\t// set of endpoints to continue operation.\n+\tEndpoints []string\n+\n+\t// Transport is used by the Client to drive HTTP requests. If not\n+\t// provided, DefaultTransport will be used.\n+\tTransport CancelableTransport\n+\n+\t// CheckRedirect specifies the policy for handling HTTP redirects.\n+\t// If CheckRedirect is not nil, the Client calls it before\n+\t// following an HTTP redirect. The sole argument is the number of\n+\t// requests that have alrady been made. If CheckRedirect returns\n+\t// an error, Client.Do will not make any further requests and return\n+\t// the error back it to the caller.\n+\t//\n+\t// If CheckRedirect is nil, the Client uses its default policy,\n+\t// which is to stop after 10 consecutive requests.\n+\tCheckRedirect CheckRedirectFunc\n+}\n+\n+func (cfg *Config) transport() CancelableTransport {\n+\tif cfg.Transport == nil {\n+\t\treturn DefaultTransport\n+\t}\n+\treturn cfg.Transport\n+}\n+\n+func (cfg *Config) checkRedirect() CheckRedirectFunc {\n+\tif cfg.CheckRedirect == nil {\n+\t\treturn DefaultCheckRedirect\n+\t}\n+\treturn cfg.CheckRedirect\n+}\n+\n+// CancelableTransport mimics net/http.Transport, but requires that\n+// the object also support request cancellation.\n+type CancelableTransport interface {\n+\thttp.RoundTripper\n+\tCancelRequest(req *http.Request)\n+}\n+\n+type CheckRedirectFunc func(via int) error\n+\n+// DefaultCheckRedirect follows up to 10 redirects, but no more.\n+var DefaultCheckRedirect CheckRedirectFunc = func(via int) error {\n+\tif via > 10 {\n+\t\treturn ErrTooManyRedirects\n+\t}\n+\treturn nil\n+}\n+\n+type Client interface {\n+\t// Sync updates the internal cache of the etcd cluster's membership.\n+\tSync(context.Context) error\n+\n+\t// Endpoints returns a copy of the current set of API endpoints used\n+\t// by Client to resolve HTTP requests. If Sync has ever been called,\n+\t// this may differ from the initial Endpoints provided in the Config.\n+\tEndpoints() []string\n+\n+\thttpClient\n+}\n+\n+func New(cfg Config) (Client, error) {\n+\tc := &httpClusterClient{clientFactory: newHTTPClientFactory(cfg.transport(), cfg.checkRedirect())}\n+\tif err := c.reset(cfg.Endpoints); err != nil {\n+\t\treturn nil, err\n+\t}\n+\treturn c, nil\n+}\n+\n+type httpClient interface {\n+\tDo(context.Context, httpAction) (*http.Response, []byte, error)\n+}\n+\n+func newHTTPClientFactory(tr CancelableTransport, cr CheckRedirectFunc) httpClientFactory {\n+\treturn func(ep url.URL) httpClient {\n+\t\treturn &redirectFollowingHTTPClient{\n+\t\t\tcheckRedirect: cr,\n+\t\t\tclient: &simpleHTTPClient{\n+\t\t\t\ttransport: tr,\n+\t\t\t\tendpoint:  ep,\n+\t\t\t},\n+\t\t}\n+\t}\n+}\n+\n+type httpClientFactory func(url.URL) httpClient\n+\n+type httpAction interface {\n+\tHTTPRequest(url.URL) *http.Request\n+}\n+\n+type httpClusterClient struct {\n+\tclientFactory httpClientFactory\n+\tendpoints     []url.URL\n+\tsync.RWMutex\n+}\n+\n+func (c *httpClusterClient) reset(eps []string) error {\n+\tif len(eps) == 0 {\n+\t\treturn ErrNoEndpoints\n+\t}\n+\n+\tneps := make([]url.URL, len(eps))\n+\tfor i, ep := range eps {\n+\t\tu, err := url.Parse(ep)\n+\t\tif err != nil {\n+\t\t\treturn err\n+\t\t}\n+\t\tneps[i] = *u\n+\t}\n+\n+\tc.endpoints = neps\n+\n+\treturn nil\n+}\n+\n+func (c *httpClusterClient) Do(ctx context.Context, act httpAction) (resp *http.Response, body []byte, err error) {\n+\tc.RLock()\n+\tleps := len(c.endpoints)\n+\teps := make([]url.URL, leps)\n+\tn := copy(eps, c.endpoints)\n+\tc.RUnlock()\n+\n+\tif leps == 0 {\n+\t\terr = ErrNoEndpoints\n+\t\treturn\n+\t}\n+\n+\tif leps != n {\n+\t\terr = errors.New(\"unable to pick endpoint: copy failed\")\n+\t\treturn\n+\t}\n+\n+\tfor _, ep := range eps {\n+\t\thc := c.clientFactory(ep)\n+\t\tresp, body, err = hc.Do(ctx, act)\n+\t\tif err != nil {\n+\t\t\tif err == context.DeadlineExceeded || err == context.Canceled {\n+\t\t\t\treturn nil, nil, err\n+\t\t\t}\n+\t\t\tcontinue\n+\t\t}\n+\t\tif resp.StatusCode/100 == 5 {\n+\t\t\tcontinue\n+\t\t}\n+\t\tbreak\n+\t}\n+\n+\treturn\n+}\n+\n+func (c *httpClusterClient) Endpoints() []string {\n+\tc.RLock()\n+\tdefer c.RUnlock()\n+\n+\teps := make([]string, len(c.endpoints))\n+\tfor i, ep := range c.endpoints {\n+\t\teps[i] = ep.String()\n+\t}\n+\n+\treturn eps\n+}\n+\n+func (c *httpClusterClient) Sync(ctx context.Context) error {\n+\tmAPI := NewMembersAPI(c)\n+\tms, err := mAPI.List(ctx)\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\n+\tc.Lock()\n+\tdefer c.Unlock()\n+\n+\teps := make([]string, 0)\n+\tfor _, m := range ms {\n+\t\teps = append(eps, m.ClientURLs...)\n+\t}\n+\n+\treturn c.reset(eps)\n+}\n+\n+type roundTripResponse struct {\n+\tresp *http.Response\n+\terr  error\n+}\n+\n+type simpleHTTPClient struct {\n+\ttransport CancelableTransport\n+\tendpoint  url.URL\n+}\n+\n+func (c *simpleHTTPClient) Do(ctx context.Context, act httpAction) (*http.Response, []byte, error) {\n+\treq := act.HTTPRequest(c.endpoint)\n+\n+\trtchan := make(chan roundTripResponse, 1)\n+\tgo func() {\n+\t\tresp, err := c.transport.RoundTrip(req)\n+\t\trtchan <- roundTripResponse{resp: resp, err: err}\n+\t\tclose(rtchan)\n+\t}()\n+\n+\tvar resp *http.Response\n+\tvar err error\n+\n+\tselect {\n+\tcase rtresp := <-rtchan:\n+\t\tresp, err = rtresp.resp, rtresp.err\n+\tcase <-ctx.Done():\n+\t\tc.transport.CancelRequest(req)\n+\t\t// wait for request to actually exit before continuing\n+\t\t<-rtchan\n+\t\terr = ctx.Err()\n+\t}\n+\n+\t// always check for resp nil-ness to deal with possible\n+\t// race conditions between channels above\n+\tdefer func() {","path":"client/client.go","position":278,"original_position":278,"commit_id":"49715518092c3a98216510bee0321f1a2a0665a2","original_commit_id":"49715518092c3a98216510bee0321f1a2a0665a2","user":{"login":"xiang90","id":4479947,"avatar_url":"https://avatars.githubusercontent.com/u/4479947?v=3","gravatar_id":"","url":"https://api.github.com/users/xiang90","html_url":"https://github.com/xiang90","followers_url":"https://api.github.com/users/xiang90/followers","following_url":"https://api.github.com/users/xiang90/following{/other_user}","gists_url":"https://api.github.com/users/xiang90/gists{/gist_id}","starred_url":"https://api.github.com/users/xiang90/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xiang90/subscriptions","organizations_url":"https://api.github.com/users/xiang90/orgs","repos_url":"https://api.github.com/users/xiang90/repos","events_url":"https://api.github.com/users/xiang90/events{/privacy}","received_events_url":"https://api.github.com/users/xiang90/received_events","type":"User","site_admin":false},"body":"what happens if line 269 gets hit and then the defer func and then line 258? seems like the resp will remain opening.","created_at":"2015-01-30T22:51:41Z","updated_at":"2015-01-30T22:51:41Z","html_url":"https://github.com/coreos/etcd/pull/2200#discussion_r23878685","pull_request_url":"https://api.github.com/repos/coreos/etcd/pulls/2200","_links":{"self":{"href":"https://api.github.com/repos/coreos/etcd/pulls/comments/23878685"},"html":{"href":"https://github.com/coreos/etcd/pull/2200#discussion_r23878685"},"pull_request":{"href":"https://api.github.com/repos/coreos/etcd/pulls/2200"}}},"pull_request":{"url":"https://api.github.com/repos/coreos/etcd/pulls/2200","id":28398736,"html_url":"https://github.com/coreos/etcd/pull/2200","diff_url":"https://github.com/coreos/etcd/pull/2200.diff","patch_url":"https://github.com/coreos/etcd/pull/2200.patch","issue_url":"https://api.github.com/repos/coreos/etcd/issues/2200","number":2200,"state":"open","locked":false,"title":"Establish etcd/client APIs","user":{"login":"bcwaldon","id":548759,"avatar_url":"https://avatars.githubusercontent.com/u/548759?v=3","gravatar_id":"","url":"https://api.github.com/users/bcwaldon","html_url":"https://github.com/bcwaldon","followers_url":"https://api.github.com/users/bcwaldon/followers","following_url":"https://api.github.com/users/bcwaldon/following{/other_user}","gists_url":"https://api.github.com/users/bcwaldon/gists{/gist_id}","starred_url":"https://api.github.com/users/bcwaldon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bcwaldon/subscriptions","organizations_url":"https://api.github.com/users/bcwaldon/orgs","repos_url":"https://api.github.com/users/bcwaldon/repos","events_url":"https://api.github.com/users/bcwaldon/events{/privacy}","received_events_url":"https://api.github.com/users/bcwaldon/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-01-30T22:29:22Z","updated_at":"2015-01-30T22:51:41Z","closed_at":null,"merged_at":null,"merge_commit_sha":"29d04d7dea966f2631a28f6328f01bd2d55f4bb5","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/coreos/etcd/pulls/2200/commits","review_comments_url":"https://api.github.com/repos/coreos/etcd/pulls/2200/comments","review_comment_url":"https://api.github.com/repos/coreos/etcd/pulls/comments/{number}","comments_url":"https://api.github.com/repos/coreos/etcd/issues/2200/comments","statuses_url":"https://api.github.com/repos/coreos/etcd/statuses/49715518092c3a98216510bee0321f1a2a0665a2","head":{"label":"bcwaldon:reclient","ref":"reclient","sha":"49715518092c3a98216510bee0321f1a2a0665a2","user":{"login":"bcwaldon","id":548759,"avatar_url":"https://avatars.githubusercontent.com/u/548759?v=3","gravatar_id":"","url":"https://api.github.com/users/bcwaldon","html_url":"https://github.com/bcwaldon","followers_url":"https://api.github.com/users/bcwaldon/followers","following_url":"https://api.github.com/users/bcwaldon/following{/other_user}","gists_url":"https://api.github.com/users/bcwaldon/gists{/gist_id}","starred_url":"https://api.github.com/users/bcwaldon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bcwaldon/subscriptions","organizations_url":"https://api.github.com/users/bcwaldon/orgs","repos_url":"https://api.github.com/users/bcwaldon/repos","events_url":"https://api.github.com/users/bcwaldon/events{/privacy}","received_events_url":"https://api.github.com/users/bcwaldon/received_events","type":"User","site_admin":false},"repo":{"id":14072631,"name":"etcd","full_name":"bcwaldon/etcd","owner":{"login":"bcwaldon","id":548759,"avatar_url":"https://avatars.githubusercontent.com/u/548759?v=3","gravatar_id":"","url":"https://api.github.com/users/bcwaldon","html_url":"https://github.com/bcwaldon","followers_url":"https://api.github.com/users/bcwaldon/followers","following_url":"https://api.github.com/users/bcwaldon/following{/other_user}","gists_url":"https://api.github.com/users/bcwaldon/gists{/gist_id}","starred_url":"https://api.github.com/users/bcwaldon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bcwaldon/subscriptions","organizations_url":"https://api.github.com/users/bcwaldon/orgs","repos_url":"https://api.github.com/users/bcwaldon/repos","events_url":"https://api.github.com/users/bcwaldon/events{/privacy}","received_events_url":"https://api.github.com/users/bcwaldon/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/bcwaldon/etcd","description":"A highly-available key value store for shared configuration and service discovery","fork":true,"url":"https://api.github.com/repos/bcwaldon/etcd","forks_url":"https://api.github.com/repos/bcwaldon/etcd/forks","keys_url":"https://api.github.com/repos/bcwaldon/etcd/keys{/key_id}","collaborators_url":"https://api.github.com/repos/bcwaldon/etcd/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/bcwaldon/etcd/teams","hooks_url":"https://api.github.com/repos/bcwaldon/etcd/hooks","issue_events_url":"https://api.github.com/repos/bcwaldon/etcd/issues/events{/number}","events_url":"https://api.github.com/repos/bcwaldon/etcd/events","assignees_url":"https://api.github.com/repos/bcwaldon/etcd/assignees{/user}","branches_url":"https://api.github.com/repos/bcwaldon/etcd/branches{/branch}","tags_url":"https://api.github.com/repos/bcwaldon/etcd/tags","blobs_url":"https://api.github.com/repos/bcwaldon/etcd/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/bcwaldon/etcd/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/bcwaldon/etcd/git/refs{/sha}","trees_url":"https://api.github.com/repos/bcwaldon/etcd/git/trees{/sha}","statuses_url":"https://api.github.com/repos/bcwaldon/etcd/statuses/{sha}","languages_url":"https://api.github.com/repos/bcwaldon/etcd/languages","stargazers_url":"https://api.github.com/repos/bcwaldon/etcd/stargazers","contributors_url":"https://api.github.com/repos/bcwaldon/etcd/contributors","subscribers_url":"https://api.github.com/repos/bcwaldon/etcd/subscribers","subscription_url":"https://api.github.com/repos/bcwaldon/etcd/subscription","commits_url":"https://api.github.com/repos/bcwaldon/etcd/commits{/sha}","git_commits_url":"https://api.github.com/repos/bcwaldon/etcd/git/commits{/sha}","comments_url":"https://api.github.com/repos/bcwaldon/etcd/comments{/number}","issue_comment_url":"https://api.github.com/repos/bcwaldon/etcd/issues/comments/{number}","contents_url":"https://api.github.com/repos/bcwaldon/etcd/contents/{+path}","compare_url":"https://api.github.com/repos/bcwaldon/etcd/compare/{base}...{head}","merges_url":"https://api.github.com/repos/bcwaldon/etcd/merges","archive_url":"https://api.github.com/repos/bcwaldon/etcd/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/bcwaldon/etcd/downloads","issues_url":"https://api.github.com/repos/bcwaldon/etcd/issues{/number}","pulls_url":"https://api.github.com/repos/bcwaldon/etcd/pulls{/number}","milestones_url":"https://api.github.com/repos/bcwaldon/etcd/milestones{/number}","notifications_url":"https://api.github.com/repos/bcwaldon/etcd/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/bcwaldon/etcd/labels{/name}","releases_url":"https://api.github.com/repos/bcwaldon/etcd/releases{/id}","created_at":"2013-11-02T18:58:03Z","updated_at":"2014-09-04T17:04:41Z","pushed_at":"2015-01-30T00:25:46Z","git_url":"git://github.com/bcwaldon/etcd.git","ssh_url":"git@github.com:bcwaldon/etcd.git","clone_url":"https://github.com/bcwaldon/etcd.git","svn_url":"https://github.com/bcwaldon/etcd","homepage":"http://coreos.com/docs/etcd/","size":14600,"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:210","ref":"210","sha":"56a515d375bb1e3be6024c3334a5d376135bbcd2","user":{"login":"coreos","id":3730757,"avatar_url":"https://avatars.githubusercontent.com/u/3730757?v=3","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=3","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":"2015-01-30T22:15:08Z","pushed_at":"2015-01-30T22:20:09Z","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":27188,"stargazers_count":5431,"watchers_count":5431,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":619,"mirror_url":null,"open_issues_count":102,"forks":619,"open_issues":102,"watchers":5431,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/coreos/etcd/pulls/2200"},"html":{"href":"https://github.com/coreos/etcd/pull/2200"},"issue":{"href":"https://api.github.com/repos/coreos/etcd/issues/2200"},"comments":{"href":"https://api.github.com/repos/coreos/etcd/issues/2200/comments"},"review_comments":{"href":"https://api.github.com/repos/coreos/etcd/pulls/2200/comments"},"review_comment":{"href":"https://api.github.com/repos/coreos/etcd/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/coreos/etcd/pulls/2200/commits"},"statuses":{"href":"https://api.github.com/repos/coreos/etcd/statuses/49715518092c3a98216510bee0321f1a2a0665a2"}}}}