109 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			109 lines
		
	
	
		
			2.6 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"
 | 
						|
 | 
						|
	"github.com/go-git/go-git/v5/plumbing"
 | 
						|
)
 | 
						|
 | 
						|
// CommitFromReader will generate a Commit from a provided reader
 | 
						|
// We will need this to interpret commits from cat-file
 | 
						|
func CommitFromReader(gitRepo *Repository, sha plumbing.Hash, reader io.Reader) (*Commit, error) {
 | 
						|
	commit := &Commit{
 | 
						|
		ID: sha,
 | 
						|
	}
 | 
						|
 | 
						|
	payloadSB := new(strings.Builder)
 | 
						|
	signatureSB := new(strings.Builder)
 | 
						|
	messageSB := new(strings.Builder)
 | 
						|
	message := false
 | 
						|
	pgpsig := false
 | 
						|
 | 
						|
	scanner := bufio.NewScanner(reader)
 | 
						|
	// Split by '\n' but include the '\n'
 | 
						|
	scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
 | 
						|
		if atEOF && len(data) == 0 {
 | 
						|
			return 0, nil, nil
 | 
						|
		}
 | 
						|
		if i := bytes.IndexByte(data, '\n'); i >= 0 {
 | 
						|
			// We have a full newline-terminated line.
 | 
						|
			return i + 1, data[0 : i+1], nil
 | 
						|
		}
 | 
						|
		// If we're at EOF, we have a final, non-terminated line. Return it.
 | 
						|
		if atEOF {
 | 
						|
			return len(data), data, nil
 | 
						|
		}
 | 
						|
		// Request more data.
 | 
						|
		return 0, nil, nil
 | 
						|
	})
 | 
						|
 | 
						|
	for scanner.Scan() {
 | 
						|
		line := scanner.Bytes()
 | 
						|
		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, plumbing.NewHash(string(data)))
 | 
						|
				_, _ = payloadSB.Write(line)
 | 
						|
			case "parent":
 | 
						|
				commit.Parents = append(commit.Parents, plumbing.NewHash(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)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	commit.CommitMessage = messageSB.String()
 | 
						|
	_, _ = payloadSB.WriteString(commit.CommitMessage)
 | 
						|
	commit.Signature = &CommitGPGSignature{
 | 
						|
		Signature: signatureSB.String(),
 | 
						|
		Payload:   payloadSB.String(),
 | 
						|
	}
 | 
						|
	if len(commit.Signature.Signature) == 0 {
 | 
						|
		commit.Signature = nil
 | 
						|
	}
 | 
						|
 | 
						|
	return commit, scanner.Err()
 | 
						|
}
 |