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()
 | |
| }
 |