diff --git a/models/git_diff.go b/models/git_diff.go index 9e361d05f..7b0b672ff 100644 --- a/models/git_diff.go +++ b/models/git_diff.go @@ -14,6 +14,7 @@ import ( "io/ioutil" "os" "os/exec" + "strconv" "strings" "code.gitea.io/git" @@ -368,8 +369,15 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D a := line[beg+2 : middle] b := line[middle+3:] if hasQuote { - a = string(git.UnescapeChars([]byte(a[1 : len(a)-1]))) - b = string(git.UnescapeChars([]byte(b[1 : len(b)-1]))) + var err error + a, err = strconv.Unquote(a) + if err != nil { + return nil, fmt.Errorf("Unquote: %v", err) + } + b, err = strconv.Unquote(b) + if err != nil { + return nil, fmt.Errorf("Unquote: %v", err) + } } curFile = &DiffFile{ diff --git a/vendor/code.gitea.io/git/Gopkg.lock b/vendor/code.gitea.io/git/Gopkg.lock new file mode 100644 index 000000000..901c74cf5 --- /dev/null +++ b/vendor/code.gitea.io/git/Gopkg.lock @@ -0,0 +1,38 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/Unknwon/com" + packages = ["."] + revision = "7677a1d7c1137cd3dd5ba7a076d0c898a1ef4520" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "6d212800a42e8ab5c146b8ace3490ee17e5225f9" + +[[projects]] + name = "github.com/mcuadros/go-version" + packages = ["."] + revision = "257f7b9a7d87427c8d7f89469a5958d57f8abd7c" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "d8ed2627bdf02c080bf22230dbb337003b7aba2d" + +[[projects]] + name = "github.com/stretchr/testify" + packages = [ + "assert", + "require" + ] + revision = "976c720a22c8eb4eb6a0b4348ad85ad12491a506" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "d37e90051cd58dd1f99f808626e82d64eac47f2b2334c6fcb9179bfcf2814622" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/code.gitea.io/git/Gopkg.toml b/vendor/code.gitea.io/git/Gopkg.toml new file mode 100644 index 000000000..3e929271b --- /dev/null +++ b/vendor/code.gitea.io/git/Gopkg.toml @@ -0,0 +1,34 @@ +# Gopkg.toml +# +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + name = "github.com/Unknwon/com" + branch = "master" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/code.gitea.io/git/MAINTAINERS b/vendor/code.gitea.io/git/MAINTAINERS index 4f3aab318..8c8a4947d 100644 --- a/vendor/code.gitea.io/git/MAINTAINERS +++ b/vendor/code.gitea.io/git/MAINTAINERS @@ -18,3 +18,4 @@ Antoine Girard (@sapk) Jonas Östanbäck (@cez81) David Schneiderbauer (@daviian) Peter Žeby (@morlinest) +Jonas Franz (@JonasFranzDEV) diff --git a/vendor/code.gitea.io/git/error.go b/vendor/code.gitea.io/git/error.go index 4fd2a5b8f..1aae5a37a 100644 --- a/vendor/code.gitea.io/git/error.go +++ b/vendor/code.gitea.io/git/error.go @@ -40,6 +40,16 @@ func (err ErrNotExist) Error() string { return fmt.Sprintf("object does not exist [id: %s, rel_path: %s]", err.ID, err.RelPath) } +// ErrBadLink entry.FollowLink error +type ErrBadLink struct { + Name string + Message string +} + +func (err ErrBadLink) Error() string { + return fmt.Sprintf("%s: %s", err.Name, err.Message) +} + // ErrUnsupportedVersion error when required git version not matched type ErrUnsupportedVersion struct { Required string diff --git a/vendor/code.gitea.io/git/parse.go b/vendor/code.gitea.io/git/parse.go new file mode 100644 index 000000000..5c964f16e --- /dev/null +++ b/vendor/code.gitea.io/git/parse.go @@ -0,0 +1,81 @@ +// Copyright 2018 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package git + +import ( + "bytes" + "fmt" + "strconv" +) + +// ParseTreeEntries parses the output of a `git ls-tree` command. +func ParseTreeEntries(data []byte) ([]*TreeEntry, error) { + return parseTreeEntries(data, nil) +} + +func parseTreeEntries(data []byte, ptree *Tree) ([]*TreeEntry, error) { + entries := make([]*TreeEntry, 0, 10) + for pos := 0; pos < len(data); { + // expect line to be of the form " \t" + entry := new(TreeEntry) + entry.ptree = ptree + if pos+6 > len(data) { + return nil, fmt.Errorf("Invalid ls-tree output: %s", string(data)) + } + switch string(data[pos : pos+6]) { + case "100644": + entry.mode = EntryModeBlob + entry.Type = ObjectBlob + pos += 12 // skip over "100644 blob " + case "100755": + entry.mode = EntryModeExec + entry.Type = ObjectBlob + pos += 12 // skip over "100755 blob " + case "120000": + entry.mode = EntryModeSymlink + entry.Type = ObjectBlob + pos += 12 // skip over "120000 blob " + case "160000": + entry.mode = EntryModeCommit + entry.Type = ObjectCommit + pos += 14 // skip over "160000 object " + case "040000": + entry.mode = EntryModeTree + entry.Type = ObjectTree + pos += 12 // skip over "040000 tree " + default: + return nil, fmt.Errorf("unknown type: %v", string(data[pos:pos+6])) + } + + if pos+40 > len(data) { + return nil, fmt.Errorf("Invalid ls-tree output: %s", string(data)) + } + id, err := NewIDFromString(string(data[pos : pos+40])) + if err != nil { + return nil, fmt.Errorf("Invalid ls-tree output: %v", err) + } + entry.ID = id + pos += 41 // skip over sha and trailing space + + end := pos + bytes.IndexByte(data[pos:], '\n') + if end < pos { + return nil, fmt.Errorf("Invalid ls-tree output: %s", string(data)) + } + + // In case entry name is surrounded by double quotes(it happens only in git-shell). + if data[pos] == '"' { + entry.name, err = strconv.Unquote(string(data[pos:end])) + if err != nil { + return nil, fmt.Errorf("Invalid ls-tree output: %v", err) + } + } else { + entry.name = string(data[pos:end]) + } + + pos = end + 1 + entries = append(entries, entry) + } + return entries, nil +} diff --git a/vendor/code.gitea.io/git/repo_blame.go b/vendor/code.gitea.io/git/repo_blame.go index b48cbeea6..80ec50e47 100644 --- a/vendor/code.gitea.io/git/repo_blame.go +++ b/vendor/code.gitea.io/git/repo_blame.go @@ -4,7 +4,21 @@ package git +import "fmt" + // FileBlame return the Blame object of file func (repo *Repository) FileBlame(revision, path, file string) ([]byte, error) { - return NewCommand("blame", "--root", file).RunInDirBytes(path) + return NewCommand("blame", "--root", "--", file).RunInDirBytes(path) +} + +// LineBlame returns the latest commit at the given line +func (repo *Repository) LineBlame(revision, path, file string, line uint) (*Commit, error) { + res, err := NewCommand("blame", fmt.Sprintf("-L %d,%d", line, line), "-p", revision, "--", file).RunInDir(path) + if err != nil { + return nil, err + } + if len(res) < 40 { + return nil, fmt.Errorf("invalid result of blame: %s", res) + } + return repo.GetCommit(string(res[:40])) } diff --git a/vendor/code.gitea.io/git/repo_commit.go b/vendor/code.gitea.io/git/repo_commit.go index 56bebd7a3..1acdfffb3 100644 --- a/vendor/code.gitea.io/git/repo_commit.go +++ b/vendor/code.gitea.io/git/repo_commit.go @@ -9,6 +9,8 @@ import ( "container/list" "strconv" "strings" + + "github.com/mcuadros/go-version" ) // GetRefCommitID returns the last commit ID string of given reference (branch or tag). @@ -274,7 +276,7 @@ func (repo *Repository) CommitsCountBetween(start, end string) (int64, error) { func (repo *Repository) commitsBefore(id SHA1, limit int) (*list.List, error) { cmd := NewCommand("log") if limit > 0 { - cmd.AddArguments("-"+ strconv.Itoa(limit), prettyLogFormat, id.String()) + cmd.AddArguments("-"+strconv.Itoa(limit), prettyLogFormat, id.String()) } else { cmd.AddArguments(prettyLogFormat, id.String()) } @@ -316,15 +318,35 @@ func (repo *Repository) getCommitsBeforeLimit(id SHA1, num int) (*list.List, err } func (repo *Repository) getBranches(commit *Commit, limit int) ([]string, error) { - stdout, err := NewCommand("for-each-ref", "--count="+ strconv.Itoa(limit), "--format=%(refname)", "--contains", commit.ID.String(), BranchPrefix).RunInDir(repo.Path) + if version.Compare(gitVersion, "2.7.0", ">=") { + stdout, err := NewCommand("for-each-ref", "--count="+strconv.Itoa(limit), "--format=%(refname:strip=2)", "--contains", commit.ID.String(), BranchPrefix).RunInDir(repo.Path) + if err != nil { + return nil, err + } + + branches := strings.Fields(stdout) + return branches, nil + } + + stdout, err := NewCommand("branch", "--contains", commit.ID.String()).RunInDir(repo.Path) if err != nil { return nil, err } refs := strings.Split(stdout, "\n") - branches := make([]string, len(refs)-1) - for i, ref := range refs[:len(refs)-1] { - branches[i] = strings.TrimPrefix(ref, BranchPrefix) + + var max int + if len(refs) > limit { + max = limit + } else { + max = len(refs) - 1 + } + + branches := make([]string, max) + for i, ref := range refs[:max] { + parts := strings.Fields(ref) + + branches[i] = parts[len(parts)-1] } return branches, nil } diff --git a/vendor/code.gitea.io/git/sha1.go b/vendor/code.gitea.io/git/sha1.go index 50708dee8..6c9d53949 100644 --- a/vendor/code.gitea.io/git/sha1.go +++ b/vendor/code.gitea.io/git/sha1.go @@ -5,6 +5,7 @@ package git import ( + "bytes" "encoding/hex" "fmt" "strings" @@ -26,43 +27,23 @@ func (id SHA1) Equal(s2 interface{}) bool { } return v == id.String() case []byte: - if len(v) != 20 { - return false - } - for i, v := range v { - if id[i] != v { - return false - } - } + return bytes.Equal(v, id[:]) case SHA1: - for i, v := range v { - if id[i] != v { - return false - } - } + return v == id default: return false } - return true } // String returns string (hex) representation of the Oid. func (id SHA1) String() string { - result := make([]byte, 0, 40) - hexvalues := []byte("0123456789abcdef") - for i := 0; i < 20; i++ { - result = append(result, hexvalues[id[i]>>4]) - result = append(result, hexvalues[id[i]&0xf]) - } - return string(result) + return hex.EncodeToString(id[:]) } // MustID always creates a new SHA1 from a [20]byte array with no validation of input. func MustID(b []byte) SHA1 { var id SHA1 - for i := 0; i < 20; i++ { - id[i] = b[i] - } + copy(id[:], b) return id } diff --git a/vendor/code.gitea.io/git/tree.go b/vendor/code.gitea.io/git/tree.go index 05e7afd12..4654dac30 100644 --- a/vendor/code.gitea.io/git/tree.go +++ b/vendor/code.gitea.io/git/tree.go @@ -5,8 +5,6 @@ package git import ( - "bytes" - "fmt" "strings" ) @@ -30,84 +28,6 @@ func NewTree(repo *Repository, id SHA1) *Tree { } } -var escapeChar = []byte("\\") - -// UnescapeChars reverses escaped characters. -func UnescapeChars(in []byte) []byte { - if bytes.Index(in, escapeChar) == -1 { - return in - } - - endIdx := len(in) - 1 - isEscape := false - out := make([]byte, 0, endIdx+1) - for i := range in { - if in[i] == '\\' && !isEscape { - isEscape = true - continue - } - isEscape = false - out = append(out, in[i]) - } - return out -} - -// parseTreeData parses tree information from the (uncompressed) raw -// data from the tree object. -func parseTreeData(tree *Tree, data []byte) ([]*TreeEntry, error) { - entries := make([]*TreeEntry, 0, 10) - l := len(data) - pos := 0 - for pos < l { - entry := new(TreeEntry) - entry.ptree = tree - step := 6 - switch string(data[pos : pos+step]) { - case "100644": - entry.mode = EntryModeBlob - entry.Type = ObjectBlob - case "100755": - entry.mode = EntryModeExec - entry.Type = ObjectBlob - case "120000": - entry.mode = EntryModeSymlink - entry.Type = ObjectBlob - case "160000": - entry.mode = EntryModeCommit - entry.Type = ObjectCommit - - step = 8 - case "040000": - entry.mode = EntryModeTree - entry.Type = ObjectTree - default: - return nil, fmt.Errorf("unknown type: %v", string(data[pos:pos+step])) - } - pos += step + 6 // Skip string type of entry type. - - step = 40 - id, err := NewIDFromString(string(data[pos : pos+step])) - if err != nil { - return nil, err - } - entry.ID = id - pos += step + 1 // Skip half of SHA1. - - step = bytes.IndexByte(data[pos:], '\n') - - // In case entry name is surrounded by double quotes(it happens only in git-shell). - if data[pos] == '"' { - entry.name = string(UnescapeChars(data[pos+1 : pos+step-1])) - } else { - entry.name = string(data[pos : pos+step]) - } - - pos += step + 1 - entries = append(entries, entry) - } - return entries, nil -} - // SubTree get a sub tree by the sub dir path func (t *Tree) SubTree(rpath string) (*Tree, error) { if len(rpath) == 0 { @@ -142,12 +62,11 @@ func (t *Tree) ListEntries() (Entries, error) { if t.entriesParsed { return t.entries, nil } - t.entriesParsed = true stdout, err := NewCommand("ls-tree", t.ID.String()).RunInDirBytes(t.repo.Path) if err != nil { return nil, err } - t.entries, err = parseTreeData(t, stdout) + t.entries, err = parseTreeEntries(stdout, t) return t.entries, err } diff --git a/vendor/code.gitea.io/git/tree_entry.go b/vendor/code.gitea.io/git/tree_entry.go index 41023010c..6201eef8f 100644 --- a/vendor/code.gitea.io/git/tree_entry.go +++ b/vendor/code.gitea.io/git/tree_entry.go @@ -5,6 +5,7 @@ package git import ( + "io" "sort" "strconv" "strings" @@ -90,6 +91,45 @@ func (te *TreeEntry) Blob() *Blob { } } +// FollowLink returns the entry pointed to by a symlink +func (te *TreeEntry) FollowLink() (*TreeEntry, error) { + if !te.IsLink() { + return nil, ErrBadLink{te.Name(), "not a symlink"} + } + + // read the link + r, err := te.Blob().Data() + if err != nil { + return nil, err + } + buf := make([]byte, te.Size()) + _, err = io.ReadFull(r, buf) + if err != nil { + return nil, err + } + + lnk := string(buf) + t := te.ptree + + // traverse up directories + for ; t != nil && strings.HasPrefix(lnk, "../"); lnk = lnk[3:] { + t = t.ptree + } + + if t == nil { + return nil, ErrBadLink{te.Name(), "points outside of repo"} + } + + target, err := t.GetTreeEntryByPath(lnk) + if err != nil { + if IsErrNotExist(err) { + return nil, ErrBadLink{te.Name(), "broken link"} + } + return nil, err + } + return target, nil +} + // GetSubJumpablePathName return the full path of subdirectory jumpable ( contains only one directory ) func (te *TreeEntry) GetSubJumpablePathName() string { if te.IsSubModule() || !te.IsDir() { diff --git a/vendor/vendor.json b/vendor/vendor.json index 409129ee0..e80b3588b 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -3,10 +3,10 @@ "ignore": "test appengine", "package": [ { - "checksumSHA1": "Gz+a5Qo4PCiB/Gf2f02v8HEAxDM=", + "checksumSHA1": "xwQNnA5geMAdbiBjBABtsjqZZMw=", "path": "code.gitea.io/git", - "revision": "6798d0f202cdc7187c00a467b586a4bdee27e8c9", - "revisionTime": "2018-01-14T14:37:32Z" + "revision": "31f4b8e8c805438ac6d8914b38accb1d8aaf695e", + "revisionTime": "2018-05-26T05:17:21Z" }, { "checksumSHA1": "Qtq0kW+BnpYMOriaoCjMa86WGG8=",