github.com/hashicorp/packer@v1.14.3/internal/hcp/registry/metadata/vcs.go (about)

     1  package metadata
     2  
     3  import (
     4  	"log"
     5  	"os"
     6  
     7  	gt "github.com/go-git/go-git/v5"
     8  )
     9  
    10  type MetadataProvider interface {
    11  	Detect() error
    12  	Details() map[string]interface{}
    13  	Type() string
    14  }
    15  
    16  type Git struct {
    17  	repo *gt.Repository
    18  }
    19  
    20  func (g *Git) Detect() error {
    21  	wd, err := os.Getwd()
    22  	if err != nil {
    23  		log.Printf("[ERROR] unable to retrieve current directory: %s", err)
    24  		return err
    25  	}
    26  
    27  	repo, err := gt.PlainOpenWithOptions(wd, &gt.PlainOpenOptions{DetectDotGit: true})
    28  	if err != nil {
    29  		return err
    30  	}
    31  
    32  	g.repo = repo
    33  	return nil
    34  }
    35  
    36  func (g *Git) hasUncommittedChanges() bool {
    37  	worktree, err := g.repo.Worktree()
    38  	if err != nil {
    39  		log.Printf("[ERROR] failed to get the git worktree: %s", err)
    40  		return false
    41  	}
    42  
    43  	status, err := worktree.Status()
    44  	if err != nil {
    45  		log.Printf("[ERROR] failed to get the git worktree status: %s", err)
    46  		return false
    47  	}
    48  	return !status.IsClean()
    49  }
    50  
    51  func (g *Git) Type() string {
    52  	return "git"
    53  }
    54  
    55  func (g *Git) Details() map[string]interface{} {
    56  	headRef, err := g.repo.Head()
    57  	if err != nil {
    58  		log.Printf("[ERROR] failed to get reference to git HEAD: %s", err)
    59  		return nil
    60  	}
    61  
    62  	resp := map[string]interface{}{
    63  		"ref": headRef.Name().Short(),
    64  	}
    65  
    66  	commit, err := g.repo.CommitObject(headRef.Hash())
    67  	if err != nil {
    68  		log.Printf("[ERROR] failed to get the git commit hash: %s", err)
    69  	} else {
    70  		resp["commit"] = commit.Hash.String()
    71  		resp["author"] = commit.Author.Name + " <" + commit.Author.Email + ">"
    72  	}
    73  
    74  	resp["has_uncommitted_changes"] = g.hasUncommittedChanges()
    75  	return resp
    76  }
    77  
    78  func GetVcsMetadata() map[string]interface{} {
    79  	vcsSystems := []MetadataProvider{
    80  		&Git{},
    81  	}
    82  
    83  	for _, vcs := range vcsSystems {
    84  		err := vcs.Detect()
    85  		if err == nil {
    86  			return map[string]interface{}{
    87  				"type":    vcs.Type(),
    88  				"details": vcs.Details(),
    89  			}
    90  		}
    91  	}
    92  
    93  	return nil
    94  }