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 }