Initial import
This commit is contained in:
35
vendor/sourcegraph.com/sourcegraph/go-diff/LICENSE
generated
vendored
Normal file
35
vendor/sourcegraph.com/sourcegraph/go-diff/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
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:
|
||||
76
vendor/sourcegraph.com/sourcegraph/go-diff/diff/diff.go
generated
vendored
Normal file
76
vendor/sourcegraph.com/sourcegraph/go-diff/diff/diff.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package diff
|
||||
|
||||
import "bytes"
|
||||
|
||||
// NOTE: types are code-generated in diff.pb.go.
|
||||
|
||||
//go:generate protoc -I../../../.. -I ../../../../github.com/gogo/protobuf/protobuf -I. --gogo_out=. diff.proto
|
||||
|
||||
// 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("@@ ")
|
||||
)
|
||||
|
||||
const hunkHeader = "@@ -%d,%d +%d,%d @@"
|
||||
|
||||
// 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"
|
||||
|
||||
// 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
|
||||
}
|
||||
1059
vendor/sourcegraph.com/sourcegraph/go-diff/diff/diff.pb.go
generated
vendored
Normal file
1059
vendor/sourcegraph.com/sourcegraph/go-diff/diff/diff.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
81
vendor/sourcegraph.com/sourcegraph/go-diff/diff/diff.proto
generated
vendored
Normal file
81
vendor/sourcegraph.com/sourcegraph/go-diff/diff/diff.proto
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
syntax = "proto3";
|
||||
package diff;
|
||||
|
||||
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
||||
import "sourcegraph.com/sqs/pbtypes/timestamp.proto";
|
||||
|
||||
option (gogoproto.goproto_getters_all) = false;
|
||||
option (gogoproto.unmarshaler_all) = true;
|
||||
option (gogoproto.marshaler_all) = true;
|
||||
option (gogoproto.sizer_all) = true;
|
||||
|
||||
// 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
|
||||
message FileDiff {
|
||||
// the original name of the file
|
||||
string OrigName = 1;
|
||||
|
||||
// the original timestamp (nil if not present)
|
||||
pbtypes.Timestamp OrigTime = 2;
|
||||
|
||||
// the new name of the file (often same as OrigName)
|
||||
string NewName = 3;
|
||||
|
||||
// the new timestamp (nil if not present)
|
||||
pbtypes.Timestamp NewTime = 4;
|
||||
|
||||
// extended header lines (e.g., git's "new mode <mode>", "rename from <path>", etc.)
|
||||
repeated string Extended = 5;
|
||||
|
||||
// hunks that were changed from orig to new
|
||||
repeated Hunk Hunks = 6;
|
||||
}
|
||||
|
||||
|
||||
// A Hunk represents a series of changes (additions or deletions) in a file's
|
||||
// unified diff.
|
||||
message Hunk {
|
||||
// starting line number in original file
|
||||
int32 OrigStartLine = 1;
|
||||
|
||||
// number of lines the hunk applies to in the original file
|
||||
int32 OrigLines = 2;
|
||||
|
||||
// if > 0, then the original file had a 'No newline at end of file' mark at this offset
|
||||
int32 OrigNoNewlineAt = 3;
|
||||
|
||||
// starting line number in new file
|
||||
int32 NewStartLine = 4;
|
||||
|
||||
// number of lines the hunk applies to in the new file
|
||||
int32 NewLines = 5;
|
||||
|
||||
// optional section heading
|
||||
string Section = 6;
|
||||
|
||||
// 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.
|
||||
int32 StartPosition = 7;
|
||||
|
||||
// hunk body (lines prefixed with '-', '+', or ' ')
|
||||
bytes Body = 8;
|
||||
}
|
||||
|
||||
// A Stat is a diff stat that represents the number of lines added/changed/deleted.
|
||||
message Stat {
|
||||
// number of lines added
|
||||
int32 Added = 1 [(gogoproto.jsontag) = ""];
|
||||
|
||||
// number of lines changed
|
||||
int32 Changed = 2 [(gogoproto.jsontag) = ""];
|
||||
|
||||
// number of lines deleted
|
||||
int32 Deleted = 3 [(gogoproto.jsontag) = ""];
|
||||
}
|
||||
|
||||
605
vendor/sourcegraph.com/sourcegraph/go-diff/diff/diff_test.go
generated
vendored
Normal file
605
vendor/sourcegraph.com/sourcegraph/go-diff/diff/diff_test.go
generated
vendored
Normal file
@@ -0,0 +1,605 @@
|
||||
package diff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/shurcooL/go-goon"
|
||||
"sourcegraph.com/sqs/pbtypes"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Diffs include times that by default are generated in the local
|
||||
// timezone. To ensure that tests behave the same in all timezones
|
||||
// (compared to the hard-coded expected output), force the test
|
||||
// timezone to UTC.
|
||||
//
|
||||
// This is safe to do in tests but should not (and need not) be
|
||||
// done for the main code.
|
||||
time.Local = time.UTC
|
||||
}
|
||||
|
||||
func TestParseHunkNoChunksize(t *testing.T) {
|
||||
filename := "sample_no_chunksize.diff"
|
||||
diffData, err := ioutil.ReadFile(filepath.Join("testdata", filename))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
diff, err := ParseHunks(diffData)
|
||||
if err != nil {
|
||||
t.Errorf("%s: got ParseHunks err %v, want %v", filename, err, nil)
|
||||
}
|
||||
if len(diff) != 1 {
|
||||
t.Fatalf("%s: Got %d hunks, want only one", filename, len(diff))
|
||||
}
|
||||
|
||||
correct := &Hunk{
|
||||
NewLines: 1,
|
||||
NewStartLine: 1,
|
||||
OrigLines: 0,
|
||||
OrigStartLine: 0,
|
||||
StartPosition: 1,
|
||||
}
|
||||
h := diff[0]
|
||||
h.Body = nil // We're not testing the body.
|
||||
if !reflect.DeepEqual(h, correct) {
|
||||
t.Errorf("%s: Got %#v, want %#v", filename, h, correct)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseHunksAndPrintHunks(t *testing.T) {
|
||||
tests := []struct {
|
||||
filename string
|
||||
wantParseErr error
|
||||
}{
|
||||
{filename: "sample_hunk.diff"},
|
||||
{filename: "sample_hunks.diff"},
|
||||
{filename: "sample_bad_hunks.diff"},
|
||||
{filename: "sample_hunks_no_newline.diff"},
|
||||
{filename: "no_newline_both.diff"},
|
||||
{filename: "no_newline_both2.diff"},
|
||||
{filename: "no_newline_orig.diff"},
|
||||
{filename: "no_newline_new.diff"},
|
||||
{filename: "empty_orig.diff"},
|
||||
{filename: "empty_new.diff"},
|
||||
{filename: "oneline_hunk.diff"},
|
||||
{filename: "empty.diff"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
diffData, err := ioutil.ReadFile(filepath.Join("testdata", test.filename))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
diff, err := ParseHunks(diffData)
|
||||
if err != test.wantParseErr {
|
||||
t.Errorf("%s: got ParseHunks err %v, want %v", test.filename, err, test.wantParseErr)
|
||||
continue
|
||||
}
|
||||
if test.wantParseErr != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
printed, err := PrintHunks(diff)
|
||||
if err != nil {
|
||||
t.Errorf("%s: PrintHunks: %s", test.filename, err)
|
||||
}
|
||||
if !bytes.Equal(printed, diffData) {
|
||||
t.Errorf("%s: printed diff hunks != original diff hunks\n\n# PrintHunks output:\n%s\n\n# Original:\n%s", test.filename, printed, diffData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseFileDiffHeaders(t *testing.T) {
|
||||
tests := []struct {
|
||||
filename string
|
||||
wantDiff *FileDiff
|
||||
}{
|
||||
{
|
||||
filename: "sample_file.diff",
|
||||
wantDiff: &FileDiff{
|
||||
OrigName: "oldname",
|
||||
OrigTime: &pbtypes.Timestamp{Seconds: 1255273940},
|
||||
NewName: "newname",
|
||||
NewTime: &pbtypes.Timestamp{Seconds: 1255273950},
|
||||
},
|
||||
},
|
||||
{
|
||||
filename: "sample_file_no_fractional_seconds.diff",
|
||||
wantDiff: &FileDiff{
|
||||
OrigName: "goyaml.go",
|
||||
OrigTime: &pbtypes.Timestamp{Seconds: 1322164040},
|
||||
NewName: "goyaml.go",
|
||||
NewTime: &pbtypes.Timestamp{Seconds: 1322486679},
|
||||
},
|
||||
},
|
||||
{
|
||||
filename: "sample_file_extended.diff",
|
||||
wantDiff: &FileDiff{
|
||||
OrigName: "oldname",
|
||||
OrigTime: &pbtypes.Timestamp{Seconds: 1255273940},
|
||||
NewName: "newname",
|
||||
NewTime: &pbtypes.Timestamp{Seconds: 1255273950},
|
||||
Extended: []string{
|
||||
"diff --git a/vcs/git_cmd.go b/vcs/git_cmd.go",
|
||||
"index aa4de15..7c048ab 100644",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
filename: "sample_file_extended_empty_new.diff",
|
||||
wantDiff: &FileDiff{
|
||||
OrigName: "/dev/null",
|
||||
OrigTime: nil,
|
||||
NewName: "b/vendor/go/build/testdata/empty/dummy",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/vendor/go/build/testdata/empty/dummy b/vendor/go/build/testdata/empty/dummy",
|
||||
"new file mode 100644",
|
||||
"index 0000000..e69de29",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
filename: "sample_file_extended_empty_new_binary.diff",
|
||||
wantDiff: &FileDiff{
|
||||
OrigName: "/dev/null",
|
||||
OrigTime: nil,
|
||||
NewName: "b/diff/binary-image.png",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/diff/binary-image.png b/diff/binary-image.png",
|
||||
"new file mode 100644",
|
||||
"index 0000000..b51756e",
|
||||
"Binary files /dev/null and b/diff/binary-image.png differ",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
filename: "sample_file_extended_empty_deleted.diff",
|
||||
wantDiff: &FileDiff{
|
||||
OrigName: "a/vendor/go/build/testdata/empty/dummy",
|
||||
OrigTime: nil,
|
||||
NewName: "/dev/null",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/vendor/go/build/testdata/empty/dummy b/vendor/go/build/testdata/empty/dummy",
|
||||
"deleted file mode 100644",
|
||||
"index e69de29..0000000",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
filename: "sample_file_extended_empty_deleted_binary.diff",
|
||||
wantDiff: &FileDiff{
|
||||
OrigName: "a/187/player/random/gopher-0.png",
|
||||
OrigTime: nil,
|
||||
NewName: "/dev/null",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/187/player/random/gopher-0.png b/187/player/random/gopher-0.png",
|
||||
"deleted file mode 100644",
|
||||
"index aebdfc7..0000000",
|
||||
"Binary files a/187/player/random/gopher-0.png and /dev/null differ",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
filename: "sample_file_extended_empty_rename.diff",
|
||||
wantDiff: &FileDiff{
|
||||
OrigName: "a/docs/integrations/Email_Notifications.md",
|
||||
OrigTime: nil,
|
||||
NewName: "b/docs/integrations/email-notifications.md",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/docs/integrations/Email_Notifications.md b/docs/integrations/email-notifications.md",
|
||||
"similarity index 100%",
|
||||
"rename from docs/integrations/Email_Notifications.md",
|
||||
"rename to docs/integrations/email-notifications.md",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
diffData, err := ioutil.ReadFile(filepath.Join("testdata", test.filename))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
diff, err := ParseFileDiff(diffData)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: got ParseFileDiff error %v", test.filename, err)
|
||||
}
|
||||
|
||||
diff.Hunks = nil
|
||||
if got, want := diff, test.wantDiff; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("%s:\n\ngot: %v\nwant: %v", test.filename, goon.Sdump(got), goon.Sdump(want))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseMultiFileDiffHeaders(t *testing.T) {
|
||||
tests := []struct {
|
||||
filename string
|
||||
wantDiffs []*FileDiff
|
||||
}{
|
||||
{
|
||||
filename: "sample_multi_file_new.diff",
|
||||
wantDiffs: []*FileDiff{
|
||||
{
|
||||
OrigName: "/dev/null",
|
||||
OrigTime: nil,
|
||||
NewName: "b/_vendor/go/build/syslist_test.go",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/_vendor/go/build/syslist_test.go b/_vendor/go/build/syslist_test.go",
|
||||
"new file mode 100644",
|
||||
"index 0000000..3be2928",
|
||||
},
|
||||
},
|
||||
{
|
||||
OrigName: "/dev/null",
|
||||
OrigTime: nil,
|
||||
NewName: "b/_vendor/go/build/testdata/empty/dummy",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/_vendor/go/build/testdata/empty/dummy b/_vendor/go/build/testdata/empty/dummy",
|
||||
"new file mode 100644",
|
||||
"index 0000000..e69de29",
|
||||
},
|
||||
},
|
||||
{
|
||||
OrigName: "/dev/null",
|
||||
OrigTime: nil,
|
||||
NewName: "b/_vendor/go/build/testdata/multi/file.go",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/_vendor/go/build/testdata/multi/file.go b/_vendor/go/build/testdata/multi/file.go",
|
||||
"new file mode 100644",
|
||||
"index 0000000..ee946eb",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
filename: "sample_multi_file_deleted.diff",
|
||||
wantDiffs: []*FileDiff{
|
||||
{
|
||||
OrigName: "a/vendor/go/build/syslist_test.go",
|
||||
OrigTime: nil,
|
||||
NewName: "/dev/null",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/vendor/go/build/syslist_test.go b/vendor/go/build/syslist_test.go",
|
||||
"deleted file mode 100644",
|
||||
"index 3be2928..0000000",
|
||||
},
|
||||
},
|
||||
{
|
||||
OrigName: "a/vendor/go/build/testdata/empty/dummy",
|
||||
OrigTime: nil,
|
||||
NewName: "/dev/null",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/vendor/go/build/testdata/empty/dummy b/vendor/go/build/testdata/empty/dummy",
|
||||
"deleted file mode 100644",
|
||||
"index e69de29..0000000",
|
||||
},
|
||||
},
|
||||
{
|
||||
OrigName: "a/vendor/go/build/testdata/multi/file.go",
|
||||
OrigTime: nil,
|
||||
NewName: "/dev/null",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/vendor/go/build/testdata/multi/file.go b/vendor/go/build/testdata/multi/file.go",
|
||||
"deleted file mode 100644",
|
||||
"index ee946eb..0000000",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
filename: "sample_multi_file_rename.diff",
|
||||
wantDiffs: []*FileDiff{
|
||||
{
|
||||
OrigName: "a/README.md",
|
||||
OrigTime: nil,
|
||||
NewName: "b/README.md",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/README.md b/README.md",
|
||||
"index 5f3d591..96a24fa 100644",
|
||||
},
|
||||
},
|
||||
{
|
||||
OrigName: "a/docs/integrations/Email_Notifications.md",
|
||||
OrigTime: nil,
|
||||
NewName: "b/docs/integrations/email-notifications.md",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/docs/integrations/Email_Notifications.md b/docs/integrations/email-notifications.md",
|
||||
"similarity index 100%",
|
||||
"rename from docs/integrations/Email_Notifications.md",
|
||||
"rename to docs/integrations/email-notifications.md",
|
||||
},
|
||||
},
|
||||
{
|
||||
OrigName: "a/release_notes.md",
|
||||
OrigTime: nil,
|
||||
NewName: "b/release_notes.md",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/release_notes.md b/release_notes.md",
|
||||
"index f2ff13f..f060cb5 100644",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
filename: "sample_multi_file_binary.diff",
|
||||
wantDiffs: []*FileDiff{
|
||||
{
|
||||
OrigName: "a/README.md",
|
||||
OrigTime: nil,
|
||||
NewName: "b/README.md",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/README.md b/README.md",
|
||||
"index 7b73e04..36cde13 100644",
|
||||
},
|
||||
},
|
||||
{
|
||||
OrigName: "a/data/Font.png",
|
||||
OrigTime: nil,
|
||||
NewName: "b/data/Font.png",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/data/Font.png b/data/Font.png",
|
||||
"index 17a971d..599f8dd 100644",
|
||||
"Binary files a/data/Font.png and b/data/Font.png differ",
|
||||
},
|
||||
},
|
||||
{
|
||||
OrigName: "a/main.go",
|
||||
OrigTime: nil,
|
||||
NewName: "b/main.go",
|
||||
NewTime: nil,
|
||||
Extended: []string{
|
||||
"diff --git a/main.go b/main.go",
|
||||
"index 1aced1e..98a982e 100644",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
diffData, err := ioutil.ReadFile(filepath.Join("testdata", test.filename))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
diffs, err := ParseMultiFileDiff(diffData)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: got ParseMultiFileDiff error %v", test.filename, err)
|
||||
}
|
||||
|
||||
for i := range diffs {
|
||||
diffs[i].Hunks = nil // This test focuses on things other than hunks, so don't compare them.
|
||||
}
|
||||
if got, want := diffs, test.wantDiffs; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("%s:\n\ngot: %v\nwant: %v", test.filename, goon.Sdump(got), goon.Sdump(want))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseFileDiffAndPrintFileDiff(t *testing.T) {
|
||||
tests := []struct {
|
||||
filename string
|
||||
wantParseErr error
|
||||
}{
|
||||
{filename: "sample_file.diff"},
|
||||
{filename: "sample_file_no_timestamp.diff"},
|
||||
{filename: "sample_file_extended.diff"},
|
||||
{filename: "sample_file_extended_empty_new.diff"},
|
||||
{filename: "sample_file_extended_empty_new_binary.diff"},
|
||||
{filename: "sample_file_extended_empty_deleted.diff"},
|
||||
{filename: "sample_file_extended_empty_deleted_binary.diff"},
|
||||
{filename: "sample_file_extended_empty_rename.diff"},
|
||||
{filename: "sample_file_extended_empty_binary.diff"},
|
||||
{
|
||||
filename: "empty.diff",
|
||||
wantParseErr: &ParseError{0, 0, ErrExtendedHeadersEOF},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
diffData, err := ioutil.ReadFile(filepath.Join("testdata", test.filename))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
diff, err := ParseFileDiff(diffData)
|
||||
if !reflect.DeepEqual(err, test.wantParseErr) {
|
||||
t.Errorf("%s: got ParseFileDiff err %v, want %v", test.filename, err, test.wantParseErr)
|
||||
continue
|
||||
}
|
||||
if test.wantParseErr != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
printed, err := PrintFileDiff(diff)
|
||||
if err != nil {
|
||||
t.Errorf("%s: PrintFileDiff: %s", test.filename, err)
|
||||
}
|
||||
if !bytes.Equal(printed, diffData) {
|
||||
t.Errorf("%s: printed file diff != original file diff\n\n# PrintFileDiff output:\n%s\n\n# Original:\n%s", test.filename, printed, diffData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseMultiFileDiffAndPrintMultiFileDiff(t *testing.T) {
|
||||
tests := []struct {
|
||||
filename string
|
||||
wantParseErr error
|
||||
wantFileDiffs int // How many instances of diff.FileDiff are expected.
|
||||
}{
|
||||
{filename: "sample_multi_file.diff", wantFileDiffs: 2},
|
||||
{filename: "sample_multi_file_single.diff", wantFileDiffs: 1},
|
||||
{filename: "sample_multi_file_new.diff", wantFileDiffs: 3},
|
||||
{filename: "sample_multi_file_deleted.diff", wantFileDiffs: 3},
|
||||
{filename: "sample_multi_file_rename.diff", wantFileDiffs: 3},
|
||||
{filename: "sample_multi_file_binary.diff", wantFileDiffs: 3},
|
||||
{filename: "long_line_multi.diff", wantFileDiffs: 3},
|
||||
{filename: "empty.diff", wantFileDiffs: 0},
|
||||
{filename: "empty_multi.diff", wantFileDiffs: 2},
|
||||
}
|
||||
for _, test := range tests {
|
||||
diffData, err := ioutil.ReadFile(filepath.Join("testdata", test.filename))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
diffs, err := ParseMultiFileDiff(diffData)
|
||||
if err != test.wantParseErr {
|
||||
t.Errorf("%s: got ParseMultiFileDiff err %v, want %v", test.filename, err, test.wantParseErr)
|
||||
continue
|
||||
}
|
||||
if test.wantParseErr != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if got, want := len(diffs), test.wantFileDiffs; got != want {
|
||||
t.Errorf("%s: got %v instances of diff.FileDiff, expected %v", test.filename, got, want)
|
||||
}
|
||||
|
||||
printed, err := PrintMultiFileDiff(diffs)
|
||||
if err != nil {
|
||||
t.Errorf("%s: PrintMultiFileDiff: %s", test.filename, err)
|
||||
}
|
||||
if !bytes.Equal(printed, diffData) {
|
||||
t.Errorf("%s: printed multi-file diff != original multi-file diff\n\n# PrintMultiFileDiff output:\n%s\n\n# Original:\n%s", test.filename, printed, diffData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoNewlineAtEnd(t *testing.T) {
|
||||
diffs := map[string]struct {
|
||||
diff string
|
||||
trailingNewlineOK bool
|
||||
}{
|
||||
"orig": {
|
||||
diff: `@@ -1,1 +1,1 @@
|
||||
-a
|
||||
\ No newline at end of file
|
||||
+b
|
||||
`,
|
||||
trailingNewlineOK: true,
|
||||
},
|
||||
"new": {
|
||||
diff: `@@ -1,1 +1,1 @@
|
||||
-a
|
||||
+b
|
||||
\ No newline at end of file
|
||||
`,
|
||||
},
|
||||
"both": {
|
||||
diff: `@@ -1,1 +1,1 @@
|
||||
-a
|
||||
\ No newline at end of file
|
||||
+b
|
||||
\ No newline at end of file
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
for label, test := range diffs {
|
||||
hunks, err := ParseHunks([]byte(test.diff))
|
||||
if err != nil {
|
||||
t.Errorf("%s: ParseHunks: %s", label, err)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, hunk := range hunks {
|
||||
if body := string(hunk.Body); strings.Contains(body, "No newline") {
|
||||
t.Errorf("%s: after parse, hunk body contains 'No newline...' string\n\nbody is:\n%s", label, body)
|
||||
}
|
||||
if !test.trailingNewlineOK {
|
||||
if bytes.HasSuffix(hunk.Body, []byte{'\n'}) {
|
||||
t.Errorf("%s: after parse, hunk body ends with newline\n\nbody is:\n%s", label, hunk.Body)
|
||||
}
|
||||
}
|
||||
if dontWant := []byte("-a+b"); bytes.Contains(hunk.Body, dontWant) {
|
||||
t.Errorf("%s: hunk body contains %q\n\nbody is:\n%s", label, dontWant, hunk.Body)
|
||||
}
|
||||
|
||||
printed, err := PrintHunks(hunks)
|
||||
if err != nil {
|
||||
t.Errorf("%s: PrintHunks: %s", label, err)
|
||||
continue
|
||||
}
|
||||
if printed := string(printed); printed != test.diff {
|
||||
t.Errorf("%s: printed diff hunks != original diff hunks\n\n# PrintHunks output:\n%s\n\n# Original:\n%s", label, printed, test.diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileDiff_Stat(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
hunks []*Hunk
|
||||
want Stat
|
||||
}{
|
||||
"no change": {
|
||||
hunks: []*Hunk{
|
||||
{Body: []byte(`@@ -0,0 +0,0
|
||||
a
|
||||
b
|
||||
`)},
|
||||
},
|
||||
want: Stat{},
|
||||
},
|
||||
"added/deleted": {
|
||||
hunks: []*Hunk{
|
||||
{Body: []byte(`@@ -0,0 +0,0
|
||||
+a
|
||||
b
|
||||
-c
|
||||
d
|
||||
`)},
|
||||
},
|
||||
want: Stat{Added: 1, Deleted: 1},
|
||||
},
|
||||
"changed": {
|
||||
hunks: []*Hunk{
|
||||
{Body: []byte(`@@ -0,0 +0,0
|
||||
+a
|
||||
+b
|
||||
-c
|
||||
-d
|
||||
e
|
||||
`)},
|
||||
},
|
||||
want: Stat{Added: 1, Changed: 1, Deleted: 1},
|
||||
},
|
||||
"many changes": {
|
||||
hunks: []*Hunk{
|
||||
{Body: []byte(`@@ -0,0 +0,0
|
||||
+a
|
||||
-b
|
||||
+c
|
||||
-d
|
||||
e
|
||||
`)},
|
||||
},
|
||||
want: Stat{Added: 0, Changed: 2, Deleted: 0},
|
||||
},
|
||||
}
|
||||
for label, test := range tests {
|
||||
fdiff := &FileDiff{Hunks: test.hunks}
|
||||
stat := fdiff.Stat()
|
||||
if !reflect.DeepEqual(stat, test.want) {
|
||||
t.Errorf("%s: got diff stat %+v, want %+v", label, stat, test.want)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
2
vendor/sourcegraph.com/sourcegraph/go-diff/diff/doc.go
generated
vendored
Normal file
2
vendor/sourcegraph.com/sourcegraph/go-diff/diff/doc.go
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package diff provides a parser for unified diffs.
|
||||
package diff // import "sourcegraph.com/sourcegraph/go-diff/diff"
|
||||
625
vendor/sourcegraph.com/sourcegraph/go-diff/diff/parse.go
generated
vendored
Normal file
625
vendor/sourcegraph.com/sourcegraph/go-diff/diff/parse.go
generated
vendored
Normal file
@@ -0,0 +1,625 @@
|
||||
package diff
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"sourcegraph.com/sqs/pbtypes"
|
||||
)
|
||||
|
||||
// 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. In the case of non-fatal per-file errors, the error
|
||||
// return value is null and the Errs field in the returned MultiFileDiff is set.
|
||||
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: bufio.NewReader(r)}
|
||||
}
|
||||
|
||||
// MultiFileDiffReader reads a multi-file unified diff.
|
||||
type MultiFileDiffReader struct {
|
||||
line int
|
||||
offset int64
|
||||
reader *bufio.Reader
|
||||
|
||||
// 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) {
|
||||
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 {
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
case OverflowError:
|
||||
r.nextFileFirstLine = []byte(e)
|
||||
return fd, nil
|
||||
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 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 := readLine(r.reader)
|
||||
if err != nil {
|
||||
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: bufio.NewReader(r)}
|
||||
}
|
||||
|
||||
// FileDiffReader reads a unified file diff.
|
||||
type FileDiffReader struct {
|
||||
line int
|
||||
offset int64
|
||||
reader *bufio.Reader
|
||||
|
||||
// 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 {
|
||||
ts := pbtypes.NewTimestamp(*origTime)
|
||||
fd.OrigTime = &ts
|
||||
}
|
||||
if newTime != nil {
|
||||
ts := pbtypes.NewTimestamp(*newTime)
|
||||
fd.NewTime = &ts
|
||||
}
|
||||
|
||||
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).
|
||||
func (r *FileDiffReader) ReadFileHeaders() (origName, newName string, origTimestamp, newTimestamp *time.Time, err error) {
|
||||
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
|
||||
}
|
||||
|
||||
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 = readLine(r.reader)
|
||||
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 {
|
||||
// Timestamp is optional, but this header has it.
|
||||
ts, err := time.Parse(diffTimeParseLayout, parts[1])
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
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", 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 = readLine(r.reader)
|
||||
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
|
||||
}
|
||||
|
||||
r.line++
|
||||
r.offset += int64(len(line))
|
||||
xheaders = append(xheaders, string(line))
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
switch {
|
||||
case (len(fd.Extended) == 3 || len(fd.Extended) == 4 && strings.HasPrefix(fd.Extended[3], "Binary files ")) &&
|
||||
strings.HasPrefix(fd.Extended[1], "new file mode ") && strings.HasPrefix(fd.Extended[0], "diff --git "):
|
||||
|
||||
names := strings.SplitN(fd.Extended[0][len("diff --git "):], " ", 2)
|
||||
fd.OrigName = "/dev/null"
|
||||
fd.NewName = names[1]
|
||||
return true
|
||||
case (len(fd.Extended) == 3 || len(fd.Extended) == 4 && strings.HasPrefix(fd.Extended[3], "Binary files ")) &&
|
||||
strings.HasPrefix(fd.Extended[1], "deleted file mode ") && strings.HasPrefix(fd.Extended[0], "diff --git "):
|
||||
|
||||
names := strings.SplitN(fd.Extended[0][len("diff --git "):], " ", 2)
|
||||
fd.OrigName = names[0]
|
||||
fd.NewName = "/dev/null"
|
||||
return true
|
||||
case len(fd.Extended) == 4 && strings.HasPrefix(fd.Extended[2], "rename from ") && strings.HasPrefix(fd.Extended[3], "rename to ") && strings.HasPrefix(fd.Extended[0], "diff --git "):
|
||||
names := strings.SplitN(fd.Extended[0][len("diff --git "):], " ", 2)
|
||||
fd.OrigName = names[0]
|
||||
fd.NewName = names[1]
|
||||
return true
|
||||
case len(fd.Extended) == 3 && strings.HasPrefix(fd.Extended[2], "Binary files ") && strings.HasPrefix(fd.Extended[0], "diff --git "):
|
||||
names := strings.SplitN(fd.Extended[0][len("diff --git "):], " ", 2)
|
||||
fd.OrigName = names[0]
|
||||
fd.NewName = names[1]
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
)
|
||||
|
||||
// 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: bufio.NewReader(r)}
|
||||
}
|
||||
|
||||
// A HunksReader reads hunks from a unified diff.
|
||||
type HunksReader struct {
|
||||
line int
|
||||
offset int64
|
||||
hunk *Hunk
|
||||
reader *bufio.Reader
|
||||
|
||||
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 = readLine(r.reader)
|
||||
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 bytes.HasPrefix(line, hunkPrefix) {
|
||||
// Saw start of new hunk, so this hunk is
|
||||
// complete. 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
140
vendor/sourcegraph.com/sourcegraph/go-diff/diff/print.go
generated
vendored
Normal file
140
vendor/sourcegraph.com/sourcegraph/go-diff/diff/print.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
package diff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"sourcegraph.com/sqs/pbtypes"
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
if d.Hunks == nil {
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
if err := printFileHeader(&buf, "--- ", d.OrigName, timePtr(d.OrigTime)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := printFileHeader(&buf, "+++ ", d.NewName, timePtr(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 timePtr(ts *pbtypes.Timestamp) *time.Time {
|
||||
if ts == nil {
|
||||
return nil
|
||||
}
|
||||
t := ts.Time()
|
||||
return &t
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
30
vendor/sourcegraph.com/sourcegraph/go-diff/diff/reader_util.go
generated
vendored
Normal file
30
vendor/sourcegraph.com/sourcegraph/go-diff/diff/reader_util.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
package diff
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
// 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 := bytes.TrimSuffix(line_, []byte{'\n'})
|
||||
return line, nil
|
||||
}
|
||||
0
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/empty.diff
generated
vendored
Normal file
0
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/empty.diff
generated
vendored
Normal file
11
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/empty_multi.diff
generated
vendored
Normal file
11
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/empty_multi.diff
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
diff --git Godeps/_workspace/src/sourcegraph.com/sourcegraph/go-diff/diff/testdata/empty.diff Godeps/_workspace/src/sourcegraph.com/sourcegraph/go-diff/diff/testdata/empty.diff
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
|
||||
diff --git Godeps/_workspace/src/sourcegraph.com/sourcegraph/go-diff/diff/testdata/empty_new.diff Godeps/_workspace/src/sourcegraph.com/sourcegraph/go-diff/diff/testdata/empty_new.diff
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..527e2e70f57b02e709f53e3ac2b7f59e2b5a46bc
|
||||
--- /dev/null
|
||||
+++ Godeps/_workspace/src/sourcegraph.com/sourcegraph/go-diff/diff/testdata/empty_new.diff
|
||||
@@ -0,0 +1,2 @@
|
||||
+@@ -1,1 +0,0 @@
|
||||
+-b
|
||||
2
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/empty_new.diff
generated
vendored
Normal file
2
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/empty_new.diff
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
@@ -1,1 +0,0 @@
|
||||
-b
|
||||
2
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/empty_orig.diff
generated
vendored
Normal file
2
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/empty_orig.diff
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
@@ -0,0 +1,1 @@
|
||||
+b
|
||||
24
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/long_line_multi.diff
generated
vendored
Normal file
24
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/long_line_multi.diff
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
5
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/no_newline_both.diff
generated
vendored
Normal file
5
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/no_newline_both.diff
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
@@ -1,1 +1,1 @@
|
||||
-a
|
||||
\ No newline at end of file
|
||||
+b
|
||||
\ No newline at end of file
|
||||
8
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/no_newline_both2.diff
generated
vendored
Normal file
8
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/no_newline_both2.diff
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
@@ -1,3 +1,3 @@
|
||||
0
|
||||
-a
|
||||
-a
|
||||
\ No newline at end of file
|
||||
+b
|
||||
+b
|
||||
\ No newline at end of file
|
||||
6
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/no_newline_new.diff
generated
vendored
Normal file
6
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/no_newline_new.diff
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
@@ -1,3 +1,2 @@
|
||||
a
|
||||
-a
|
||||
-a
|
||||
+a
|
||||
\ No newline at end of file
|
||||
4
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/no_newline_orig.diff
generated
vendored
Normal file
4
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/no_newline_orig.diff
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
@@ -1,1 +1,1 @@
|
||||
-a
|
||||
\ No newline at end of file
|
||||
+b
|
||||
3
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/oneline_hunk.diff
generated
vendored
Normal file
3
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/oneline_hunk.diff
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
@@ -1,1 +1,1 @@
|
||||
-a
|
||||
+b
|
||||
37
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_bad_hunks.diff
generated
vendored
Normal file
37
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_bad_hunks.diff
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
@@ -1,3 +1,9 @@
|
||||
+This is an important
|
||||
+notice! It should
|
||||
+therefore be located at
|
||||
+the beginning of this
|
||||
+document!
|
||||
+
|
||||
This part of the
|
||||
document has stayed the
|
||||
same from version to
|
||||
@@ -5,16 +11,13 @@
|
||||
be shown if it doesn't
|
||||
change. Otherwise, that
|
||||
would not be helping to
|
||||
-compress the size of the
|
||||
-changes.
|
||||
-
|
||||
-This paragraph contains
|
||||
-text that is outdated.
|
||||
-It will be deleted in the
|
||||
-near future.
|
||||
+compress anything.
|
||||
|
||||
It is important to spell
|
||||
-check this dokument. On
|
||||
+check this document. On
|
||||
the other hand, a
|
||||
misspelled word isn't
|
||||
the end of the world.
|
||||
@@ -22,3 +22,7 @@
|
||||
this paragraph needs to
|
||||
be changed. Things can
|
||||
be added after it.
|
||||
+
|
||||
+This paragraph contains
|
||||
+important new additions
|
||||
+to this document.
|
||||
31
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file.diff
generated
vendored
Normal file
31
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file.diff
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
--- oldname 2009-10-11 15:12:20.000000000 +0000
|
||||
+++ newname 2009-10-11 15:12:30.000000000 +0000
|
||||
@@ -1,3 +1,9 @@
|
||||
+This is an important
|
||||
+notice! It should
|
||||
+therefore be located at
|
||||
+the beginning of this
|
||||
+document!
|
||||
+
|
||||
This part of the
|
||||
document has stayed the
|
||||
same from version to
|
||||
@@ -5,16 +11,10 @@
|
||||
be shown if it doesn't
|
||||
change. Otherwise, that
|
||||
would not be helping to
|
||||
-compress the size of the
|
||||
-changes.
|
||||
-
|
||||
-This paragraph contains
|
||||
-text that is outdated.
|
||||
-It will be deleted in the
|
||||
-near future.
|
||||
+compress anything.
|
||||
|
||||
It is important to spell
|
||||
-check this dokument. On
|
||||
+check this document. On
|
||||
the other hand, a
|
||||
misspelled word isn't
|
||||
the end of the world.
|
||||
33
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_extended.diff
generated
vendored
Normal file
33
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_extended.diff
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
diff --git a/vcs/git_cmd.go b/vcs/git_cmd.go
|
||||
index aa4de15..7c048ab 100644
|
||||
--- oldname 2009-10-11 15:12:20.000000000 +0000
|
||||
+++ newname 2009-10-11 15:12:30.000000000 +0000
|
||||
@@ -1,3 +1,9 @@
|
||||
+This is an important
|
||||
+notice! It should
|
||||
+therefore be located at
|
||||
+the beginning of this
|
||||
+document!
|
||||
+
|
||||
This part of the
|
||||
document has stayed the
|
||||
same from version to
|
||||
@@ -5,16 +11,10 @@
|
||||
be shown if it doesn't
|
||||
change. Otherwise, that
|
||||
would not be helping to
|
||||
-compress the size of the
|
||||
-changes.
|
||||
-
|
||||
-This paragraph contains
|
||||
-text that is outdated.
|
||||
-It will be deleted in the
|
||||
-near future.
|
||||
+compress anything.
|
||||
|
||||
It is important to spell
|
||||
-check this dokument. On
|
||||
+check this document. On
|
||||
the other hand, a
|
||||
misspelled word isn't
|
||||
the end of the world.
|
||||
3
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_extended_empty_binary.diff
generated
vendored
Normal file
3
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_extended_empty_binary.diff
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
diff --git a/data/Font.png b/data/Font.png
|
||||
index 17a971d..599f8dd 100644
|
||||
Binary files a/data/Font.png and b/data/Font.png differ
|
||||
3
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_extended_empty_deleted.diff
generated
vendored
Normal file
3
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_extended_empty_deleted.diff
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
diff --git a/vendor/go/build/testdata/empty/dummy b/vendor/go/build/testdata/empty/dummy
|
||||
deleted file mode 100644
|
||||
index e69de29..0000000
|
||||
4
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_extended_empty_deleted_binary.diff
generated
vendored
Normal file
4
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_extended_empty_deleted_binary.diff
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
diff --git a/187/player/random/gopher-0.png b/187/player/random/gopher-0.png
|
||||
deleted file mode 100644
|
||||
index aebdfc7..0000000
|
||||
Binary files a/187/player/random/gopher-0.png and /dev/null differ
|
||||
3
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_extended_empty_new.diff
generated
vendored
Normal file
3
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_extended_empty_new.diff
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
diff --git a/vendor/go/build/testdata/empty/dummy b/vendor/go/build/testdata/empty/dummy
|
||||
new file mode 100644
|
||||
index 0000000..e69de29
|
||||
4
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_extended_empty_new_binary.diff
generated
vendored
Normal file
4
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_extended_empty_new_binary.diff
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
diff --git a/diff/binary-image.png b/diff/binary-image.png
|
||||
new file mode 100644
|
||||
index 0000000..b51756e
|
||||
Binary files /dev/null and b/diff/binary-image.png differ
|
||||
4
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_extended_empty_rename.diff
generated
vendored
Normal file
4
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_extended_empty_rename.diff
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
diff --git a/docs/integrations/Email_Notifications.md b/docs/integrations/email-notifications.md
|
||||
similarity index 100%
|
||||
rename from docs/integrations/Email_Notifications.md
|
||||
rename to docs/integrations/email-notifications.md
|
||||
11
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_no_fractional_seconds.diff
generated
vendored
Normal file
11
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_no_fractional_seconds.diff
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
--- goyaml.go 2011-11-24 19:47:20 +0000
|
||||
+++ goyaml.go 2011-11-28 13:24:39 +0000
|
||||
@@ -256,7 +256,7 @@
|
||||
switch v.Kind() {
|
||||
case reflect.String:
|
||||
return len(v.String()) == 0
|
||||
- case reflect.Interface:
|
||||
+ case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
case reflect.Slice:
|
||||
return v.Len() == 0
|
||||
31
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_no_timestamp.diff
generated
vendored
Normal file
31
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_file_no_timestamp.diff
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
--- oldname
|
||||
+++ newname
|
||||
@@ -1,3 +1,9 @@
|
||||
+This is an important
|
||||
+notice! It should
|
||||
+therefore be located at
|
||||
+the beginning of this
|
||||
+document!
|
||||
+
|
||||
This part of the
|
||||
document has stayed the
|
||||
same from version to
|
||||
@@ -5,16 +11,10 @@
|
||||
be shown if it doesn't
|
||||
change. Otherwise, that
|
||||
would not be helping to
|
||||
-compress the size of the
|
||||
-changes.
|
||||
-
|
||||
-This paragraph contains
|
||||
-text that is outdated.
|
||||
-It will be deleted in the
|
||||
-near future.
|
||||
+compress anything.
|
||||
|
||||
It is important to spell
|
||||
-check this dokument. On
|
||||
+check this document. On
|
||||
the other hand, a
|
||||
misspelled word isn't
|
||||
the end of the world.
|
||||
10
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_hunk.diff
generated
vendored
Normal file
10
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_hunk.diff
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
@@ -1,3 +1,9 @@ Section Header
|
||||
+This is an important
|
||||
+notice! It should
|
||||
+therefore be located at
|
||||
+the beginning of this
|
||||
+document!
|
||||
+
|
||||
This part of the
|
||||
document has stayed the
|
||||
same from version to
|
||||
37
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_hunks.diff
generated
vendored
Normal file
37
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_hunks.diff
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
@@ -1,3 +1,9 @@ Section Header
|
||||
+This is an important
|
||||
+notice! It should
|
||||
+therefore be located at
|
||||
+the beginning of this
|
||||
+document!
|
||||
+
|
||||
This part of the
|
||||
document has stayed the
|
||||
same from version to
|
||||
@@ -5,16 +11,10 @@
|
||||
be shown if it doesn't
|
||||
change. Otherwise, that
|
||||
would not be helping to
|
||||
-compress the size of the
|
||||
-changes.
|
||||
-
|
||||
-This paragraph contains
|
||||
-text that is outdated.
|
||||
-It will be deleted in the
|
||||
-near future.
|
||||
+compress anything.
|
||||
|
||||
It is important to spell
|
||||
-check this dokument. On
|
||||
+check this document. On
|
||||
the other hand, a
|
||||
misspelled word isn't
|
||||
the end of the world.
|
||||
@@ -22,3 +22,7 @@
|
||||
this paragraph needs to
|
||||
be changed. Things can
|
||||
be added after it.
|
||||
+
|
||||
+This paragraph contains
|
||||
+important new additions
|
||||
+to this document.
|
||||
4
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_hunks_no_newline.diff
generated
vendored
Normal file
4
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_hunks_no_newline.diff
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
@@ -1,1 +1,1 @@
|
||||
-b
|
||||
+b
|
||||
\ No newline at end of file
|
||||
63
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_multi_file.diff
generated
vendored
Normal file
63
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_multi_file.diff
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
diff --ruN a/oldname1 b/newname1
|
||||
old mode 0777
|
||||
new mode 0755
|
||||
--- oldname1 2009-10-11 15:12:20.000000000 +0000
|
||||
+++ newname1 2009-10-11 15:12:30.000000000 +0000
|
||||
@@ -1,3 +1,9 @@
|
||||
+This is an important
|
||||
+notice! It should
|
||||
+therefore be located at
|
||||
+the beginning of this
|
||||
+document!
|
||||
+
|
||||
This part of the
|
||||
document has stayed the
|
||||
same from version to
|
||||
@@ -5,16 +11,10 @@
|
||||
be shown if it doesn't
|
||||
change. Otherwise, that
|
||||
would not be helping to
|
||||
-compress the size of the
|
||||
-changes.
|
||||
-
|
||||
-This paragraph contains
|
||||
-text that is outdated.
|
||||
-It will be deleted in the
|
||||
-near future.
|
||||
+compress anything.
|
||||
|
||||
It is important to spell
|
||||
-check this dokument. On
|
||||
+check this document. On
|
||||
diff --ruN a/oldname2 b/newname2
|
||||
--- oldname2 2009-10-11 15:12:20.000000000 +0000
|
||||
+++ newname2 2009-10-11 15:12:30.000000000 +0000
|
||||
@@ -1,3 +1,9 @@
|
||||
+This is an important
|
||||
+notice! It should
|
||||
+therefore be located at
|
||||
+the beginning of this
|
||||
+document!
|
||||
+
|
||||
This part of the
|
||||
document has stayed the
|
||||
same from version to
|
||||
@@ -5,16 +11,10 @@
|
||||
be shown if it doesn't
|
||||
change. Otherwise, that
|
||||
would not be helping to
|
||||
-compress the size of the
|
||||
-changes.
|
||||
-
|
||||
-This paragraph contains
|
||||
-text that is outdated.
|
||||
-It will be deleted in the
|
||||
-near future.
|
||||
+compress anything.
|
||||
|
||||
It is important to spell
|
||||
-check this dokument. On
|
||||
+check this document. On
|
||||
the other hand, a
|
||||
misspelled word isn't
|
||||
the end of the world.
|
||||
29
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_multi_file_binary.diff
generated
vendored
Normal file
29
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_multi_file_binary.diff
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
diff --git a/README.md b/README.md
|
||||
index 7b73e04..36cde13 100644
|
||||
--- a/README.md
|
||||
+++ b/README.md
|
||||
@@ -1,6 +1,8 @@
|
||||
Conception-go [](https://travis-ci.org/shurcooL/Conception-go)
|
||||
=============
|
||||
|
||||
+This is a change.
|
||||
+
|
||||
This is a work in progress Go implementation of [Conception](https://github.com/shurcooL/Conception#demonstration).
|
||||
|
||||
Conception is an experimental project. It's a platform for researching software development tools and techniques. It is driven by a set of guiding principles. Conception-go targets Go development.
|
||||
diff --git a/data/Font.png b/data/Font.png
|
||||
index 17a971d..599f8dd 100644
|
||||
Binary files a/data/Font.png and b/data/Font.png differ
|
||||
diff --git a/main.go b/main.go
|
||||
index 1aced1e..98a982e 100644
|
||||
--- a/main.go
|
||||
+++ b/main.go
|
||||
@@ -6710,6 +6710,8 @@ func init() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
+ // Another plain text change.
|
||||
+
|
||||
//defer profile.Start(profile.CPUProfile).Stop()
|
||||
//defer profile.Start(profile.MemProfile).Stop()
|
||||
|
||||
27
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_multi_file_deleted.diff
generated
vendored
Normal file
27
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_multi_file_deleted.diff
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
diff --git a/vendor/go/build/syslist_test.go b/vendor/go/build/syslist_test.go
|
||||
deleted file mode 100644
|
||||
index 3be2928..0000000
|
||||
--- a/vendor/go/build/syslist_test.go
|
||||
+++ /dev/null
|
||||
@@ -1,62 +0,0 @@
|
||||
-func TestGoodOSArch(t *testing.T) {
|
||||
- for _, test := range tests {
|
||||
- if Default.goodOSArchFile(test.name, make(map[string]bool)) != test.result {
|
||||
- t.Fatalf("goodOSArchFile(%q) != %v", test.name, test.result)
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
diff --git a/vendor/go/build/testdata/empty/dummy b/vendor/go/build/testdata/empty/dummy
|
||||
deleted file mode 100644
|
||||
index e69de29..0000000
|
||||
diff --git a/vendor/go/build/testdata/multi/file.go b/vendor/go/build/testdata/multi/file.go
|
||||
deleted file mode 100644
|
||||
index ee946eb..0000000
|
||||
--- a/vendor/go/build/testdata/multi/file.go
|
||||
+++ /dev/null
|
||||
@@ -1,5 +0,0 @@
|
||||
-// Test data - not compiled.
|
||||
-
|
||||
-package main
|
||||
-
|
||||
-func main() {}
|
||||
27
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_multi_file_new.diff
generated
vendored
Normal file
27
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_multi_file_new.diff
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
diff --git a/_vendor/go/build/syslist_test.go b/_vendor/go/build/syslist_test.go
|
||||
new file mode 100644
|
||||
index 0000000..3be2928
|
||||
--- /dev/null
|
||||
+++ b/_vendor/go/build/syslist_test.go
|
||||
@@ -0,0 +1,62 @@
|
||||
+func TestGoodOSArch(t *testing.T) {
|
||||
+ for _, test := range tests {
|
||||
+ if Default.goodOSArchFile(test.name, make(map[string]bool)) != test.result {
|
||||
+ t.Fatalf("goodOSArchFile(%q) != %v", test.name, test.result)
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/_vendor/go/build/testdata/empty/dummy b/_vendor/go/build/testdata/empty/dummy
|
||||
new file mode 100644
|
||||
index 0000000..e69de29
|
||||
diff --git a/_vendor/go/build/testdata/multi/file.go b/_vendor/go/build/testdata/multi/file.go
|
||||
new file mode 100644
|
||||
index 0000000..ee946eb
|
||||
--- /dev/null
|
||||
+++ b/_vendor/go/build/testdata/multi/file.go
|
||||
@@ -0,0 +1,5 @@
|
||||
+// Test data - not compiled.
|
||||
+
|
||||
+package main
|
||||
+
|
||||
+func main() {}
|
||||
27
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_multi_file_rename.diff
generated
vendored
Normal file
27
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_multi_file_rename.diff
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
diff --git a/README.md b/README.md
|
||||
index 5f3d591..96a24fa 100644
|
||||
--- a/README.md
|
||||
+++ b/README.md
|
||||
@@ -24,6 +24,8 @@ and [view enterprise capabilities](https://www.example.com).*
|
||||
|
||||
## Installation
|
||||
|
||||
+Minor change here.
|
||||
+
|
||||
Follow the 5-minute
|
||||
[installation instructions](https://www.example.com/.docs/getting-started/). For
|
||||
more installation methods, check out the
|
||||
diff --git a/docs/integrations/Email_Notifications.md b/docs/integrations/email-notifications.md
|
||||
similarity index 100%
|
||||
rename from docs/integrations/Email_Notifications.md
|
||||
rename to docs/integrations/email-notifications.md
|
||||
diff --git a/release_notes.md b/release_notes.md
|
||||
index f2ff13f..f060cb5 100644
|
||||
--- a/release_notes.md
|
||||
+++ b/release_notes.md
|
||||
@@ -1,3 +1,5 @@
|
||||
+# new section
|
||||
+
|
||||
# dev
|
||||
|
||||
- Removed example pages and the `--auth.example-flag`
|
||||
29
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_multi_file_single.diff
generated
vendored
Normal file
29
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_multi_file_single.diff
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
diff --ruN a/oldname1 b/newname1
|
||||
--- oldname1 2009-10-11 15:12:20.000000000 +0000
|
||||
+++ newname1 2009-10-11 15:12:30.000000000 +0000
|
||||
@@ -1,3 +1,9 @@
|
||||
+This is an important
|
||||
+notice! It should
|
||||
+therefore be located at
|
||||
+the beginning of this
|
||||
+document!
|
||||
+
|
||||
This part of the
|
||||
document has stayed the
|
||||
same from version to
|
||||
@@ -5,16 +11,10 @@
|
||||
be shown if it doesn't
|
||||
change. Otherwise, that
|
||||
would not be helping to
|
||||
-compress the size of the
|
||||
-changes.
|
||||
-
|
||||
-This paragraph contains
|
||||
-text that is outdated.
|
||||
-It will be deleted in the
|
||||
-near future.
|
||||
+compress anything.
|
||||
|
||||
It is important to spell
|
||||
-check this dokument. On
|
||||
+check this document. On
|
||||
2
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_no_chunksize.diff
generated
vendored
Normal file
2
vendor/sourcegraph.com/sourcegraph/go-diff/diff/testdata/sample_no_chunksize.diff
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
@@ -0,0 +1 @@
|
||||
+Added one line
|
||||
Reference in New Issue
Block a user