// Copyright 2016 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 gitgraph import ( "bufio" "bytes" "context" "fmt" "os" "strings" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting") // GetCommitGraph return a list of commit (GraphItems) from all branchesfunc GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bool, branches, files []string) (*Graph, error) { format := "DATA:%D|%H|%ad|%h|%s" if page == 0 { page = 1 } args := make([]string, 0, 12+len(branches)+len(files)) args = append(args, "--graph", "--date-order", "--decorate=full") if hidePRRefs { args = append(args, "--exclude="+git.PullPrefix+"*") } if len(branches) == 0 { args = append(args, "--all") } args = append(args, "-C", "-M", fmt.Sprintf("-n %d", setting.UI.GraphMaxCommitNum*page), "--date=iso", fmt.Sprintf("--pretty=format:%s", format)) if len(branches) > 0 { args = append(args, branches...) } args = append(args, "--") if len(files) > 0 { args = append(args, files...) } graphCmd := git.NewCommand("log") graphCmd.AddArguments(args...) graph := NewGraph() stderr := new(strings.Builder) stdoutReader, stdoutWriter, err := os.Pipe() if err != nil { return nil, err } commitsToSkip := setting.UI.GraphMaxCommitNum * (page - 1) scanner := bufio.NewScanner(stdoutReader) if err := graphCmd.RunInDirTimeoutEnvFullPipelineFunc(nil, -1, r.Path, stdoutWriter, stderr, nil, func(ctx context.Context, cancel context.CancelFunc) error { _ = stdoutWriter.Close() defer stdoutReader.Close() parser := &Parser{} parser.firstInUse = -1 parser.maxAllowedColors = maxAllowedColors if maxAllowedColors > 0 { parser.availableColors = make([]int, maxAllowedColors) for i := range parser.availableColors { parser.availableColors[i] = i + 1 } } else { parser.availableColors = []int{1, 2} } for commitsToSkip > 0 && scanner.Scan() { line := scanner.Bytes() dataIdx := bytes.Index(line, []byte("DATA:")) if dataIdx < 0 { dataIdx = len(line) } starIdx := bytes.IndexByte(line, '*') if starIdx >= 0 && starIdx < dataIdx { commitsToSkip-- } parser.ParseGlyphs(line[:dataIdx]) } row := 0 // Skip initial non-commit lines for scanner.Scan() { line := scanner.Bytes() if bytes.IndexByte(line, '*') >= 0 { if err := parser.AddLineToGraph(graph, row, line); err != nil { cancel() return err } break } parser.ParseGlyphs(line) } for scanner.Scan() { row++ line := scanner.Bytes() if err := parser.AddLineToGraph(graph, row, line); err != nil { cancel() return err } } return scanner.Err() }); err != nil { return graph, err } return graph, nil}
// Copyright 2016 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 gitgraph
import (
"bufio"
"bytes"
"context"
"fmt"
"os"
"strings"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
)
// GetCommitGraph return a list of commit (GraphItems) from all branches
func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bool, branches, files []string) (*Graph, error) {
format := "DATA:%D|%H|%ad|%h|%s"
if page == 0 {
page = 1
}
args := make([]string, 0, 12+len(branches)+len(files))
args = append(args, "--graph", "--date-order", "--decorate=full")
if hidePRRefs {
args = append(args, "--exclude="+git.PullPrefix+"*")
}
if len(branches) == 0 {
args = append(args, "--all")
}
args = append(args,
"-C",
"-M",
fmt.Sprintf("-n %d", setting.UI.GraphMaxCommitNum*page),
"--date=iso",
fmt.Sprintf("--pretty=format:%s", format))
if len(branches) > 0 {
args = append(args, branches...)
}
args = append(args, "--")
if len(files) > 0 {
args = append(args, files...)
}
graphCmd := git.NewCommand("log")
graphCmd.AddArguments(args...)
graph := NewGraph()
stderr := new(strings.Builder)
stdoutReader, stdoutWriter, err := os.Pipe()
if err != nil {
return nil, err
}
commitsToSkip := setting.UI.GraphMaxCommitNum * (page - 1)
scanner := bufio.NewScanner(stdoutReader)
if err := graphCmd.RunInDirTimeoutEnvFullPipelineFunc(nil, -1, r.Path, stdoutWriter, stderr, nil, func(ctx context.Context, cancel context.CancelFunc) error {
_ = stdoutWriter.Close()
defer stdoutReader.Close()
parser := &Parser{}
parser.firstInUse = -1
parser.maxAllowedColors = maxAllowedColors
if maxAllowedColors > 0 {
parser.availableColors = make([]int, maxAllowedColors)
for i := range parser.availableColors {
parser.availableColors[i] = i + 1
}
} else {
parser.availableColors = []int{1, 2}
}
for commitsToSkip > 0 && scanner.Scan() {
line := scanner.Bytes()
dataIdx := bytes.Index(line, []byte("DATA:"))
if dataIdx < 0 {
dataIdx = len(line)
}
starIdx := bytes.IndexByte(line, '*')
if starIdx >= 0 && starIdx < dataIdx {
commitsToSkip--
}
parser.ParseGlyphs(line[:dataIdx])
}
row := 0
// Skip initial non-commit lines
for scanner.Scan() {
line := scanner.Bytes()
if bytes.IndexByte(line, '*') >= 0 {
if err := parser.AddLineToGraph(graph, row, line); err != nil {
cancel()
return err
}
break
}
parser.ParseGlyphs(line)
}
for scanner.Scan() {
row++
line := scanner.Bytes()
if err := parser.AddLineToGraph(graph, row, line); err != nil {
cancel()
return err
}
}
return scanner.Err()
}); err != nil {
return graph, err
}
return graph, nil
}