summaryrefslogtreecommitdiffstats
path: root/vendor/code.gitea.io/git/tree_entry.go
diff options
context:
space:
mode:
authorSandro Santilli <strk@kbt.io>2016-11-10 17:24:48 +0100
committerThibault Meyer <0xbaadf00d@users.noreply.github.com>2016-11-10 17:24:48 +0100
commit4247304f5aeb791e3e201947478eef4964744146 (patch)
tree47a27cdaafe235512921fb1aba4a5c6738e4c384 /vendor/code.gitea.io/git/tree_entry.go
parent1c0a4e166fc3c37ebed528fc41b1cbca5a00556d (diff)
downloadgitea-4247304f5aeb791e3e201947478eef4964744146.tar.gz
gitea-4247304f5aeb791e3e201947478eef4964744146.zip
Update import paths from github.com/go-gitea to code.gitea.io (#135)
- Update import paths from github.com/go-gitea to code.gitea.io - Fix import path for travis See https://docs.travis-ci.com/user/languages/go#Go-Import-Path
Diffstat (limited to 'vendor/code.gitea.io/git/tree_entry.go')
-rw-r--r--vendor/code.gitea.io/git/tree_entry.go209
1 files changed, 209 insertions, 0 deletions
diff --git a/vendor/code.gitea.io/git/tree_entry.go b/vendor/code.gitea.io/git/tree_entry.go
new file mode 100644
index 0000000000..1c9e89d70c
--- /dev/null
+++ b/vendor/code.gitea.io/git/tree_entry.go
@@ -0,0 +1,209 @@
+// Copyright 2015 The Gogs 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 (
+ "fmt"
+ "path"
+ "path/filepath"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+)
+
+type EntryMode int
+
+// There are only a few file modes in Git. They look like unix file modes, but they can only be
+// one of these.
+const (
+ ENTRY_MODE_BLOB EntryMode = 0100644
+ ENTRY_MODE_EXEC EntryMode = 0100755
+ ENTRY_MODE_SYMLINK EntryMode = 0120000
+ ENTRY_MODE_COMMIT EntryMode = 0160000
+ ENTRY_MODE_TREE EntryMode = 0040000
+)
+
+type TreeEntry struct {
+ ID sha1
+ Type ObjectType
+
+ mode EntryMode
+ name string
+
+ ptree *Tree
+
+ commited bool
+
+ size int64
+ sized bool
+}
+
+func (te *TreeEntry) Name() string {
+ return te.name
+}
+
+func (te *TreeEntry) Size() int64 {
+ if te.IsDir() {
+ return 0
+ } else if te.sized {
+ return te.size
+ }
+
+ stdout, err := NewCommand("cat-file", "-s", te.ID.String()).RunInDir(te.ptree.repo.Path)
+ if err != nil {
+ return 0
+ }
+
+ te.sized = true
+ te.size, _ = strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
+ return te.size
+}
+
+func (te *TreeEntry) IsSubModule() bool {
+ return te.mode == ENTRY_MODE_COMMIT
+}
+
+func (te *TreeEntry) IsDir() bool {
+ return te.mode == ENTRY_MODE_TREE
+}
+
+func (te *TreeEntry) Blob() *Blob {
+ return &Blob{
+ repo: te.ptree.repo,
+ TreeEntry: te,
+ }
+}
+
+type Entries []*TreeEntry
+
+var sorter = []func(t1, t2 *TreeEntry) bool{
+ func(t1, t2 *TreeEntry) bool {
+ return (t1.IsDir() || t1.IsSubModule()) && !t2.IsDir() && !t2.IsSubModule()
+ },
+ func(t1, t2 *TreeEntry) bool {
+ return t1.name < t2.name
+ },
+}
+
+func (tes Entries) Len() int { return len(tes) }
+func (tes Entries) Swap(i, j int) { tes[i], tes[j] = tes[j], tes[i] }
+func (tes Entries) Less(i, j int) bool {
+ t1, t2 := tes[i], tes[j]
+ var k int
+ for k = 0; k < len(sorter)-1; k++ {
+ sort := sorter[k]
+ switch {
+ case sort(t1, t2):
+ return true
+ case sort(t2, t1):
+ return false
+ }
+ }
+ return sorter[k](t1, t2)
+}
+
+func (tes Entries) Sort() {
+ sort.Sort(tes)
+}
+
+type commitInfo struct {
+ entryName string
+ infos []interface{}
+ err error
+}
+
+// GetCommitsInfo takes advantages of concurrey to speed up getting information
+// of all commits that are corresponding to these entries.
+// TODO: limit max goroutines number should be configurable
+func (tes Entries) GetCommitsInfo(commit *Commit, treePath string) ([][]interface{}, error) {
+ if len(tes) == 0 {
+ return nil, nil
+ }
+
+ // Length of taskChan determines how many goroutines (subprocesses) can run at the same time.
+ // The length of revChan should be same as taskChan so goroutines whoever finished job can
+ // exit as early as possible, only store data inside channel.
+ taskChan := make(chan bool, 10)
+ revChan := make(chan commitInfo, 10)
+ doneChan := make(chan error)
+
+ // Receive loop will exit when it collects same number of data pieces as tree entries.
+ // It notifies doneChan before exits or notify early with possible error.
+ infoMap := make(map[string][]interface{}, len(tes))
+ go func() {
+ i := 0
+ for info := range revChan {
+ if info.err != nil {
+ doneChan <- info.err
+ return
+ }
+
+ infoMap[info.entryName] = info.infos
+ i++
+ if i == len(tes) {
+ break
+ }
+ }
+ doneChan <- nil
+ }()
+
+ for i := range tes {
+ // When taskChan is idle (or has empty slots), put operation will not block.
+ // However when taskChan is full, code will block and wait any running goroutines to finish.
+ taskChan <- true
+
+ if tes[i].Type != OBJECT_COMMIT {
+ go func(i int) {
+ time.Sleep(200 * time.Millisecond)
+ cinfo := commitInfo{entryName: tes[i].Name()}
+ c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
+ if err != nil {
+ cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
+ } else {
+ cinfo.infos = []interface{}{tes[i], c}
+ }
+ revChan <- cinfo
+ <-taskChan // Clear one slot from taskChan to allow new goroutines to start.
+ }(i)
+ continue
+ }
+
+ // Handle submodule
+ go func(i int) {
+ cinfo := commitInfo{entryName: tes[i].Name()}
+ sm, err := commit.GetSubModule(path.Join(treePath, tes[i].Name()))
+ if err != nil && !IsErrNotExist(err) {
+ cinfo.err = fmt.Errorf("GetSubModule (%s/%s): %v", treePath, tes[i].Name(), err)
+ revChan <- cinfo
+ return
+ }
+
+ smURL := ""
+ if sm != nil {
+ smURL = sm.URL
+ }
+
+ c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
+ if err != nil {
+ cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
+ } else {
+ cinfo.infos = []interface{}{tes[i], NewSubModuleFile(c, smURL, tes[i].ID.String())}
+ }
+ revChan <- cinfo
+ <-taskChan
+ }(i)
+ }
+
+ if err := <-doneChan; err != nil {
+ return nil, err
+ }
+
+ commitsInfo := make([][]interface{}, len(tes))
+ for i := 0; i < len(tes); i++ {
+ commitsInfo[i] = infoMap[tes[i].Name()]
+ }
+ return commitsInfo, nil
+}