Version: v0.6.1 Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Sep 28, 2020 License: MIT Imports: 9 Imported by: 31



Package diff provides a parser for unified diffs.



This section is empty.


View Source
var (
	// ErrNoFileHeader is when a file unified diff has no file header
	// (i.e., the lines that begin with "---" and "+++").
	ErrNoFileHeader = errors.New("expected file header, got EOF")

	// ErrBadFileHeader is when a file unified diff has a malformed
	// file header (i.e., the lines that begin with "---" and "+++").
	ErrBadFileHeader = errors.New("bad file header")

	// ErrExtendedHeadersEOF is when an EOF was encountered while reading extended file headers, which means that there were no ---/+++ headers encountered before hunks (if any) began.
	ErrExtendedHeadersEOF = errors.New("expected file header while reading extended headers, got EOF")

	// ErrBadOnlyInMessage is when a file have a malformed `only in` message
	// Should be in format `Only in {source}: {filename}`
	ErrBadOnlyInMessage = errors.New("bad 'only in' message")
View Source
var ErrNoHunkHeader = errors.New("no hunk header")

ErrNoHunkHeader indicates that a unified diff hunk header was expected but not found during parsing.


func PrintFileDiff

func PrintFileDiff(d *FileDiff) ([]byte, error)

PrintFileDiff prints a FileDiff in unified diff format.

TODO(sqs): handle escaping whitespace/etc. chars in filenames

func PrintHunks

func PrintHunks(hunks []*Hunk) ([]byte, error)

PrintHunks prints diff hunks in unified diff format.

func PrintMultiFileDiff

func PrintMultiFileDiff(ds []*FileDiff) ([]byte, error)

PrintMultiFileDiff prints a multi-file diff in unified diff format.


type ErrBadHunkHeader

type ErrBadHunkHeader struct {
	// contains filtered or unexported fields

ErrBadHunkHeader indicates that a malformed unified diff hunk header was encountered during parsing.

func (*ErrBadHunkHeader) Error

func (e *ErrBadHunkHeader) Error() string

type ErrBadHunkLine

type ErrBadHunkLine struct {
	Line []byte

ErrBadHunkLine is when a line not beginning with ' ', '-', '+', or '\' is encountered while reading a hunk. In the context of reading a single hunk or file, it is an unexpected error. In a multi-file diff, however, it indicates that the current file's diff is complete (and remaining diff data will describe another file unified diff).

func (*ErrBadHunkLine) Error

func (e *ErrBadHunkLine) Error() string

type FileDiff

type FileDiff struct {
	// the original name of the file
	OrigName string
	// the original timestamp (nil if not present)
	OrigTime *time.Time
	// the new name of the file (often same as OrigName)
	NewName string
	// the new timestamp (nil if not present)
	NewTime *time.Time
	// extended header lines (e.g., git's "new mode <mode>", "rename from <path>", etc.)
	Extended []string
	// hunks that were changed from orig to new
	Hunks []*Hunk

A FileDiff represents a unified diff for a single file.

A file unified diff has a header that resembles the following:

--- oldname	2009-10-11 15:12:20.000000000 -0700
+++ newname	2009-10-11 15:12:30.000000000 -0700

func ParseFileDiff

func ParseFileDiff(diff []byte) (*FileDiff, error)

ParseFileDiff parses a file unified diff.

func ParseMultiFileDiff

func ParseMultiFileDiff(diff []byte) ([]*FileDiff, error)

ParseMultiFileDiff parses a multi-file unified diff. It returns an error if parsing failed as a whole, but does its best to parse as many files in the case of per-file errors. If it cannot detect when the diff of the next file begins, the hunks are added to the FileDiff of the previous file.

func (*FileDiff) Stat

func (d *FileDiff) Stat() Stat

Stat computes the number of lines added/changed/deleted in all hunks in this file's diff.

type FileDiffReader

type FileDiffReader struct {
	// contains filtered or unexported fields

FileDiffReader reads a unified file diff.

func NewFileDiffReader

func NewFileDiffReader(r io.Reader) *FileDiffReader

NewFileDiffReader returns a new FileDiffReader that reads a file unified diff.

func (*FileDiffReader) HunksReader

func (r *FileDiffReader) HunksReader() *HunksReader

HunksReader returns a new HunksReader that reads hunks from r. The HunksReader's line and offset (used in error messages) is set to start where the file diff header ended (which means errors have the correct position information).

func (*FileDiffReader) Read

func (r *FileDiffReader) Read() (*FileDiff, error)

Read reads a file unified diff, including headers and hunks, from r.

func (*FileDiffReader) ReadAllHeaders

func (r *FileDiffReader) ReadAllHeaders() (*FileDiff, error)

ReadAllHeaders reads the file headers and extended headers (if any) from a file unified diff. It does not read hunks, and the returned FileDiff's Hunks field is nil. To read the hunks, call the (*FileDiffReader).HunksReader() method to get a HunksReader and read hunks from that.

func (*FileDiffReader) ReadExtendedHeaders

func (r *FileDiffReader) ReadExtendedHeaders() ([]string, error)

ReadExtendedHeaders reads the extended header lines, if any, from a unified diff file (e.g., git's "diff --git a/foo.go b/foo.go", "new mode <mode>", "rename from <path>", etc.).

func (*FileDiffReader) ReadFileHeaders

func (r *FileDiffReader) ReadFileHeaders() (origName, newName string, origTimestamp, newTimestamp *time.Time, err error)

ReadFileHeaders reads the unified file diff header (the lines that start with "---" and "+++" with the orig/new file names and timestamps). Or which starts with "Only in " with dir path and filename. "Only in" message is supported in POSIX locale: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/diff.html#tag_20_34_10

type Hunk

type Hunk struct {
	// starting line number in original file
	OrigStartLine int32
	// number of lines the hunk applies to in the original file
	OrigLines int32
	// if > 0, then the original file had a 'No newline at end of file' mark at this offset
	OrigNoNewlineAt int32
	// starting line number in new file
	NewStartLine int32
	// number of lines the hunk applies to in the new file
	NewLines int32
	// optional section heading
	Section string
	// 0-indexed line offset in unified file diff (including section headers); this is
	// only set when Hunks are read from entire file diff (i.e., when ReadAllHunks is
	// called) This accounts for hunk headers, too, so the StartPosition of the first
	// hunk will be 1.
	StartPosition int32
	// hunk body (lines prefixed with '-', '+', or ' ')
	Body []byte

A Hunk represents a series of changes (additions or deletions) in a file's unified diff.

func ParseHunks

func ParseHunks(diff []byte) ([]*Hunk, error)

ParseHunks parses hunks from a unified diff. The diff must consist only of hunks and not include a file header; if it has a file header, use ParseFileDiff.

func (*Hunk) Stat

func (h *Hunk) Stat() Stat

Stat computes the number of lines added/changed/deleted in this hunk.

type HunksReader

type HunksReader struct {
	// contains filtered or unexported fields

A HunksReader reads hunks from a unified diff.

func NewHunksReader

func NewHunksReader(r io.Reader) *HunksReader

NewHunksReader returns a new HunksReader that reads unified diff hunks from r.

func (*HunksReader) ReadAllHunks

func (r *HunksReader) ReadAllHunks() ([]*Hunk, error)

ReadAllHunks reads all remaining hunks from r. A successful call returns err == nil, not err == EOF. Because ReadAllHunks is defined to read until EOF, it does not treat end of file as an error to be reported.

func (*HunksReader) ReadHunk

func (r *HunksReader) ReadHunk() (*Hunk, error)

ReadHunk reads one hunk from r. If there are no more hunks, it returns error io.EOF.

type MultiFileDiffReader

type MultiFileDiffReader struct {
	// contains filtered or unexported fields

MultiFileDiffReader reads a multi-file unified diff.

func NewMultiFileDiffReader

func NewMultiFileDiffReader(r io.Reader) *MultiFileDiffReader

NewMultiFileDiffReader returns a new MultiFileDiffReader that reads a multi-file unified diff from r.

func (*MultiFileDiffReader) ReadAllFiles

func (r *MultiFileDiffReader) ReadAllFiles() ([]*FileDiff, error)

ReadAllFiles reads all file unified diffs (including headers and all hunks) remaining in r.

func (*MultiFileDiffReader) ReadFile

func (r *MultiFileDiffReader) ReadFile() (*FileDiff, error)

ReadFile reads the next file unified diff (including headers and all hunks) from r. If there are no more files in the diff, it returns error io.EOF.

type OverflowError

type OverflowError string

OverflowError is returned when we have overflowed into the start of the next file while reading extended headers.

func (OverflowError) Error

func (e OverflowError) Error() string

type ParseError

type ParseError struct {
	Line   int   // Line where the error occurred
	Offset int64 // Offset where the error occurred
	Err    error // The actual error

A ParseError is a description of a unified diff syntax error.

func (*ParseError) Error

func (e *ParseError) Error() string

type Stat

type Stat struct {
	// number of lines added
	Added int32
	// number of lines changed
	Changed int32
	// number of lines deleted
	Deleted int32

A Stat is a diff stat that represents the number of lines added/changed/deleted.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL