初始提交: Gitea 项目代码
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
const (
|
||||
commitHeaderGpgsig = "gpgsig"
|
||||
commitHeaderGpgsigSha256 = "gpgsig-sha256"
|
||||
)
|
||||
|
||||
func assignCommitFields(gitRepo *Repository, commit *Commit, headerKey string, headerValue []byte) error {
|
||||
if len(headerValue) > 0 && headerValue[len(headerValue)-1] == '\n' {
|
||||
headerValue = headerValue[:len(headerValue)-1] // remove trailing newline
|
||||
}
|
||||
switch headerKey {
|
||||
case "tree":
|
||||
objID, err := NewIDFromString(string(headerValue))
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid tree ID %q: %w", string(headerValue), err)
|
||||
}
|
||||
commit.Tree = *NewTree(gitRepo, objID)
|
||||
case "parent":
|
||||
objID, err := NewIDFromString(string(headerValue))
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid parent ID %q: %w", string(headerValue), err)
|
||||
}
|
||||
commit.Parents = append(commit.Parents, objID)
|
||||
case "author":
|
||||
commit.Author.Decode(headerValue)
|
||||
case "committer":
|
||||
commit.Committer.Decode(headerValue)
|
||||
case commitHeaderGpgsig, commitHeaderGpgsigSha256:
|
||||
// if there are duplicate "gpgsig" and "gpgsig-sha256" headers, then the signature must have already been invalid
|
||||
// so we don't need to handle duplicate headers here
|
||||
commit.Signature = &CommitSignature{Signature: string(headerValue)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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, objectID ObjectID, reader io.Reader) (*Commit, error) {
|
||||
commit := &Commit{
|
||||
ID: objectID,
|
||||
Author: &Signature{},
|
||||
Committer: &Signature{},
|
||||
}
|
||||
|
||||
bufReader := bufio.NewReader(reader)
|
||||
inHeader := true
|
||||
var payloadSB, messageSB bytes.Buffer
|
||||
var headerKey string
|
||||
var headerValue []byte
|
||||
for {
|
||||
line, err := bufReader.ReadBytes('\n')
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, fmt.Errorf("unable to read commit %q: %w", objectID.String(), err)
|
||||
}
|
||||
if len(line) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if inHeader {
|
||||
inHeader = !(len(line) == 1 && line[0] == '\n') // still in header if line is not just a newline
|
||||
k, v, _ := bytes.Cut(line, []byte{' '})
|
||||
if len(k) != 0 || !inHeader {
|
||||
if headerKey != "" {
|
||||
if err = assignCommitFields(gitRepo, commit, headerKey, headerValue); err != nil {
|
||||
return nil, fmt.Errorf("unable to parse commit %q: %w", objectID.String(), err)
|
||||
}
|
||||
}
|
||||
headerKey = string(k) // it also resets the headerValue to empty string if not inHeader
|
||||
headerValue = v
|
||||
} else {
|
||||
headerValue = append(headerValue, v...)
|
||||
}
|
||||
if headerKey != commitHeaderGpgsig && headerKey != commitHeaderGpgsigSha256 {
|
||||
_, _ = payloadSB.Write(line)
|
||||
}
|
||||
} else {
|
||||
_, _ = messageSB.Write(line)
|
||||
_, _ = payloadSB.Write(line)
|
||||
}
|
||||
}
|
||||
|
||||
commit.MessageRaw = messageSB.String()
|
||||
if commit.Signature != nil {
|
||||
commit.Signature.Payload = payloadSB.String()
|
||||
}
|
||||
return commit, nil
|
||||
}
|
||||
Reference in New Issue
Block a user