From 539c0e41e4a62e7b558bd57c4f83079a3aa08233 Mon Sep 17 00:00:00 2001 From: Mihai Parparita Date: Sat, 19 Jul 2014 14:34:20 -0700 Subject: [PATCH] Small refactoring to break up the large handler functions. --- app/githop.go | 152 +++++++++++++++++++++++++++++--------------------- 1 file changed, 88 insertions(+), 64 deletions(-) diff --git a/app/githop.go b/app/githop.go index 1b64948..8b80370 100644 --- a/app/githop.go +++ b/app/githop.go @@ -28,9 +28,46 @@ type RepoDigest struct { type Digest struct { User *github.User + StartTime time.Time + EndTime time.Time RepoDigests []*RepoDigest } +func (digest *Digest) Fetch(repos []github.Repository, githubClient *github.Client) error { + type RepoDigestResponse struct { + repoDigest *RepoDigest + err error + } + ch := make(chan *RepoDigestResponse) + for _, repo := range repos { + go func(repo github.Repository) { + commits, _, err := githubClient.Repositories.ListCommits( + *repo.Owner.Login, + *repo.Name, + &github.CommitsListOptions{ + Author: *digest.User.Login, + Since: digest.StartTime, + Until: digest.EndTime, + }) + if err != nil { + ch <- &RepoDigestResponse{nil, err} + } else { + ch <- &RepoDigestResponse{&RepoDigest{&repo, commits}, nil} + } + }(repo) + } + for i := 0; i < len(repos); i++ { + select { + case r := <-ch: + if r.err != nil { + return r.err + } + digest.RepoDigests = append(digest.RepoDigests, r.repoDigest) + } + } + return nil +} + func initGithubOAuthConfig() { path := "config/github-oauth" if appengine.IsDevAppServer() { @@ -39,7 +76,7 @@ func initGithubOAuthConfig() { path += ".json" configBytes, err := ioutil.ReadFile(path) if err != nil { - log.Panicf("Could not read GitHut OAuth config from %s: %s", path, err.Error()) + log.Panicf("Could not read GitHub OAuth config from %s: %s", path, err.Error()) } err = json.Unmarshal(configBytes, &githubOauthConfig) if err != nil { @@ -67,23 +104,14 @@ func indexHandler(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, githubOauthConfig.AuthCodeURL(""), http.StatusFound) return } - tokenBytes, err := base64.URLEncoding.DecodeString(tokenEncoded) + token, err := decodeOAuthToken(tokenEncoded) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - var token oauth.Token - err = json.Unmarshal(tokenBytes, &token) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - appengineContext := appengine.NewContext(r) - oauthTransport := &oauth.Transport{ - Config: &githubOauthConfig, - Transport: &urlfetch.Transport{Context: appengineContext}, - Token: &token, - } + + oauthTransport := githubOAuthTransport(r) + oauthTransport.Token = token githubClient := github.NewClient(oauthTransport.Client()) user, _, err := githubClient.Users.Get("") @@ -92,10 +120,6 @@ func indexHandler(w http.ResponseWriter, r *http.Request) { return } - now := time.Now() - digestStartTime := time.Date(now.Year()-1, now.Month(), now.Day(), 0, 0, 0, 0, now.Location()) - digestEndTime := digestStartTime.AddDate(0, 0, 7) - // The username parameter must be left blank so that we can get all of the // repositories the user has access to, not just ones that they own. repos, _, err := githubClient.Repositories.List("", nil) @@ -103,42 +127,18 @@ func indexHandler(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) return } - digest := Digest{User: user, RepoDigests: make([]*RepoDigest, 0, len(repos))} - type RepoDigestResponse struct { - repoDigest *RepoDigest - err error + now := time.Now() + digestStartTime := time.Date(now.Year()-1, now.Month(), now.Day(), 0, 0, 0, 0, now.Location()) + digestEndTime := digestStartTime.AddDate(0, 0, 7) + digest := Digest{ + User: user, + RepoDigests: make([]*RepoDigest, 0, len(repos)), + StartTime: digestStartTime, + EndTime: digestEndTime, } - ch := make(chan *RepoDigestResponse) - for _, repo := range repos { - go func(repo github.Repository) { - commits, _, err := githubClient.Repositories.ListCommits( - *repo.Owner.Login, - *repo.Name, - &github.CommitsListOptions{ - Author: *user.Login, - Since: digestStartTime, - Until: digestEndTime, - }) - if err != nil { - ch <- &RepoDigestResponse{nil, err} - } else { - ch <- &RepoDigestResponse{&RepoDigest{&repo, commits}, nil} - } - }(repo) - } -loop: - for { - select { - case r := <-ch: - if r.err != nil { - http.Error(w, r.err.Error(), http.StatusInternalServerError) - return - } - digest.RepoDigests = append(digest.RepoDigests, r.repoDigest) - if len(digest.RepoDigests) == len(repos) { - break loop - } - } + err = digest.Fetch(repos, githubClient) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) } if err := indexTemplate.Execute(w, digest); err != nil { @@ -148,25 +148,49 @@ loop: func githubOAuthCallbackHandler(w http.ResponseWriter, r *http.Request) { code := r.FormValue("code") - appengineContext := appengine.NewContext(r) - oauthTransport := &oauth.Transport{ - Config: &githubOauthConfig, - Transport: &urlfetch.Transport{Context: appengineContext}, - } + oauthTransport := githubOAuthTransport(r) token, err := oauthTransport.Exchange(code) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - tokenBytes, err := json.Marshal(token) - tokenEncoded := base64.StdEncoding.EncodeToString(tokenBytes) - redirectUrl, err := router.GetRoute("index").URL() - redirectParams := url.Values{} - redirectParams.Add("token", tokenEncoded) - redirectUrl.RawQuery = redirectParams.Encode() + tokenEncoded, err := encodeOAuthToken(token) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } + redirectUrl, _ := router.GetRoute("index").URL() + redirectParams := url.Values{} + redirectParams.Add("token", tokenEncoded) + redirectUrl.RawQuery = redirectParams.Encode() http.Redirect(w, r, redirectUrl.String(), http.StatusFound) } + +func githubOAuthTransport(r *http.Request) *oauth.Transport { + appengineContext := appengine.NewContext(r) + return &oauth.Transport{ + Config: &githubOauthConfig, + Transport: &urlfetch.Transport{Context: appengineContext}, + } +} + +func encodeOAuthToken(token *oauth.Token) (string, error) { + tokenBytes, err := json.Marshal(token) + if err != nil { + return "", err + } + return base64.StdEncoding.EncodeToString(tokenBytes), nil +} + +func decodeOAuthToken(tokenEncoded string) (*oauth.Token, error) { + tokenBytes, err := base64.URLEncoding.DecodeString(tokenEncoded) + if err != nil { + return nil, err + } + var token oauth.Token + err = json.Unmarshal(tokenBytes, &token) + if err != nil { + return nil, err + } + return &token, nil +}