Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
2.5 KiB
108 lines
2.5 KiB
// 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 |
|
}
|
|
|