func recordHead(m *ingest.Message, repo *git.Repository) { head, err := repo.Head() if err != nil { log.Fatalf("Could not get repo HEAD") } oid := head.Target() hn, err := os.Hostname() if err != nil { log.Fatalln("Could not determine hostname for environment") } // be extra safe about cleaning the path wrt trailing slashes p := repo.Path() if strings.LastIndex(p, string(os.PathSeparator)) == len(p)-1 { p = path.Dir(path.Dir(p)) } else { p = path.Dir(p) } m.Add(semantic.LogicState{ Environment: semantic.EnvLink{ Address: semantic.Address{ Hostname: hn, }, }, Path: p, ID: semantic.LogicIdentiifer{ CommitStr: hex.EncodeToString(oid[:]), }, }) if head.IsBranch() { b := head.Branch() bn, _ := b.Name() m.Add(semantic.CommitMeta{ Sha1Str: hex.EncodeToString(oid[:]), Tags: make([]string, 0), Branches: []string{bn}, }) } }
func runPostCommit(cmd *cobra.Command, args []string) { repo := getRepoOrExit() head, err := repo.Head() if err != nil { log.Fatalf("Could not get repo HEAD") } commit, err := repo.LookupCommit(head.Target()) if err != nil { log.Fatalf("Could not find commit pointed at by HEAD") } ident, err := githelp.GetRepoIdent(repo) if err != nil { log.Fatalln("Failed to retrieve identifier for repository") } m := new(ingest.Message) m.Add(commitToSemanticForm(commit, ident)) recordHead(m, repo) sendMapToPipeviz(m, repo) }
func (gpe githubPushEvent) ToMessage(token string) *ingest.Message { msg := new(ingest.Message) client := http.Client{Timeout: 2 * time.Second} for _, c := range gpe.Commits { // don't include commits we know not to be new - make that someone else's job if !c.Distinct { continue } // take up to 50 bytes for subject subjlen := len(c.Message) if subjlen > 50 { subjlen = 50 } // github doesn't include parent commit list in push payload (UGHHHH). so, call out for it. // TODO spawn a goroutine per commit to do these in parallel url := strings.Replace(gpe.Repository.GitCommitsURL, "{/sha}", "/"+c.Sha, 1) req, err := http.NewRequest("GET", url, nil) if err != nil { logrus.WithFields(logrus.Fields{ "system": "pvproxy", "err": err, "sha1": c.Sha, }).Warn("Error while creating request for additional information from github; skipping commit.") continue } if token != "" { req.Header.Set("Authentication", "token "+token) } resp, err := client.Do(req) if err != nil { // just drop the problematic commit logrus.WithFields(logrus.Fields{ "system": "pvproxy", "err": err, "sha1": c.Sha, }).Warn("Request to github to retrieve commit parent info failed; commit dropped.") continue } if !statusIsOK(resp) { logrus.WithFields(logrus.Fields{ "system": "pvproxy", "status": resp.StatusCode, "sha1": c.Sha, }).Warn("Github responded with non-2xx response when requesting parent commit data.") continue } // skip err here, it's effectively caught by the json unmarshaler bod, _ := ioutil.ReadAll(resp.Body) var jmap interface{} err = json.Unmarshal(bod, &jmap) if err != nil { logrus.WithFields(logrus.Fields{ "system": "pvproxy", "err": err, "sha1": c.Sha, }).Warn("Bad JSON response from github when requesting commit parent info; commit dropped.") continue } var parents []string for _, iparent := range jmap.(map[string]interface{})["parents"].([]interface{}) { parent := iparent.(map[string]interface{}) parents = append(parents, parent["sha"].(string)) } t, err := time.Parse(time.RFC3339, c.Timestamp) if err != nil { logrus.WithFields(logrus.Fields{ "system": "pvproxy", "err": err, "datestring": c.Timestamp, "sha1": c.Sha, }).Warn("Error on parsing date field in github payload; commit dropped.") } msg.Add(semantic.Commit{ Sha1Str: c.Sha, Subject: c.Message[:subjlen], Author: fmt.Sprintf("%q <%s>", c.Author.Name, c.Author.Email), Date: t.Format(gitDateFormat), Repository: gpe.Repository.Ident, ParentsStr: parents, }) } if gpe.Ref[:11] == "refs/heads/" { msg.Add(semantic.CommitMeta{ Sha1Str: gpe.HeadCommit.Sha, Branches: []string{gpe.Ref[11:]}, }) } else if gpe.Ref[:10] == "refs/tags/" { msg.Add(semantic.CommitMeta{ Sha1Str: gpe.HeadCommit.Sha, Tags: []string{gpe.Ref[10:]}, }) } return msg }
func syncHistory(repo *git.Repository, all bool) { var err error var ident string msg := new(ingest.Message) if all { ident, err = githelp.GetRepoIdent(repo) if err != nil { log.Fatalf("Failed to retrieve a stable identifier for this repository; cannot formulate commits correctly. Aborting.") } } cvisited := make(map[git.Oid]struct{}) iter, err := repo.NewReferenceIterator() if err != nil { log.Fatalln("Error while creating reference iterator:", err) } // For simplicity, create a revwalker now even if we don't use it later w, err := repo.Walk() if err != nil { log.Fatalln("Could not create revwalker iterator:", err) } w.Sorting(git.SortTopological) //defer w.Free() for ref, err := iter.Next(); err == nil; ref, err = iter.Next() { // in func for easy defer of Free() func(r *git.Reference, m *ingest.Message) { //defer r.Free() oid := r.Target() if !r.IsBranch() && !r.IsTag() { return } if r.IsBranch() { bn, _ := r.Branch().Name() w.Push(oid) m.Add(semantic.CommitMeta{ Sha1Str: hex.EncodeToString(oid[:]), Tags: make([]string, 0), Branches: []string{bn}, }) } else if r.IsTag() { w.Push(oid) m.Add(semantic.CommitMeta{ Sha1Str: hex.EncodeToString(oid[:]), // TODO this still emits the refs/tags/<name> form, ugh Tags: []string{r.Name()}, Branches: make([]string, 0), }) } else { log.Fatalf("Ref %s is neither branch nor tag - wtf\n", r.Name()) } }(ref, msg) } //iter.Free() if err != nil { if !git.IsErrorCode(err, git.ErrIterOver) { //if gerr, ok := err.(*git.GitError); !ok || gerr.Code != git.ErrIterOver { gerr := err.(*git.GitError) log.Fatalf("Iteration through repository refs terminated with unexpected error (code: %d, message: %q)\n", gerr.Code, gerr.Message) } } if all { w.Iterate(func(c *git.Commit) bool { //defer c.Free() if _, exists := cvisited[*c.Id()]; exists { return false } cvisited[*c.Id()] = struct{}{} msg.Add(commitToSemanticForm(c, ident)) return true }) } //w.Free() recordHead(msg, repo) sendMapToPipeviz(msg, repo) }