diff --git a/github/client.go b/github/client.go index 181654115..07339fb92 100644 --- a/github/client.go +++ b/github/client.go @@ -9,8 +9,6 @@ import ( "net/url" "os" "os/exec" - "path/filepath" - "sort" "strings" "time" @@ -93,20 +91,6 @@ func (client *Client) PullRequest(project *Project, id string) (pr *PullRequest, return } -func (client *Client) PullRequestPatch(project *Project, id string) (patch io.ReadCloser, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - res, err := api.GetFile(fmt.Sprintf("repos/%s/%s/pulls/%s", project.Owner, project.Name, id), patchMediaType) - if err = checkStatus(200, "getting pull request patch", res, err); err != nil { - return - } - - return res.Body, nil -} - func (client *Client) CreatePullRequest(project *Project, params map[string]interface{}) (pr *PullRequest, err error) { api, err := client.simpleApi() if err != nil { @@ -159,56 +143,6 @@ func (client *Client) RequestReview(project *Project, prNumber int, params map[s return } -func (client *Client) CommitPatch(project *Project, sha string) (patch io.ReadCloser, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - res, err := api.GetFile(fmt.Sprintf("repos/%s/%s/commits/%s", project.Owner, project.Name, sha), patchMediaType) - if err = checkStatus(200, "getting commit patch", res, err); err != nil { - return - } - - return res.Body, nil -} - -type Gist struct { - Files map[string]GistFile `json:"files"` -} -type GistFile struct { - RawUrl string `json:"raw_url"` -} - -func (client *Client) GistPatch(id string) (patch io.ReadCloser, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - res, err := api.Get(fmt.Sprintf("gists/%s", id)) - if err = checkStatus(200, "getting gist patch", res, err); err != nil { - return - } - - gist := Gist{} - if err = res.Unmarshal(&gist); err != nil { - return - } - rawUrl := "" - for _, file := range gist.Files { - rawUrl = file.RawUrl - break - } - - res, err = api.GetFile(rawUrl, textMediaType) - if err = checkStatus(200, "getting gist patch", res, err); err != nil { - return - } - - return res.Body, nil -} - func (client *Client) Repository(project *Project) (repo *Repository, err error) { api, err := client.simpleApi() if err != nil { @@ -225,299 +159,6 @@ func (client *Client) Repository(project *Project) (repo *Repository, err error) return } -func (client *Client) CreateRepository(project *Project, description, homepage string, isPrivate bool) (repo *Repository, err error) { - repoURL := "user/repos" - if project.Owner != client.Host.User { - repoURL = fmt.Sprintf("orgs/%s/repos", project.Owner) - } - - params := map[string]interface{}{ - "name": project.Name, - "description": description, - "homepage": homepage, - "private": isPrivate, - } - - api, err := client.simpleApi() - if err != nil { - return - } - - res, err := api.PostJSON(repoURL, params) - if err = checkStatus(201, "creating repository", res, err); err != nil { - return - } - - repo = &Repository{} - err = res.Unmarshal(repo) - return -} - -func (client *Client) DeleteRepository(project *Project) error { - api, err := client.simpleApi() - if err != nil { - return err - } - - repoURL := fmt.Sprintf("repos/%s/%s", project.Owner, project.Name) - res, err := api.Delete(repoURL) - return checkStatus(204, "deleting repository", res, err) -} - -type Release struct { - Name string `json:"name"` - TagName string `json:"tag_name"` - TargetCommitish string `json:"target_commitish"` - Body string `json:"body"` - Draft bool `json:"draft"` - Prerelease bool `json:"prerelease"` - Assets []ReleaseAsset `json:"assets"` - TarballUrl string `json:"tarball_url"` - ZipballUrl string `json:"zipball_url"` - HtmlUrl string `json:"html_url"` - UploadUrl string `json:"upload_url"` - ApiUrl string `json:"url"` - CreatedAt time.Time `json:"created_at"` - PublishedAt time.Time `json:"published_at"` -} - -type ReleaseAsset struct { - Name string `json:"name"` - Label string `json:"label"` - DownloadUrl string `json:"browser_download_url"` - ApiUrl string `json:"url"` -} - -func (client *Client) FetchReleases(project *Project, limit int, filter func(*Release) bool) (releases []Release, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - path := fmt.Sprintf("repos/%s/%s/releases?per_page=%d", project.Owner, project.Name, perPage(limit, 100)) - - releases = []Release{} - var res *simpleResponse - - for path != "" { - res, err = api.Get(path) - if err = checkStatus(200, "fetching releases", res, err); err != nil { - return - } - path = res.Link("next") - - releasesPage := []Release{} - if err = res.Unmarshal(&releasesPage); err != nil { - return - } - for _, release := range releasesPage { - if filter == nil || filter(&release) { - releases = append(releases, release) - if limit > 0 && len(releases) == limit { - path = "" - break - } - } - } - } - - return -} - -func (client *Client) FetchRelease(project *Project, tagName string) (*Release, error) { - releases, err := client.FetchReleases(project, 100, func(release *Release) bool { - return release.TagName == tagName - }) - - if err == nil { - if len(releases) < 1 { - return nil, fmt.Errorf("Unable to find release with tag name `%s'", tagName) - } else { - return &releases[0], nil - } - } else { - return nil, err - } -} - -func (client *Client) CreateRelease(project *Project, releaseParams *Release) (release *Release, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - res, err := api.PostJSON(fmt.Sprintf("repos/%s/%s/releases", project.Owner, project.Name), releaseParams) - if err = checkStatus(201, "creating release", res, err); err != nil { - return - } - - release = &Release{} - err = res.Unmarshal(release) - return -} - -func (client *Client) EditRelease(release *Release, releaseParams map[string]interface{}) (updatedRelease *Release, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - res, err := api.PatchJSON(release.ApiUrl, releaseParams) - if err = checkStatus(200, "editing release", res, err); err != nil { - return - } - - updatedRelease = &Release{} - err = res.Unmarshal(updatedRelease) - return -} - -func (client *Client) DeleteRelease(release *Release) (err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - res, err := api.Delete(release.ApiUrl) - if err = checkStatus(204, "deleting release", res, err); err != nil { - return - } - - return -} - -func (client *Client) UploadReleaseAsset(release *Release, filename, label string) (asset *ReleaseAsset, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - parts := strings.SplitN(release.UploadUrl, "{", 2) - uploadUrl := parts[0] - uploadUrl += "?name=" + url.QueryEscape(filepath.Base(filename)) - if label != "" { - uploadUrl += "&label=" + url.QueryEscape(label) - } - - res, err := api.PostFile(uploadUrl, filename) - if err = checkStatus(201, "uploading release asset", res, err); err != nil { - return - } - - asset = &ReleaseAsset{} - err = res.Unmarshal(asset) - return -} - -func (client *Client) DeleteReleaseAsset(asset *ReleaseAsset) (err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - res, err := api.Delete(asset.ApiUrl) - err = checkStatus(204, "deleting release asset", res, err) - - return -} - -func (client *Client) DownloadReleaseAsset(url string) (asset io.ReadCloser, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - resp, err := api.GetFile(url, "application/octet-stream") - if err = checkStatus(200, "downloading asset", resp, err); err != nil { - return - } - - return resp.Body, err -} - -type CIStatusResponse struct { - State string `json:"state"` - Statuses []CIStatus `json:"statuses"` -} - -type CIStatus struct { - State string `json:"state"` - Context string `json:"context"` - TargetUrl string `json:"target_url"` -} - -type CheckRunsResponse struct { - CheckRuns []CheckRun `json:"check_runs"` -} - -type CheckRun struct { - Status string `json:"status"` - Conclusion string `json:"conclusion"` - Name string `json:"name"` - HtmlUrl string `json:"html_url"` -} - -func (client *Client) FetchCIStatus(project *Project, sha string) (status *CIStatusResponse, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - res, err := api.Get(fmt.Sprintf("repos/%s/%s/commits/%s/status", project.Owner, project.Name, sha)) - if err = checkStatus(200, "fetching statuses", res, err); err != nil { - return - } - - status = &CIStatusResponse{} - if err = res.Unmarshal(status); err != nil { - return - } - - sortStatuses := func() { - sort.Slice(status.Statuses, func(a, b int) bool { - sA := status.Statuses[a] - sB := status.Statuses[b] - cmp := strings.Compare(strings.ToLower(sA.Context), strings.ToLower(sB.Context)) - if cmp == 0 { - return strings.Compare(sA.TargetUrl, sB.TargetUrl) < 0 - } else { - return cmp < 0 - } - }) - } - sortStatuses() - - res, err = api.GetFile(fmt.Sprintf("repos/%s/%s/commits/%s/check-runs", project.Owner, project.Name, sha), checksType) - if err == nil && (res.StatusCode == 403 || res.StatusCode == 404 || res.StatusCode == 422) { - return - } - if err = checkStatus(200, "fetching checks", res, err); err != nil { - return - } - - checks := &CheckRunsResponse{} - if err = res.Unmarshal(checks); err != nil { - return - } - - for _, checkRun := range checks.CheckRuns { - state := "pending" - if checkRun.Status == "completed" { - state = checkRun.Conclusion - } - checkStatus := CIStatus{ - State: state, - Context: checkRun.Name, - TargetUrl: checkRun.HtmlUrl, - } - status.Statuses = append(status.Statuses, checkStatus) - } - - sortStatuses() - - return -} - type Repository struct { Name string `json:"name"` FullName string `json:"full_name"` @@ -536,30 +177,6 @@ type RepositoryPermissions struct { Pull bool `json:"pull"` } -func (client *Client) ForkRepository(project *Project, params map[string]interface{}) (repo *Repository, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - res, err := api.PostJSON(fmt.Sprintf("repos/%s/%s/forks", project.Owner, project.Name), params) - if err = checkStatus(202, "creating fork", res, err); err != nil { - return - } - - repo = &Repository{} - err = res.Unmarshal(repo) - - return -} - -type Comment struct { - Id int `json:"id"` - Body string `json:"body"` - User *User `json:"user"` - CreatedAt time.Time `json:"created_at"` -} - type Issue struct { Number int `json:"number"` State string `json:"state"` @@ -644,178 +261,6 @@ type Milestone struct { Title string `json:"title"` } -func (client *Client) FetchIssues(project *Project, filterParams map[string]interface{}, limit int, filter func(*Issue) bool) (issues []Issue, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - path := fmt.Sprintf("repos/%s/%s/issues?per_page=%d", project.Owner, project.Name, perPage(limit, 100)) - if filterParams != nil { - path = addQuery(path, filterParams) - } - - issues = []Issue{} - var res *simpleResponse - - for path != "" { - res, err = api.Get(path) - if err = checkStatus(200, "fetching issues", res, err); err != nil { - return - } - path = res.Link("next") - - issuesPage := []Issue{} - if err = res.Unmarshal(&issuesPage); err != nil { - return - } - for _, issue := range issuesPage { - if filter == nil || filter(&issue) { - issues = append(issues, issue) - if limit > 0 && len(issues) == limit { - path = "" - break - } - } - } - } - - return -} - -func (client *Client) FetchIssue(project *Project, number string) (issue *Issue, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - res, err := api.Get(fmt.Sprintf("repos/%s/%s/issues/%s", project.Owner, project.Name, number)) - if err = checkStatus(200, "fetching issue", res, err); err != nil { - return nil, err - } - - issue = &Issue{} - err = res.Unmarshal(issue) - return -} - -func (client *Client) FetchComments(project *Project, number string) (comments []Comment, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - res, err := api.Get(fmt.Sprintf("repos/%s/%s/issues/%s/comments", project.Owner, project.Name, number)) - if err = checkStatus(200, "fetching comments for issue", res, err); err != nil { - return nil, err - } - - comments = []Comment{} - err = res.Unmarshal(&comments) - return -} - -func (client *Client) CreateIssue(project *Project, params interface{}) (issue *Issue, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - res, err := api.PostJSON(fmt.Sprintf("repos/%s/%s/issues", project.Owner, project.Name), params) - if err = checkStatus(201, "creating issue", res, err); err != nil { - return - } - - issue = &Issue{} - err = res.Unmarshal(issue) - return -} - -func (client *Client) UpdateIssue(project *Project, issueNumber int, params map[string]interface{}) (err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - res, err := api.PatchJSON(fmt.Sprintf("repos/%s/%s/issues/%d", project.Owner, project.Name, issueNumber), params) - if err = checkStatus(200, "updating issue", res, err); err != nil { - return - } - - res.Body.Close() - return -} - -type sortedLabels []IssueLabel - -func (s sortedLabels) Len() int { - return len(s) -} -func (s sortedLabels) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} -func (s sortedLabels) Less(i, j int) bool { - return strings.Compare(strings.ToLower(s[i].Name), strings.ToLower(s[j].Name)) < 0 -} - -func (client *Client) FetchLabels(project *Project) (labels []IssueLabel, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - path := fmt.Sprintf("repos/%s/%s/labels?per_page=100", project.Owner, project.Name) - - labels = []IssueLabel{} - var res *simpleResponse - - for path != "" { - res, err = api.Get(path) - if err = checkStatus(200, "fetching labels", res, err); err != nil { - return - } - path = res.Link("next") - - labelsPage := []IssueLabel{} - if err = res.Unmarshal(&labelsPage); err != nil { - return - } - labels = append(labels, labelsPage...) - } - - sort.Sort(sortedLabels(labels)) - - return -} - -func (client *Client) FetchMilestones(project *Project) (milestones []Milestone, err error) { - api, err := client.simpleApi() - if err != nil { - return - } - - path := fmt.Sprintf("repos/%s/%s/milestones?per_page=100", project.Owner, project.Name) - - milestones = []Milestone{} - var res *simpleResponse - - for path != "" { - res, err = api.Get(path) - if err = checkStatus(200, "fetching milestones", res, err); err != nil { - return - } - path = res.Link("next") - - milestonesPage := []Milestone{} - if err = res.Unmarshal(&milestonesPage); err != nil { - return - } - milestones = append(milestones, milestonesPage...) - } - - return -} - func (client *Client) GenericAPIRequest(method, path string, data interface{}, headers map[string]string, ttl int) (*simpleResponse, error) { api, err := client.simpleApi() if err != nil { diff --git a/github/http.go b/github/http.go index 889253504..f0dfd6e49 100644 --- a/github/http.go +++ b/github/http.go @@ -165,7 +165,6 @@ func newHttpClient(testHost string, verbose bool, unixSocket string) *http.Clien } } else { httpTransport = &http.Transport{ - Proxy: proxyFromEnvironment, DialContext: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, @@ -197,30 +196,6 @@ func cloneRequest(req *http.Request) *http.Request { return dup } -// An implementation of http.ProxyFromEnvironment that isn't broken -func proxyFromEnvironment(req *http.Request) (*url.URL, error) { - proxy := os.Getenv("http_proxy") - if proxy == "" { - proxy = os.Getenv("HTTP_PROXY") - } - if proxy == "" { - return nil, nil - } - - proxyURL, err := url.Parse(proxy) - if err != nil || !strings.HasPrefix(proxyURL.Scheme, "http") { - if proxyURL, err := url.Parse("http://" + proxy); err == nil { - return proxyURL, nil - } - } - - if err != nil { - return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err) - } - - return proxyURL, nil -} - type simpleClient struct { httpClient *http.Client rootUrl *url.URL @@ -425,10 +400,6 @@ func (c *simpleClient) GetFile(path string, mimeType string) (*simpleResponse, e }) } -func (c *simpleClient) Delete(path string) (*simpleResponse, error) { - return c.performRequest("DELETE", path, nil, nil) -} - func (c *simpleClient) PostJSON(path string, payload interface{}) (*simpleResponse, error) { return c.jsonRequest("POST", path, payload, nil) } @@ -443,24 +414,6 @@ func (c *simpleClient) PatchJSON(path string, payload interface{}) (*simpleRespo return c.jsonRequest("PATCH", path, payload, nil) } -func (c *simpleClient) PostFile(path, filename string) (*simpleResponse, error) { - stat, err := os.Stat(filename) - if err != nil { - return nil, err - } - - file, err := os.Open(filename) - if err != nil { - return nil, err - } - defer file.Close() - - return c.performRequest("POST", path, file, func(req *http.Request) { - req.ContentLength = stat.Size() - req.Header.Set("Content-Type", "application/octet-stream") - }) -} - type simpleResponse struct { *http.Response }