aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/sourcegraph/go-diff
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2025-01-22 16:07:17 +0100
committerTaras Madan <tarasmadan@google.com>2025-01-23 10:42:36 +0000
commit7b4377ad9d8a7205416df8d6217ef2b010f89481 (patch)
treee6fec4fd12ff807a16d847923f501075bf71d16c /vendor/github.com/sourcegraph/go-diff
parent475a4c203afb8b7d3af51c4fd32bb170ff32a45e (diff)
vendor: delete
Diffstat (limited to 'vendor/github.com/sourcegraph/go-diff')
-rw-r--r--vendor/github.com/sourcegraph/go-diff/LICENSE46
-rw-r--r--vendor/github.com/sourcegraph/go-diff/diff/diff.go136
-rw-r--r--vendor/github.com/sourcegraph/go-diff/diff/doc.go2
-rw-r--r--vendor/github.com/sourcegraph/go-diff/diff/parse.go865
-rw-r--r--vendor/github.com/sourcegraph/go-diff/diff/print.go141
-rw-r--r--vendor/github.com/sourcegraph/go-diff/diff/reader_util.go120
6 files changed, 0 insertions, 1310 deletions
diff --git a/vendor/github.com/sourcegraph/go-diff/LICENSE b/vendor/github.com/sourcegraph/go-diff/LICENSE
deleted file mode 100644
index 5ba1c4436..000000000
--- a/vendor/github.com/sourcegraph/go-diff/LICENSE
+++ /dev/null
@@ -1,46 +0,0 @@
-Copyright (c) 2014 Sourcegraph, Inc.
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
------------------------------------------------------------------
-
-Portions adapted from python-unidiff:
-
-Copyright (c) 2012 Matias Bordese
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
-OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/github.com/sourcegraph/go-diff/diff/diff.go b/vendor/github.com/sourcegraph/go-diff/diff/diff.go
deleted file mode 100644
index 81aa65570..000000000
--- a/vendor/github.com/sourcegraph/go-diff/diff/diff.go
+++ /dev/null
@@ -1,136 +0,0 @@
-package diff
-
-import (
- "bytes"
- "time"
-)
-
-// 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
-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 Hunk represents a series of changes (additions or deletions) in a file's
-// unified diff.
-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 Stat is a diff stat that represents the number of lines added/changed/deleted.
-type Stat struct {
- // number of lines added
- Added int32
- // number of lines changed
- Changed int32
- // number of lines deleted
- Deleted int32
-}
-
-// Stat computes the number of lines added/changed/deleted in all
-// hunks in this file's diff.
-func (d *FileDiff) Stat() Stat {
- total := Stat{}
- for _, h := range d.Hunks {
- total.add(h.Stat())
- }
- return total
-}
-
-// Stat computes the number of lines added/changed/deleted in this
-// hunk.
-func (h *Hunk) Stat() Stat {
- lines := bytes.Split(h.Body, []byte{'\n'})
- var last byte
- st := Stat{}
- for _, line := range lines {
- if len(line) == 0 {
- last = 0
- continue
- }
- switch line[0] {
- case '-':
- if last == '+' {
- st.Added--
- st.Changed++
- last = 0 // next line can't change this one since this is already a change
- } else {
- st.Deleted++
- last = line[0]
- }
- case '+':
- if last == '-' {
- st.Deleted--
- st.Changed++
- last = 0 // next line can't change this one since this is already a change
- } else {
- st.Added++
- last = line[0]
- }
- default:
- last = 0
- }
- }
- return st
-}
-
-var (
- hunkPrefix = []byte("@@ ")
- onlyInMessagePrefix = []byte("Only in ")
-)
-
-const hunkHeader = "@@ -%d,%d +%d,%d @@"
-const onlyInMessage = "Only in %s: %s\n"
-
-// diffTimeParseLayout is the layout used to parse the time in unified diff file
-// header timestamps.
-// See https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html.
-const diffTimeParseLayout = "2006-01-02 15:04:05 -0700"
-
-// Apple's diff is based on freebsd diff, which uses a timestamp format that does
-// not include the timezone offset.
-const diffTimeParseWithoutTZLayout = "2006-01-02 15:04:05"
-
-// diffTimeFormatLayout is the layout used to format (i.e., print) the time in unified diff file
-// header timestamps.
-// See https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html.
-const diffTimeFormatLayout = "2006-01-02 15:04:05.000000000 -0700"
-
-func (s *Stat) add(o Stat) {
- s.Added += o.Added
- s.Changed += o.Changed
- s.Deleted += o.Deleted
-}
diff --git a/vendor/github.com/sourcegraph/go-diff/diff/doc.go b/vendor/github.com/sourcegraph/go-diff/diff/doc.go
deleted file mode 100644
index 12fe96a07..000000000
--- a/vendor/github.com/sourcegraph/go-diff/diff/doc.go
+++ /dev/null
@@ -1,2 +0,0 @@
-// Package diff provides a parser for unified diffs.
-package diff
diff --git a/vendor/github.com/sourcegraph/go-diff/diff/parse.go b/vendor/github.com/sourcegraph/go-diff/diff/parse.go
deleted file mode 100644
index 48eeb9670..000000000
--- a/vendor/github.com/sourcegraph/go-diff/diff/parse.go
+++ /dev/null
@@ -1,865 +0,0 @@
-package diff
-
-import (
- "bufio"
- "bytes"
- "errors"
- "fmt"
- "io"
- "path/filepath"
- "strconv"
- "strings"
- "time"
-)
-
-// 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 ParseMultiFileDiff(diff []byte) ([]*FileDiff, error) {
- return NewMultiFileDiffReader(bytes.NewReader(diff)).ReadAllFiles()
-}
-
-// NewMultiFileDiffReader returns a new MultiFileDiffReader that reads
-// a multi-file unified diff from r.
-func NewMultiFileDiffReader(r io.Reader) *MultiFileDiffReader {
- return &MultiFileDiffReader{reader: newLineReader(r)}
-}
-
-// MultiFileDiffReader reads a multi-file unified diff.
-type MultiFileDiffReader struct {
- line int
- offset int64
- reader *lineReader
-
- // TODO(sqs): line and offset tracking in multi-file diffs is broken; add tests and fix
-
- // nextFileFirstLine is a line that was read by a HunksReader that
- // was how it determined the hunk was complete. But to determine
- // that, it needed to read the first line of the next file. We
- // store nextFileFirstLine so we can "give the first line back" to
- // the next file.
- nextFileFirstLine []byte
-}
-
-// 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.
-func (r *MultiFileDiffReader) ReadFile() (*FileDiff, error) {
- fd, _, err := r.ReadFileWithTrailingContent()
- return fd, err
-}
-
-// ReadFileWithTrailingContent reads the next file unified diff (including
-// headers and all hunks) from r, also returning any trailing content. If there
-// are no more files in the diff, it returns error io.EOF.
-func (r *MultiFileDiffReader) ReadFileWithTrailingContent() (*FileDiff, string, error) {
- fr := &FileDiffReader{
- line: r.line,
- offset: r.offset,
- reader: r.reader,
- fileHeaderLine: r.nextFileFirstLine,
- }
- r.nextFileFirstLine = nil
-
- fd, err := fr.ReadAllHeaders()
- if err != nil {
- switch e := err.(type) {
- case *ParseError:
- if e.Err == ErrNoFileHeader || e.Err == ErrExtendedHeadersEOF {
- // Any non-diff content preceding a valid diff is included in the
- // extended headers of the following diff. In this way, mixed diff /
- // non-diff content can be parsed. Trailing non-diff content is
- // different: it doesn't make sense to return a FileDiff with only
- // extended headers populated. Instead, we return any trailing content
- // in case the caller needs it.
- trailing := ""
- if fd != nil {
- trailing = strings.Join(fd.Extended, "\n")
- }
- return nil, trailing, io.EOF
- }
- return nil, "", err
-
- case OverflowError:
- r.nextFileFirstLine = []byte(e)
- return fd, "", nil
-
- default:
- return nil, "", err
- }
- }
-
- // FileDiff is added/deleted file
- // No further collection of hunks needed
- if fd.NewName == "" {
- return fd, "", nil
- }
-
- // Before reading hunks, check to see if there are any. If there
- // aren't any, and there's another file after this file in the
- // diff, then the hunks reader will complain ErrNoHunkHeader. It's
- // not easy for us to tell from that error alone if that was
- // caused by the lack of any hunks, or a malformatted hunk, so we
- // need to perform the check here.
- hr := fr.HunksReader()
- line, err := r.reader.readLine()
- if err != nil && err != io.EOF {
- return fd, "", err
- }
- line = bytes.TrimSuffix(line, []byte{'\n'})
- if bytes.HasPrefix(line, hunkPrefix) {
- hr.nextHunkHeaderLine = line
- fd.Hunks, err = hr.ReadAllHunks()
- r.line = fr.line
- r.offset = fr.offset
- if err != nil {
- if e0, ok := err.(*ParseError); ok {
- if e, ok := e0.Err.(*ErrBadHunkLine); ok {
- // This just means we finished reading the hunks for the
- // current file. See the ErrBadHunkLine doc for more info.
- r.nextFileFirstLine = e.Line
- return fd, "", nil
- }
- }
- return nil, "", err
- }
- } else {
- // There weren't any hunks, so that line we peeked ahead at
- // actually belongs to the next file. Put it back.
- r.nextFileFirstLine = line
- }
-
- return fd, "", nil
-}
-
-// ReadAllFiles reads all file unified diffs (including headers and all
-// hunks) remaining in r.
-func (r *MultiFileDiffReader) ReadAllFiles() ([]*FileDiff, error) {
- var ds []*FileDiff
- for {
- d, err := r.ReadFile()
- if d != nil {
- ds = append(ds, d)
- }
- if err == io.EOF {
- return ds, nil
- }
- if err != nil {
- return nil, err
- }
- }
-}
-
-// ParseFileDiff parses a file unified diff.
-func ParseFileDiff(diff []byte) (*FileDiff, error) {
- return NewFileDiffReader(bytes.NewReader(diff)).Read()
-}
-
-// NewFileDiffReader returns a new FileDiffReader that reads a file
-// unified diff.
-func NewFileDiffReader(r io.Reader) *FileDiffReader {
- return &FileDiffReader{reader: &lineReader{reader: bufio.NewReader(r)}}
-}
-
-// FileDiffReader reads a unified file diff.
-type FileDiffReader struct {
- line int
- offset int64
- reader *lineReader
-
- // fileHeaderLine is the first file header line, set by:
- //
- // (1) ReadExtendedHeaders if it encroaches on a file header line
- // (which it must to detect when extended headers are done); or
- // (2) (*MultiFileDiffReader).ReadFile() if it encroaches on a
- // file header line while reading the previous file's hunks (in a
- // multi-file diff).
- fileHeaderLine []byte
-}
-
-// Read reads a file unified diff, including headers and hunks, from r.
-func (r *FileDiffReader) Read() (*FileDiff, error) {
- fd, err := r.ReadAllHeaders()
- if err != nil {
- return nil, err
- }
-
- fd.Hunks, err = r.HunksReader().ReadAllHunks()
- if err != nil {
- return nil, err
- }
-
- return fd, nil
-}
-
-// 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 (r *FileDiffReader) ReadAllHeaders() (*FileDiff, error) {
- var err error
- fd := &FileDiff{}
-
- fd.Extended, err = r.ReadExtendedHeaders()
- if pe, ok := err.(*ParseError); ok && pe.Err == ErrExtendedHeadersEOF {
- wasEmpty := handleEmpty(fd)
- if wasEmpty {
- return fd, nil
- }
- return fd, err
- } else if _, ok := err.(OverflowError); ok {
- handleEmpty(fd)
- return fd, err
- } else if err != nil {
- return fd, err
- }
-
- var origTime, newTime *time.Time
- fd.OrigName, fd.NewName, origTime, newTime, err = r.ReadFileHeaders()
- if err != nil {
- return nil, err
- }
- if origTime != nil {
- fd.OrigTime = origTime
- }
- if newTime != nil {
- fd.NewTime = newTime
- }
-
- return fd, nil
-}
-
-// 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 (r *FileDiffReader) HunksReader() *HunksReader {
- return &HunksReader{
- line: r.line,
- offset: r.offset,
- reader: r.reader,
- }
-}
-
-// 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
-func (r *FileDiffReader) ReadFileHeaders() (origName, newName string, origTimestamp, newTimestamp *time.Time, err error) {
- if r.fileHeaderLine != nil {
- if isOnlyMessage, source, filename := parseOnlyInMessage(r.fileHeaderLine); isOnlyMessage {
- return filepath.Join(string(source), string(filename)),
- "", nil, nil, nil
- }
- }
- origName, origTimestamp, err = r.readOneFileHeader([]byte("--- "))
- if err != nil {
- return "", "", nil, nil, err
- }
-
- newName, newTimestamp, err = r.readOneFileHeader([]byte("+++ "))
- if err != nil {
- return "", "", nil, nil, err
- }
-
- unquotedOrigName, err := strconv.Unquote(origName)
- if err == nil {
- origName = unquotedOrigName
- }
- unquotedNewName, err := strconv.Unquote(newName)
- if err == nil {
- newName = unquotedNewName
- }
-
- return origName, newName, origTimestamp, newTimestamp, nil
-}
-
-// readOneFileHeader reads one of the file headers (prefix should be
-// either "+++ " or "--- ").
-func (r *FileDiffReader) readOneFileHeader(prefix []byte) (filename string, timestamp *time.Time, err error) {
- var line []byte
-
- if r.fileHeaderLine == nil {
- var err error
- line, err = r.reader.readLine()
- if err == io.EOF {
- return "", nil, &ParseError{r.line, r.offset, ErrNoFileHeader}
- } else if err != nil {
- return "", nil, err
- }
- } else {
- line = r.fileHeaderLine
- r.fileHeaderLine = nil
- }
-
- if !bytes.HasPrefix(line, prefix) {
- return "", nil, &ParseError{r.line, r.offset, ErrBadFileHeader}
- }
-
- r.offset += int64(len(line))
- r.line++
- line = line[len(prefix):]
-
- trimmedLine := strings.TrimSpace(string(line)) // filenames that contain spaces may be terminated by a tab
- parts := strings.SplitN(trimmedLine, "\t", 2)
- filename = parts[0]
- if len(parts) == 2 {
- var ts time.Time
- // Timestamp is optional, but this header has it.
- ts, err = time.Parse(diffTimeParseLayout, parts[1])
- if err != nil {
- var err1 error
- ts, err1 = time.Parse(diffTimeParseWithoutTZLayout, parts[1])
- if err1 != nil {
- return "", nil, err
- }
- err = nil
- }
- timestamp = &ts
- }
-
- return filename, timestamp, err
-}
-
-// OverflowError is returned when we have overflowed into the start
-// of the next file while reading extended headers.
-type OverflowError string
-
-func (e OverflowError) Error() string {
- return fmt.Sprintf("overflowed into next file: %s", string(e))
-}
-
-// 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 (r *FileDiffReader) ReadExtendedHeaders() ([]string, error) {
- var xheaders []string
- firstLine := true
- for {
- var line []byte
- if r.fileHeaderLine == nil {
- var err error
- line, err = r.reader.readLine()
- if err == io.EOF {
- return xheaders, &ParseError{r.line, r.offset, ErrExtendedHeadersEOF}
- } else if err != nil {
- return xheaders, err
- }
- } else {
- line = r.fileHeaderLine
- r.fileHeaderLine = nil
- }
-
- if bytes.HasPrefix(line, []byte("diff --git ")) {
- if firstLine {
- firstLine = false
- } else {
- return xheaders, OverflowError(line)
- }
- }
- if bytes.HasPrefix(line, []byte("--- ")) {
- // We've reached the file header.
- r.fileHeaderLine = line // pass to readOneFileHeader (see fileHeaderLine field doc)
- return xheaders, nil
- }
-
- // Reached message that file is added/deleted
- if isOnlyInMessage, _, _ := parseOnlyInMessage(line); isOnlyInMessage {
- r.fileHeaderLine = line // pass to readOneFileHeader (see fileHeaderLine field doc)
- return xheaders, nil
- }
-
- r.line++
- r.offset += int64(len(line))
- xheaders = append(xheaders, string(line))
- }
-}
-
-// readQuotedFilename extracts a quoted filename from the beginning of a string,
-// returning the unquoted filename and any remaining text after the filename.
-func readQuotedFilename(text string) (value string, remainder string, err error) {
- if text == "" || text[0] != '"' {
- return "", "", fmt.Errorf(`string must start with a '"': %s`, text)
- }
-
- // The end quote is the first quote NOT preceeded by an uneven number of backslashes.
- numberOfBackslashes := 0
- for i, c := range text {
- if c == '"' && i > 0 && numberOfBackslashes%2 == 0 {
- value, err = strconv.Unquote(text[:i+1])
- remainder = text[i+1:]
- return
- } else if c == '\\' {
- numberOfBackslashes++
- } else {
- numberOfBackslashes = 0
- }
- }
- return "", "", fmt.Errorf(`end of string found while searching for '"': %s`, text)
-}
-
-// parseDiffGitArgs extracts the two filenames from a 'diff --git' line.
-// Returns false on syntax error, true if syntax is valid. Even with a
-// valid syntax, it may be impossible to extract filenames; if so, the
-// function returns ("", "", true).
-func parseDiffGitArgs(diffArgs string) (string, string, bool) {
- length := len(diffArgs)
- if length < 3 {
- return "", "", false
- }
-
- if diffArgs[0] != '"' && diffArgs[length-1] != '"' {
- // Both filenames are unquoted.
- firstSpace := strings.IndexByte(diffArgs, ' ')
- if firstSpace <= 0 || firstSpace == length-1 {
- return "", "", false
- }
-
- secondSpace := strings.IndexByte(diffArgs[firstSpace+1:], ' ')
- if secondSpace == -1 {
- if diffArgs[firstSpace+1] == '"' {
- // The second filename begins with '"', but doesn't end with one.
- return "", "", false
- }
- return diffArgs[:firstSpace], diffArgs[firstSpace+1:], true
- }
-
- // One or both filenames contain a space, but the names are
- // unquoted. Here, the 'diff --git' syntax is ambiguous, and
- // we have to obtain the filenames elsewhere (e.g. from the
- // hunk headers or extended headers). HOWEVER, if the file
- // is newly created and empty, there IS no other place to
- // find the filename. In this case, the two filenames are
- // identical (except for the leading 'a/' prefix), and we have
- // to handle that case here.
- first := diffArgs[:length/2]
- second := diffArgs[length/2+1:]
-
- // If the two strings could be equal, based on length, proceed.
- if length%2 == 1 {
- // If the name minus the a/ b/ prefixes is equal, proceed.
- if len(first) >= 3 && first[1] == '/' && first[1:] == second[1:] {
- return first, second, true
- }
- // If the names don't have the a/ and b/ prefixes and they're equal, proceed.
- if !(first[:2] == "a/" && second[:2] == "b/") && first == second {
- return first, second, true
- }
- }
-
- // The syntax is (unfortunately) valid, but we could not extract
- // the filenames.
- return "", "", true
- }
-
- if diffArgs[0] == '"' {
- first, remainder, err := readQuotedFilename(diffArgs)
- if err != nil || len(remainder) < 2 || remainder[0] != ' ' {
- return "", "", false
- }
- if remainder[1] == '"' {
- second, remainder, err := readQuotedFilename(remainder[1:])
- if remainder != "" || err != nil {
- return "", "", false
- }
- return first, second, true
- }
- return first, remainder[1:], true
- }
-
- // In this case, second argument MUST be quoted (or it's a syntax error)
- i := strings.IndexByte(diffArgs, '"')
- if i == -1 || i+2 >= length || diffArgs[i-1] != ' ' {
- return "", "", false
- }
-
- second, remainder, err := readQuotedFilename(diffArgs[i:])
- if remainder != "" || err != nil {
- return "", "", false
- }
- return diffArgs[:i-1], second, true
-}
-
-// handleEmpty detects when FileDiff was an empty diff and will not have any hunks
-// that follow. It updates fd fields from the parsed extended headers.
-func handleEmpty(fd *FileDiff) (wasEmpty bool) {
- lineCount := len(fd.Extended)
- if lineCount > 0 && !strings.HasPrefix(fd.Extended[0], "diff --git ") {
- return false
- }
-
- lineHasPrefix := func(idx int, prefix string) bool {
- return strings.HasPrefix(fd.Extended[idx], prefix)
- }
-
- linesHavePrefixes := func(idx1 int, prefix1 string, idx2 int, prefix2 string) bool {
- return lineHasPrefix(idx1, prefix1) && lineHasPrefix(idx2, prefix2)
- }
-
- isCopy := (lineCount == 4 && linesHavePrefixes(2, "copy from ", 3, "copy to ")) ||
- (lineCount == 6 && linesHavePrefixes(2, "copy from ", 3, "copy to ") && lineHasPrefix(5, "Binary files ")) ||
- (lineCount == 6 && linesHavePrefixes(1, "old mode ", 2, "new mode ") && linesHavePrefixes(4, "copy from ", 5, "copy to "))
-
- isRename := (lineCount == 4 && linesHavePrefixes(2, "rename from ", 3, "rename to ")) ||
- (lineCount == 5 && linesHavePrefixes(2, "rename from ", 3, "rename to ") && lineHasPrefix(4, "Binary files ")) ||
- (lineCount == 6 && linesHavePrefixes(2, "rename from ", 3, "rename to ") && lineHasPrefix(5, "Binary files ")) ||
- (lineCount == 6 && linesHavePrefixes(1, "old mode ", 2, "new mode ") && linesHavePrefixes(4, "rename from ", 5, "rename to "))
-
- isDeletedFile := (lineCount == 3 || lineCount == 4 && lineHasPrefix(3, "Binary files ") || lineCount > 4 && lineHasPrefix(3, "GIT binary patch")) &&
- lineHasPrefix(1, "deleted file mode ")
-
- isNewFile := (lineCount == 3 || lineCount == 4 && lineHasPrefix(3, "Binary files ") || lineCount > 4 && lineHasPrefix(3, "GIT binary patch")) &&
- lineHasPrefix(1, "new file mode ")
-
- isModeChange := lineCount == 3 && linesHavePrefixes(1, "old mode ", 2, "new mode ")
-
- isBinaryPatch := lineCount == 3 && lineHasPrefix(2, "Binary files ") || lineCount > 3 && lineHasPrefix(2, "GIT binary patch")
-
- if !isModeChange && !isCopy && !isRename && !isBinaryPatch && !isNewFile && !isDeletedFile {
- return false
- }
-
- var success bool
- fd.OrigName, fd.NewName, success = parseDiffGitArgs(fd.Extended[0][len("diff --git "):])
- if isNewFile {
- fd.OrigName = "/dev/null"
- }
-
- if isDeletedFile {
- fd.NewName = "/dev/null"
- }
-
- // For ambiguous 'diff --git' lines, try to reconstruct filenames using extended headers.
- if success && (isCopy || isRename) && fd.OrigName == "" && fd.NewName == "" {
- diffArgs := fd.Extended[0][len("diff --git "):]
-
- tryReconstruct := func(header string, prefix string, whichFile int, result *string) {
- if !strings.HasPrefix(header, prefix) {
- return
- }
- rawFilename := header[len(prefix):]
-
- // extract the filename prefix (e.g. "a/") from the 'diff --git' line.
- var prefixLetterIndex int
- if whichFile == 1 {
- prefixLetterIndex = 0
- } else if whichFile == 2 {
- prefixLetterIndex = len(diffArgs) - len(rawFilename) - 2
- }
- if prefixLetterIndex < 0 || diffArgs[prefixLetterIndex+1] != '/' {
- return
- }
-
- *result = diffArgs[prefixLetterIndex:prefixLetterIndex+2] + rawFilename
- }
-
- for _, header := range fd.Extended {
- tryReconstruct(header, "copy from ", 1, &fd.OrigName)
- tryReconstruct(header, "copy to ", 2, &fd.NewName)
- tryReconstruct(header, "rename from ", 1, &fd.OrigName)
- tryReconstruct(header, "rename to ", 2, &fd.NewName)
- }
- }
- return success
-}
-
-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")
-)
-
-// 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 ParseHunks(diff []byte) ([]*Hunk, error) {
- r := NewHunksReader(bytes.NewReader(diff))
- hunks, err := r.ReadAllHunks()
- if err != nil {
- return nil, err
- }
- return hunks, nil
-}
-
-// NewHunksReader returns a new HunksReader that reads unified diff hunks
-// from r.
-func NewHunksReader(r io.Reader) *HunksReader {
- return &HunksReader{reader: &lineReader{reader: bufio.NewReader(r)}}
-}
-
-// A HunksReader reads hunks from a unified diff.
-type HunksReader struct {
- line int
- offset int64
- hunk *Hunk
- reader *lineReader
-
- nextHunkHeaderLine []byte
-}
-
-// ReadHunk reads one hunk from r. If there are no more hunks, it
-// returns error io.EOF.
-func (r *HunksReader) ReadHunk() (*Hunk, error) {
- r.hunk = nil
- lastLineFromOrig := true
- var line []byte
- var err error
- for {
- if r.nextHunkHeaderLine != nil {
- // Use stored hunk header line that was scanned in at the
- // completion of the previous hunk's ReadHunk.
- line = r.nextHunkHeaderLine
- r.nextHunkHeaderLine = nil
- } else {
- line, err = r.reader.readLine()
- if err != nil {
- if err == io.EOF && r.hunk != nil {
- return r.hunk, nil
- }
- return nil, err
- }
- }
-
- // Record position.
- r.line++
- r.offset += int64(len(line))
-
- if r.hunk == nil {
- // Check for presence of hunk header.
- if !bytes.HasPrefix(line, hunkPrefix) {
- return nil, &ParseError{r.line, r.offset, ErrNoHunkHeader}
- }
-
- // Parse hunk header.
- r.hunk = &Hunk{}
- items := []interface{}{
- &r.hunk.OrigStartLine, &r.hunk.OrigLines,
- &r.hunk.NewStartLine, &r.hunk.NewLines,
- }
- header, section, err := normalizeHeader(string(line))
- if err != nil {
- return nil, &ParseError{r.line, r.offset, err}
- }
- n, err := fmt.Sscanf(header, hunkHeader, items...)
- if err != nil {
- return nil, err
- }
- if n < len(items) {
- return nil, &ParseError{r.line, r.offset, &ErrBadHunkHeader{header: string(line)}}
- }
-
- r.hunk.Section = section
- } else {
- // Read hunk body line.
-
- // If the line starts with `---` and the next one with `+++` we're
- // looking at a non-extended file header and need to abort.
- if bytes.HasPrefix(line, []byte("---")) {
- ok, err := r.reader.nextLineStartsWith("+++")
- if err != nil {
- return r.hunk, err
- }
- if ok {
- ok2, _ := r.reader.nextNextLineStartsWith(string(hunkPrefix))
- if ok2 {
- return r.hunk, &ParseError{r.line, r.offset, &ErrBadHunkLine{Line: line}}
- }
- }
- }
-
- // If the line starts with the hunk prefix, this hunk is complete.
- if bytes.HasPrefix(line, hunkPrefix) {
- // But we've already read in the next hunk's
- // header, so we need to be sure that the next call to
- // ReadHunk starts with that header.
- r.nextHunkHeaderLine = line
-
- // Rewind position.
- r.line--
- r.offset -= int64(len(line))
-
- return r.hunk, nil
- }
-
- if len(line) >= 1 && !linePrefix(line[0]) {
- // Bad hunk header line. If we're reading a multi-file
- // diff, this may be the end of the current
- // file. Return a "rich" error that lets our caller
- // handle that case.
- return r.hunk, &ParseError{r.line, r.offset, &ErrBadHunkLine{Line: line}}
- }
- if bytes.Equal(line, []byte(noNewlineMessage)) {
- if lastLineFromOrig {
- // Retain the newline in the body (otherwise the
- // diff line would be like "-a+b", where "+b" is
- // the the next line of the new file, which is not
- // validly formatted) but record that the orig had
- // no newline.
- r.hunk.OrigNoNewlineAt = int32(len(r.hunk.Body))
- } else {
- // Remove previous line's newline.
- if len(r.hunk.Body) != 0 {
- r.hunk.Body = r.hunk.Body[:len(r.hunk.Body)-1]
- }
- }
- continue
- }
-
- if len(line) > 0 {
- lastLineFromOrig = line[0] == '-'
- }
-
- r.hunk.Body = append(r.hunk.Body, line...)
- r.hunk.Body = append(r.hunk.Body, '\n')
- }
- }
-}
-
-const noNewlineMessage = `\ No newline at end of file`
-
-// linePrefixes is the set of all characters a valid line in a diff
-// hunk can start with. '\' can appear in diffs when no newline is
-// present at the end of a file.
-// See: 'http://www.gnu.org/software/diffutils/manual/diffutils.html#Incomplete-Lines'
-var linePrefixes = []byte{' ', '-', '+', '\\'}
-
-// linePrefix returns true if 'c' is in 'linePrefixes'.
-func linePrefix(c byte) bool {
- for _, p := range linePrefixes {
- if p == c {
- return true
- }
- }
- return false
-}
-
-// normalizeHeader takes a header of the form:
-// "@@ -linestart[,chunksize] +linestart[,chunksize] @@ section"
-// and returns two strings, with the first in the form:
-// "@@ -linestart,chunksize +linestart,chunksize @@".
-// where linestart and chunksize are both integers. The second is the
-// optional section header. chunksize may be omitted from the header
-// if its value is 1. normalizeHeader returns an error if the header
-// is not in the correct format.
-func normalizeHeader(header string) (string, string, error) {
- // Split the header into five parts: the first '@@', the two
- // ranges, the last '@@', and the optional section.
- pieces := strings.SplitN(header, " ", 5)
- if len(pieces) < 4 {
- return "", "", &ErrBadHunkHeader{header: header}
- }
-
- if pieces[0] != "@@" {
- return "", "", &ErrBadHunkHeader{header: header}
- }
- for i := 1; i < 3; i++ {
- if !strings.ContainsRune(pieces[i], ',') {
- pieces[i] = pieces[i] + ",1"
- }
- }
- if pieces[3] != "@@" {
- return "", "", &ErrBadHunkHeader{header: header}
- }
-
- var section string
- if len(pieces) == 5 {
- section = pieces[4]
- }
- return strings.Join(pieces, " "), strings.TrimSpace(section), nil
-}
-
-// 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 (r *HunksReader) ReadAllHunks() ([]*Hunk, error) {
- var hunks []*Hunk
- linesRead := int32(0)
- for {
- hunk, err := r.ReadHunk()
- if err == io.EOF {
- return hunks, nil
- }
- if hunk != nil {
- linesRead++ // account for the hunk header line
- hunk.StartPosition = linesRead
- hunks = append(hunks, hunk)
- linesRead += int32(bytes.Count(hunk.Body, []byte{'\n'}))
- }
- if err != nil {
- return hunks, err
- }
- }
-}
-
-// parseOnlyInMessage checks if line is a "Only in {source}: {filename}" and returns source and filename
-func parseOnlyInMessage(line []byte) (bool, []byte, []byte) {
- if !bytes.HasPrefix(line, onlyInMessagePrefix) {
- return false, nil, nil
- }
- line = line[len(onlyInMessagePrefix):]
- idx := bytes.Index(line, []byte(": "))
- if idx < 0 {
- return false, nil, nil
- }
- return true, line[:idx], line[idx+2:]
-}
-
-// A ParseError is a description of a unified diff syntax error.
-type ParseError struct {
- Line int // Line where the error occurred
- Offset int64 // Offset where the error occurred
- Err error // The actual error
-}
-
-func (e *ParseError) Error() string {
- return fmt.Sprintf("line %d, char %d: %s", e.Line, e.Offset, e.Err)
-}
-
-// ErrNoHunkHeader indicates that a unified diff hunk header was
-// expected but not found during parsing.
-var ErrNoHunkHeader = errors.New("no hunk header")
-
-// ErrBadHunkHeader indicates that a malformed unified diff hunk
-// header was encountered during parsing.
-type ErrBadHunkHeader struct {
- header string
-}
-
-func (e *ErrBadHunkHeader) Error() string {
- if e.header == "" {
- return "bad hunk header"
- }
- return "bad hunk header: " + e.header
-}
-
-// 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).
-type ErrBadHunkLine struct {
- Line []byte
-}
-
-func (e *ErrBadHunkLine) Error() string {
- m := "bad hunk line (does not start with ' ', '-', '+', or '\\')"
- if len(e.Line) == 0 {
- return m
- }
- return m + ": " + string(e.Line)
-}
diff --git a/vendor/github.com/sourcegraph/go-diff/diff/print.go b/vendor/github.com/sourcegraph/go-diff/diff/print.go
deleted file mode 100644
index 012651a33..000000000
--- a/vendor/github.com/sourcegraph/go-diff/diff/print.go
+++ /dev/null
@@ -1,141 +0,0 @@
-package diff
-
-import (
- "bytes"
- "fmt"
- "io"
- "path/filepath"
- "time"
-)
-
-// PrintMultiFileDiff prints a multi-file diff in unified diff format.
-func PrintMultiFileDiff(ds []*FileDiff) ([]byte, error) {
- var buf bytes.Buffer
- for _, d := range ds {
- diff, err := PrintFileDiff(d)
- if err != nil {
- return nil, err
- }
- if _, err := buf.Write(diff); err != nil {
- return nil, err
- }
- }
- return buf.Bytes(), nil
-}
-
-// PrintFileDiff prints a FileDiff in unified diff format.
-//
-// TODO(sqs): handle escaping whitespace/etc. chars in filenames
-func PrintFileDiff(d *FileDiff) ([]byte, error) {
- var buf bytes.Buffer
-
- for _, xheader := range d.Extended {
- if _, err := fmt.Fprintln(&buf, xheader); err != nil {
- return nil, err
- }
- }
-
- // FileDiff is added/deleted file
- // No further hunks printing needed
- if d.NewName == "" {
- _, err := fmt.Fprintf(&buf, onlyInMessage, filepath.Dir(d.OrigName), filepath.Base(d.OrigName))
- if err != nil {
- return nil, err
- }
- return buf.Bytes(), nil
- }
-
- if d.Hunks == nil {
- return buf.Bytes(), nil
- }
-
- if err := printFileHeader(&buf, "--- ", d.OrigName, d.OrigTime); err != nil {
- return nil, err
- }
- if err := printFileHeader(&buf, "+++ ", d.NewName, d.NewTime); err != nil {
- return nil, err
- }
-
- ph, err := PrintHunks(d.Hunks)
- if err != nil {
- return nil, err
- }
-
- if _, err := buf.Write(ph); err != nil {
- return nil, err
- }
- return buf.Bytes(), nil
-}
-
-func printFileHeader(w io.Writer, prefix string, filename string, timestamp *time.Time) error {
- if _, err := fmt.Fprint(w, prefix, filename); err != nil {
- return err
- }
- if timestamp != nil {
- if _, err := fmt.Fprint(w, "\t", timestamp.Format(diffTimeFormatLayout)); err != nil {
- return err
- }
- }
- if _, err := fmt.Fprintln(w); err != nil {
- return err
- }
- return nil
-}
-
-// PrintHunks prints diff hunks in unified diff format.
-func PrintHunks(hunks []*Hunk) ([]byte, error) {
- var buf bytes.Buffer
- for _, hunk := range hunks {
- _, err := fmt.Fprintf(&buf,
- "@@ -%d,%d +%d,%d @@", hunk.OrigStartLine, hunk.OrigLines, hunk.NewStartLine, hunk.NewLines,
- )
- if err != nil {
- return nil, err
- }
- if hunk.Section != "" {
- _, err := fmt.Fprint(&buf, " ", hunk.Section)
- if err != nil {
- return nil, err
- }
- }
- if _, err := fmt.Fprintln(&buf); err != nil {
- return nil, err
- }
-
- if hunk.OrigNoNewlineAt == 0 {
- if _, err := buf.Write(hunk.Body); err != nil {
- return nil, err
- }
- } else {
- if _, err := buf.Write(hunk.Body[:hunk.OrigNoNewlineAt]); err != nil {
- return nil, err
- }
- if err := printNoNewlineMessage(&buf); err != nil {
- return nil, err
- }
- if _, err := buf.Write(hunk.Body[hunk.OrigNoNewlineAt:]); err != nil {
- return nil, err
- }
- }
-
- if !bytes.HasSuffix(hunk.Body, []byte{'\n'}) {
- if _, err := fmt.Fprintln(&buf); err != nil {
- return nil, err
- }
- if err := printNoNewlineMessage(&buf); err != nil {
- return nil, err
- }
- }
- }
- return buf.Bytes(), nil
-}
-
-func printNoNewlineMessage(w io.Writer) error {
- if _, err := w.Write([]byte(noNewlineMessage)); err != nil {
- return err
- }
- if _, err := fmt.Fprintln(w); err != nil {
- return err
- }
- return nil
-}
diff --git a/vendor/github.com/sourcegraph/go-diff/diff/reader_util.go b/vendor/github.com/sourcegraph/go-diff/diff/reader_util.go
deleted file mode 100644
index 45300252b..000000000
--- a/vendor/github.com/sourcegraph/go-diff/diff/reader_util.go
+++ /dev/null
@@ -1,120 +0,0 @@
-package diff
-
-import (
- "bufio"
- "bytes"
- "errors"
- "io"
-)
-
-var ErrLineReaderUninitialized = errors.New("line reader not initialized")
-
-func newLineReader(r io.Reader) *lineReader {
- return &lineReader{reader: bufio.NewReader(r)}
-}
-
-// lineReader is a wrapper around a bufio.Reader that caches the next line to
-// provide lookahead functionality for the next two lines.
-type lineReader struct {
- reader *bufio.Reader
-
- cachedNextLine []byte
- cachedNextLineErr error
-}
-
-// readLine returns the next unconsumed line and advances the internal cache of
-// the lineReader.
-func (l *lineReader) readLine() ([]byte, error) {
- if l.cachedNextLine == nil && l.cachedNextLineErr == nil {
- l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader)
- }
-
- if l.cachedNextLineErr != nil {
- return nil, l.cachedNextLineErr
- }
-
- next := l.cachedNextLine
-
- l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader)
-
- return next, nil
-}
-
-// nextLineStartsWith looks at the line that would be returned by the next call
-// to readLine to check whether it has the given prefix.
-//
-// io.EOF and bufio.ErrBufferFull errors are ignored so that the function can
-// be used when at the end of the file.
-func (l *lineReader) nextLineStartsWith(prefix string) (bool, error) {
- if l.cachedNextLine == nil && l.cachedNextLineErr == nil {
- l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader)
- }
-
- return l.lineHasPrefix(l.cachedNextLine, prefix, l.cachedNextLineErr)
-}
-
-// nextNextLineStartsWith checks the prefix of the line *after* the line that
-// would be returned by the next readLine.
-//
-// io.EOF and bufio.ErrBufferFull errors are ignored so that the function can
-// be used when at the end of the file.
-//
-// The lineReader MUST be initialized by calling readLine at least once before
-// calling nextLineStartsWith. Otherwise ErrLineReaderUninitialized will be
-// returned.
-func (l *lineReader) nextNextLineStartsWith(prefix string) (bool, error) {
- if l.cachedNextLine == nil && l.cachedNextLineErr == nil {
- l.cachedNextLine, l.cachedNextLineErr = readLine(l.reader)
- }
-
- next, err := l.reader.Peek(len(prefix))
- return l.lineHasPrefix(next, prefix, err)
-}
-
-// lineHasPrefix checks whether the given line has the given prefix with
-// bytes.HasPrefix.
-//
-// The readErr should be the error that was returned when the line was read.
-// lineHasPrefix checks the error to adjust its return value to, e.g., return
-// false and ignore the error when readErr is io.EOF.
-func (l *lineReader) lineHasPrefix(line []byte, prefix string, readErr error) (bool, error) {
- if readErr != nil {
- if readErr == io.EOF || readErr == bufio.ErrBufferFull {
- return false, nil
- }
- return false, readErr
- }
-
- return bytes.HasPrefix(line, []byte(prefix)), nil
-}
-
-// readLine is a helper that mimics the functionality of calling bufio.Scanner.Scan() and
-// bufio.Scanner.Bytes(), but without the token size limitation. It will read and return
-// the next line in the Reader with the trailing newline stripped. It will return an
-// io.EOF error when there is nothing left to read (at the start of the function call). It
-// will return any other errors it receives from the underlying call to ReadBytes.
-func readLine(r *bufio.Reader) ([]byte, error) {
- line_, err := r.ReadBytes('\n')
- if err == io.EOF {
- if len(line_) == 0 {
- return nil, io.EOF
- }
-
- // ReadBytes returned io.EOF, because it didn't find another newline, but there is
- // still the remainder of the file to return as a line.
- line := line_
- return line, nil
- } else if err != nil {
- return nil, err
- }
- line := line_[0 : len(line_)-1]
- return dropCR(line), nil
-}
-
-// dropCR drops a terminal \r from the data.
-func dropCR(data []byte) []byte {
- if len(data) > 0 && data[len(data)-1] == '\r' {
- return data[0 : len(data)-1]
- }
- return data
-}