Browse Source

Limit file contents, results...

- Limit amount of data sent to linguist.LanguageByContents to 512 bytes
   (performance concern, though it is still slow...)

 - Limit amount of results to 8, sum remainder and display as "Other"
   (the widget looks cluttered with a lot of results)

 - Better error handling.
pull/2135/head
tso 9 years ago
parent
commit
8bac1467a1
  1. 103
      routers/repo/view.go

103
routers/repo/view.go

@ -7,7 +7,9 @@ package repo
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os/exec"
"path"
"sort"
"strconv"
@ -203,7 +205,11 @@ func Home(ctx *middleware.Context) {
if err != nil || branchId != lastCommit.ID.String() {
branchId = lastCommit.ID.String()
}
Langs := getLanguageStats(ctx, branchId)
Langs, tsoErr := getLanguageStats(ctx, branchId)
if tsoErr != nil {
ctx.Handle(500, "*blames tso*", err)
return
}
ctx.Data["LanguageStats"] = Langs
}
@ -284,9 +290,12 @@ func Forks(ctx *middleware.Context) {
ctx.HTML(200, FORKS)
}
func getLanguageStats(ctx *middleware.Context, branchId string) interface{} {
func getLanguageStats(ctx *middleware.Context, branchId string) (interface{}, error) {
all_files := linguistlstree(ctx, branchId)
all_files, err := linguistlstree(ctx, branchId)
if err != nil {
return nil, err
}
languages := map[string]float64{}
var total_size float64
@ -307,21 +316,29 @@ func getLanguageStats(ctx *middleware.Context, branchId string) interface{} {
sort.Sort(sort.Reverse(sort.Float64Slice(percent)))
ret := []*LanguageStat{}
other := 0.0
default_color := "#ccc" // grey
for i, p := range percent {
// limit result set
if i > 10 {
// limit result set, doesn't look nice when list is huge
if i >= 8 {
other += p
break
}
lang := results[p]
color := linguist.LanguageColor(lang)
if color == "" {
color = "#ccc" //grey
color = default_color
}
ret = append(ret, &LanguageStat{Name: lang,
Percent: fmt.Sprintf("%.2f%%", p),
Color: color})
}
return ret
if other > 0.0 {
ret = append(ret, &LanguageStat{Name: "Other",
Percent: fmt.Sprintf("%.2f%%", other),
Color: default_color})
}
return ret, nil
}
type LanguageStat struct {
@ -338,27 +355,54 @@ type file struct {
}
// just some utilities...
func gitcmd(ctx *middleware.Context, args ...string) string {
func gitcmd(ctx *middleware.Context, args ...string) (string, error) {
stdout, _, err := com.ExecCmdDir(ctx.Repo.GitRepo.Path, "git", args...)
tsoErr(ctx, err)
return stdout
}
func gitcmdbytes(ctx *middleware.Context, args ...string) []byte {
stdout, _, err := com.ExecCmdDirBytes(ctx.Repo.GitRepo.Path, "git", args...)
tsoErr(ctx, err)
return stdout
if err != nil {
return "", err
}
return stdout, nil
}
func tsoErr(ctx *middleware.Context, err error) {
func gitcatfile(ctx *middleware.Context, hash string) ([]byte, error) {
git := exec.Command("git", "cat-file blob"+hash)
git.Dir = ctx.Repo.GitRepo.Path
stdout, err := git.StdoutPipe()
if err != nil {
ctx.Handle(500, "*blames tso*", err)
return nil, err
}
// please be aware of weirdness, i.e. this error message:
// "read |0: bad file descriptor"
// https://code.google.com/p/go/issues/detail?id=2266
c := make(chan error)
r := make(chan struct{})
blob := make([]byte, 512)
go func() {
git.Start()
r <- struct{}{}
git.Wait()
c <- nil
}()
go func() {
<-r
_, err := stdout.Read(blob)
if err != io.EOF && err != nil {
c <- err
return
}
git.Process.Kill()
c <- nil
}()
err = <-c
return blob, err
}
// returns every file in a tree
// additionally detecting programming language
func linguistlstree(ctx *middleware.Context, treeish string) (files []*file) {
func linguistlstree(ctx *middleware.Context, treeish string) (files []*file, e error) {
files = []*file{}
lstext := gitcmd(ctx, "ls-tree", treeish)
lstext, err := gitcmd(ctx, "ls-tree", treeish)
if err != nil {
return nil, err
}
for _, ln := range strings.Split(lstext, "\n") {
fields := strings.Split(ln, " ")
if len(fields) != 3 {
@ -375,12 +419,20 @@ func linguistlstree(ctx *middleware.Context, treeish string) (files []*file) {
switch ftype {
case "tree":
subdir := linguistlstree(ctx, fhash)
subdir, err := linguistlstree(ctx, fhash)
if err != nil {
return nil, err
}
files = append(files, subdir...)
case "blob":
ssize := gitcmd(ctx, "cat-file", "-s", fhash)
ssize, err := gitcmd(ctx, "cat-file", "-s", fhash)
if err != nil {
return nil, err
}
fsize, err := strconv.ParseFloat(strings.TrimSpace(ssize), 64)
tsoErr(ctx, err)
if err != nil {
return nil, err
}
// if it's an empty file don't even waste time
if fsize == 0 {
@ -407,7 +459,10 @@ func linguistlstree(ctx *middleware.Context, treeish string) (files []*file) {
}
hints := linguist.LanguageHints(fname)
contents := gitcmdbytes(ctx, "cat-file", "blob", fhash)
contents, err := gitcatfile(ctx, fhash)
if err != nil {
return nil, err
}
if linguist.ShouldIgnoreContents(contents) {
continue
@ -422,5 +477,5 @@ func linguistlstree(ctx *middleware.Context, treeish string) (files []*file) {
files = append(files, f)
}
}
return files
return files, nil
}

Loading…
Cancel
Save