forked from Shiloh/githaven
2a565478d1
Unfortunately some old repositories can have tags with empty Tagger, Commit or Author. Go-Git variants will always have empty values for these whereas the native git variant leaves them at nil. The simplest solution is just to always have these set to empty Signatures. v156 migration also makes the incorrect assumption that these cannot be empty. Therefore add some handling to this and add logging and adjust broken logging elsewhere in this migration. Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
109 lines
2.5 KiB
Go
109 lines
2.5 KiB
Go
// Copyright 2020 The Gitea Authors. All rights reserved.
|
|
// Use of this source code is governed by a MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package git
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"io"
|
|
"strings"
|
|
)
|
|
|
|
// CommitFromReader will generate a Commit from a provided reader
|
|
// We need this to interpret commits from cat-file or cat-file --batch
|
|
//
|
|
// If used as part of a cat-file --batch stream you need to limit the reader to the correct size
|
|
func CommitFromReader(gitRepo *Repository, sha SHA1, reader io.Reader) (*Commit, error) {
|
|
commit := &Commit{
|
|
ID: sha,
|
|
Author: &Signature{},
|
|
Committer: &Signature{},
|
|
}
|
|
|
|
payloadSB := new(strings.Builder)
|
|
signatureSB := new(strings.Builder)
|
|
messageSB := new(strings.Builder)
|
|
message := false
|
|
pgpsig := false
|
|
|
|
bufReader, ok := reader.(*bufio.Reader)
|
|
if !ok {
|
|
bufReader = bufio.NewReader(reader)
|
|
}
|
|
|
|
readLoop:
|
|
for {
|
|
line, err := bufReader.ReadBytes('\n')
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
if message {
|
|
_, _ = messageSB.Write(line)
|
|
}
|
|
_, _ = payloadSB.Write(line)
|
|
break readLoop
|
|
}
|
|
return nil, err
|
|
}
|
|
if pgpsig {
|
|
if len(line) > 0 && line[0] == ' ' {
|
|
_, _ = signatureSB.Write(line[1:])
|
|
continue
|
|
} else {
|
|
pgpsig = false
|
|
}
|
|
}
|
|
|
|
if !message {
|
|
// This is probably not correct but is copied from go-gits interpretation...
|
|
trimmed := bytes.TrimSpace(line)
|
|
if len(trimmed) == 0 {
|
|
message = true
|
|
_, _ = payloadSB.Write(line)
|
|
continue
|
|
}
|
|
|
|
split := bytes.SplitN(trimmed, []byte{' '}, 2)
|
|
var data []byte
|
|
if len(split) > 1 {
|
|
data = split[1]
|
|
}
|
|
|
|
switch string(split[0]) {
|
|
case "tree":
|
|
commit.Tree = *NewTree(gitRepo, MustIDFromString(string(data)))
|
|
_, _ = payloadSB.Write(line)
|
|
case "parent":
|
|
commit.Parents = append(commit.Parents, MustIDFromString(string(data)))
|
|
_, _ = payloadSB.Write(line)
|
|
case "author":
|
|
commit.Author = &Signature{}
|
|
commit.Author.Decode(data)
|
|
_, _ = payloadSB.Write(line)
|
|
case "committer":
|
|
commit.Committer = &Signature{}
|
|
commit.Committer.Decode(data)
|
|
_, _ = payloadSB.Write(line)
|
|
case "gpgsig":
|
|
_, _ = signatureSB.Write(data)
|
|
_ = signatureSB.WriteByte('\n')
|
|
pgpsig = true
|
|
}
|
|
} else {
|
|
_, _ = messageSB.Write(line)
|
|
_, _ = payloadSB.Write(line)
|
|
}
|
|
}
|
|
commit.CommitMessage = messageSB.String()
|
|
commit.Signature = &CommitGPGSignature{
|
|
Signature: signatureSB.String(),
|
|
Payload: payloadSB.String(),
|
|
}
|
|
if len(commit.Signature.Signature) == 0 {
|
|
commit.Signature = nil
|
|
}
|
|
|
|
return commit, nil
|
|
}
|