github.com/driusan/dgit@v0.0.0-20221118233547-f39f0c15edbb/git/committree.go (about)

     1  package git
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"os"
     7  	"strconv"
     8  	//	"strings"
     9  	"regexp"
    10  	"time"
    11  )
    12  
    13  type GPGKeyId string
    14  type CommitTreeOptions struct {
    15  	GPGKey GPGKeyId
    16  
    17  	NoGPGSign bool
    18  }
    19  
    20  func parseDate(str string) (time.Time, error) {
    21  	// RFC 2822
    22  	if t, err := time.Parse("Mon, 02 Jan 2006 15:04:05 -0700", str); err == nil {
    23  		return t, nil
    24  	}
    25  	// ISO 8601
    26  	if t, err := time.Parse("2006-01-02T15:04:05", str); err == nil {
    27  		return t, nil
    28  	}
    29  	// YYYY-MM-DD HH:MM with a separate TZ environment variable
    30  	if t, err := time.Parse("2006-01-02 15:04", str); err == nil {
    31  		// FIXME: Investigate whether git and Go have the same interpretation
    32  		// of locations. This is probably not accurate.
    33  		loc, err := time.LoadLocation(os.Getenv("TZ"))
    34  		if err != nil {
    35  			return time.Time{}, err
    36  		}
    37  		return t.In(loc), nil
    38  	}
    39  
    40  	// Git Internal format doesn't parse with time.Parse, so we manually parse it..
    41  	re, err := regexp.Compile("([0-9]+) ([+-])([0-9]{4})")
    42  	if err != nil {
    43  		panic(err)
    44  	}
    45  	if pieces := re.FindStringSubmatch(str); len(pieces) == 4 {
    46  		// Create the time seconds since the epoch
    47  		utime, _ := strconv.Atoi(pieces[1])
    48  		t := time.Unix(int64(utime), 0)
    49  
    50  		// Take the hour of the timezone and convert it to seconds
    51  		// from UTC.
    52  		// FIXME: This should deal with half hour timezones
    53  		// properly.
    54  		tz, _ := strconv.Atoi(pieces[3][0:2])
    55  		if pieces[2] == "-" {
    56  			tz *= -1
    57  		}
    58  		tz *= 60 * 60
    59  		zone := time.FixedZone(pieces[2]+pieces[3], tz)
    60  		return t.In(zone), nil
    61  	}
    62  	return time.Time{}, fmt.Errorf("Unsupported date format")
    63  }
    64  
    65  func CommitTree(c *Client, opts CommitTreeOptions, tree Treeish, parents []CommitID, message string) (CommitID, error) {
    66  	content := bytes.NewBuffer(nil)
    67  
    68  	treeid, err := tree.TreeID(c)
    69  	if err != nil {
    70  		return CommitID{}, err
    71  	}
    72  	fmt.Fprintf(content, "tree %s\n", treeid)
    73  	for _, val := range parents {
    74  		fmt.Fprintf(content, "parent %s\n", val)
    75  	}
    76  
    77  	var t time.Time
    78  	var author, committer Person
    79  	if date := os.Getenv("GIT_AUTHOR_DATE"); date != "" {
    80  		t, err := parseDate(date)
    81  		if err != nil {
    82  			return CommitID{}, err
    83  		}
    84  		author = c.GetAuthor(&t)
    85  	} else {
    86  		t = time.Now()
    87  		author = c.GetAuthor(&t)
    88  	}
    89  	var committerError error
    90  	if date := os.Getenv("GIT_COMMITTER_DATE"); date != "" {
    91  		t, err := parseDate(date)
    92  		if err != nil {
    93  			return CommitID{}, err
    94  		}
    95  		committer, committerError = c.GetCommitter(&t)
    96  	} else {
    97  		t = time.Now()
    98  		committer, committerError = c.GetCommitter(&t)
    99  	}
   100  
   101  	fmt.Fprintf(content, "author %s\n", author)
   102  	fmt.Fprintf(content, "committer %s\n\n", committer)
   103  	fmt.Fprintf(content, "%s", message)
   104  	sha1, err := c.WriteObject("commit", content.Bytes())
   105  	if err != nil {
   106  		return CommitID(sha1), err
   107  	}
   108  	return CommitID(sha1), committerError
   109  }