File: rawdiff.go

package info (click to toggle)
gitlab-shell 14.35.0%2Bds1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 23,652 kB
  • sloc: ruby: 1,129; makefile: 583; sql: 391; sh: 384
file content (79 lines) | stat: -rw-r--r-- 1,716 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package rawdiff

import (
	"bufio"
	"fmt"
	"io"
)

// Diff represents a `git diff --raw` entry.
type Diff struct {
	// The naming of the fields below follows the "RAW DIFF FORMAT" of `git
	// diff`.

	SrcMode string
	DstMode string
	SrcSHA  string
	DstSHA  string
	Status  string
	SrcPath string
	DstPath string // optional!
}

// Parser is a parser for the "-z" variant of the "RAW DIFF FORMAT"
// documented in `git help diff`.
type Parser struct {
	r *bufio.Reader
}

// NewParser returns a new Parser instance. The reader must contain
// output from `git diff --raw -z`.
func NewParser(r io.Reader) *Parser {
	return &Parser{r: bufio.NewReader(r)}
}

// NextDiff returns the next raw diff. If there are no more diffs, the
// error is io.EOF.
func (p *Parser) NextDiff() (*Diff, error) {
	c, err := p.r.ReadByte()
	if err != nil {
		return nil, err
	}

	if c != ':' {
		return nil, fmt.Errorf("expected leading colon in raw diff line")
	}

	d := &Diff{}

	for _, field := range []*string{&d.SrcMode, &d.DstMode, &d.SrcSHA, &d.DstSHA} {
		if *field, err = p.readStringChop(' '); err != nil {
			return nil, err
		}
	}

	for _, field := range []*string{&d.Status, &d.SrcPath} {
		if *field, err = p.readStringChop(0); err != nil {
			return nil, err
		}
	}

	if len(d.Status) > 0 && (d.Status[0] == 'C' || d.Status[0] == 'R') {
		if d.DstPath, err = p.readStringChop(0); err != nil {
			return nil, err
		}
	}

	return d, nil
}

// readStringChop combines bufio.Reader.ReadString with removing the
// trailing delimiter.
func (p *Parser) readStringChop(delim byte) (string, error) {
	s, err := p.r.ReadString(delim)
	if err != nil {
		return "", fmt.Errorf("read raw diff: %w", err)
	}

	return s[:len(s)-1], nil
}