github.com/vlal/goveralls@v0.0.2-0.20171114042957-b71a1e4855f8/gitinfo.go (about)

     1  package main
     2  
     3  import (
     4  	"log"
     5  	"os"
     6  	"os/exec"
     7  	"regexp"
     8  	"strings"
     9  )
    10  
    11  var remotesRE = regexp.MustCompile(`^(\S+)\s+(\S+)`)
    12  
    13  // A Head object encapsulates information about the HEAD revision of a git repo.
    14  type Head struct {
    15  	Id             string `json:"id"`
    16  	AuthorName     string `json:"author_name,omitempty"`
    17  	AuthorEmail    string `json:"author_email,omitempty"`
    18  	CommitterName  string `json:"committer_name,omitempty"`
    19  	CommitterEmail string `json:"committer_email,omitempty"`
    20  	Message        string `json:"message"`
    21  }
    22  
    23  // A Remote object encapsulates information about a remote of a git repo.
    24  type Remote struct {
    25  	Name string `json:"name"`
    26  	Url  string `json:"url"`
    27  }
    28  
    29  // A Git object encapsulates information about a git repo.
    30  type Git struct {
    31  	Head    Head      `json:"head"`
    32  	Branch  string    `json:"branch"`
    33  	Remotes []*Remote `json:"remotes,omitempty"`
    34  }
    35  
    36  // collectGitInfo runs several git commands to compose a Git object.
    37  func collectGitInfo() *Git {
    38  	gitCmds := map[string][]string{
    39  		"id":      {"rev-parse", "HEAD"},
    40  		"branch":  {"rev-parse", "--abbrev-ref", "HEAD"},
    41  		"aname":   {"log", "-1", "--pretty=%aN"},
    42  		"aemail":  {"log", "-1", "--pretty=%aE"},
    43  		"cname":   {"log", "-1", "--pretty=%cN"},
    44  		"cemail":  {"log", "-1", "--pretty=%cE"},
    45  		"message": {"log", "-1", "--pretty=%s"},
    46  		"remotes": {"remote", "-v"},
    47  	}
    48  	results := map[string]string{}
    49  	remotes := map[string]Remote{}
    50  	gitPath, err := exec.LookPath("git")
    51  	if err != nil {
    52  		log.Fatal(err)
    53  	}
    54  	for key, args := range gitCmds {
    55  		if key == "branch" {
    56  			if envBranch := loadBranchFromEnv(); envBranch != "" {
    57  				results[key] = envBranch
    58  				continue
    59  			}
    60  		}
    61  
    62  		cmd := exec.Command(gitPath, args...)
    63  		ret, err := cmd.CombinedOutput()
    64  		if err != nil {
    65  			if strings.Contains(string(ret), `Not a git repository`) {
    66  				return nil
    67  			}
    68  			log.Fatalf("%v: %v", err, string(ret))
    69  		}
    70  		s := string(ret)
    71  		s = strings.TrimRight(s, "\n")
    72  		results[key] = s
    73  	}
    74  	for _, line := range strings.Split(results["remotes"], "\n") {
    75  		matches := remotesRE.FindAllStringSubmatch(line, -1)
    76  		if len(matches) != 1 {
    77  			continue
    78  		}
    79  		if len(matches[0]) != 3 {
    80  			continue
    81  		}
    82  		name := matches[0][1]
    83  		url := matches[0][2]
    84  		r := Remote{
    85  			Name: name,
    86  			Url:  url,
    87  		}
    88  		remotes[name] = r
    89  	}
    90  	h := Head{
    91  		Id:             results["id"],
    92  		AuthorName:     results["aname"],
    93  		AuthorEmail:    results["aemail"],
    94  		CommitterName:  results["cname"],
    95  		CommitterEmail: results["cemail"],
    96  		Message:        results["message"],
    97  	}
    98  	g := &Git{
    99  		Head:   h,
   100  		Branch: results["branch"],
   101  	}
   102  	for _, r := range remotes {
   103  		g.Remotes = append(g.Remotes, &r)
   104  	}
   105  	return g
   106  }
   107  
   108  func loadBranchFromEnv() string {
   109  	varNames := []string{"GIT_BRANCH", "CIRCLE_BRANCH", "TRAVIS_BRANCH", "CI_BRANCH", "APPVEYOR_REPO_BRANCH"}
   110  	for _, varName := range varNames {
   111  		if branch := os.Getenv(varName); branch != "" {
   112  			return branch
   113  		}
   114  	}
   115  	return ""
   116  }