Skip to content

Commit

Permalink
fix: respect gitattributes
Browse files Browse the repository at this point in the history
Check gitattributes for file attrs before displaying files.

Fixes: #238
  • Loading branch information
aymanbagabas committed Jul 19, 2023
1 parent e4a47c5 commit 10e9f88
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 5 deletions.
62 changes: 62 additions & 0 deletions git/attr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package git

import (
"math/rand"
"os"
"path/filepath"
"strconv"
"strings"
"time"
)

// Attribute represents a Git attribute.
type Attribute struct {
Name string
Value string
}

// CheckAttributes checks the attributes of the given ref and path.
func (r *Repository) CheckAttributes(ref *Reference, path string) ([]Attribute, error) {
rnd := rand.NewSource(time.Now().UnixNano())
fn := "soft-serve-index-" + strconv.Itoa(rand.New(rnd).Int()) // nolint: gosec

Check failure on line 21 in git/attr.go

View workflow job for this annotation

GitHub Actions / lint-soft

directive `// nolint: gosec` should be written without leading space as `//nolint: gosec` (nolintlint)
tmpindex := filepath.Join(os.TempDir(), fn)

defer os.Remove(tmpindex) // nolint: errcheck

Check failure on line 24 in git/attr.go

View workflow job for this annotation

GitHub Actions / lint-soft

directive `// nolint: errcheck` should be written without leading space as `//nolint: errcheck` (nolintlint)

readTree := NewCommand("read-tree", "--reset", "-i", ref.Name().String()).
AddEnvs("GIT_INDEX_FILE=" + tmpindex)
if _, err := readTree.RunInDir(r.Path); err != nil {
return nil, err

Check failure on line 29 in git/attr.go

View workflow job for this annotation

GitHub Actions / lint-soft

error returned from external package is unwrapped: sig: func (*github.com/gogs/git-module.Command).RunInDir(dir string) ([]byte, error) (wrapcheck)
}

Check warning on line 30 in git/attr.go

View check run for this annotation

Codecov / codecov/patch

git/attr.go#L19-L30

Added lines #L19 - L30 were not covered by tests

checkAttr := NewCommand("check-attr", "--cached", "-a", "--", path).
AddEnvs("GIT_INDEX_FILE=" + tmpindex)
out, err := checkAttr.RunInDir(r.Path)
if err != nil {
return nil, err

Check failure on line 36 in git/attr.go

View workflow job for this annotation

GitHub Actions / lint-soft

error returned from external package is unwrapped: sig: func (*github.com/gogs/git-module.Command).RunInDir(dir string) ([]byte, error) (wrapcheck)
}

Check warning on line 37 in git/attr.go

View check run for this annotation

Codecov / codecov/patch

git/attr.go#L32-L37

Added lines #L32 - L37 were not covered by tests

return parseAttributes(path, out), nil

Check warning on line 39 in git/attr.go

View check run for this annotation

Codecov / codecov/patch

git/attr.go#L39

Added line #L39 was not covered by tests
}

func parseAttributes(path string, buf []byte) []Attribute {
var attrs []Attribute

Check failure on line 43 in git/attr.go

View workflow job for this annotation

GitHub Actions / lint-soft

Consider pre-allocating `attrs` (prealloc)
for _, line := range strings.Split(string(buf), "\n") {
if line == "" {
continue

Check warning on line 46 in git/attr.go

View check run for this annotation

Codecov / codecov/patch

git/attr.go#L42-L46

Added lines #L42 - L46 were not covered by tests
}

line = strings.TrimPrefix(line, path+": ")
parts := strings.SplitN(line, ": ", 2)

Check failure on line 50 in git/attr.go

View workflow job for this annotation

GitHub Actions / lint-soft

mnd: Magic number: 2, in <argument> detected (gomnd)
if len(parts) != 2 {

Check failure on line 51 in git/attr.go

View workflow job for this annotation

GitHub Actions / lint-soft

mnd: Magic number: 2, in <condition> detected (gomnd)
continue

Check warning on line 52 in git/attr.go

View check run for this annotation

Codecov / codecov/patch

git/attr.go#L49-L52

Added lines #L49 - L52 were not covered by tests
}

attrs = append(attrs, Attribute{
Name: parts[0],
Value: parts[1],
})

Check warning on line 58 in git/attr.go

View check run for this annotation

Codecov / codecov/patch

git/attr.go#L55-L58

Added lines #L55 - L58 were not covered by tests
}

return attrs

Check warning on line 61 in git/attr.go

View check run for this annotation

Codecov / codecov/patch

git/attr.go#L61

Added line #L61 was not covered by tests
}
38 changes: 33 additions & 5 deletions server/ui/pages/repo/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,26 +376,54 @@ func (f *Files) selectFileCmd() tea.Msg {
log.Printf("ui: files: current item is not a file")
return common.ErrorMsg(errInvalidFile)
}
bin, err := fi.IsBinary()
if err != nil {
f.path = filepath.Dir(f.path)
log.Printf("ui: files: error checking if file is binary %v", err)
return common.ErrorMsg(err)

var err error
var bin bool

r, err := f.repo.Open()
if err == nil {
attrs, err := r.CheckAttributes(f.ref, fi.Path())
if err == nil {
for _, attr := range attrs {
if (attr.Name == "binary" && attr.Value == "set") ||
(attr.Name == "text" && attr.Value == "unset") {
bin = true
break

Check warning on line 391 in server/ui/pages/repo/files.go

View check run for this annotation

Codecov / codecov/patch

server/ui/pages/repo/files.go#L380-L391

Added lines #L380 - L391 were not covered by tests
}
}
} else {
log.Printf("ui: files: error checking attributes %v", err)
}
} else {
log.Printf("ui: files: error opening repo %v", err)
}

Check warning on line 399 in server/ui/pages/repo/files.go

View check run for this annotation

Codecov / codecov/patch

server/ui/pages/repo/files.go#L394-L399

Added lines #L394 - L399 were not covered by tests

if !bin {
bin, err = fi.IsBinary()
if err != nil {
f.path = filepath.Dir(f.path)
log.Printf("ui: files: error checking if file is binary %v", err)
return common.ErrorMsg(err)
}

Check warning on line 407 in server/ui/pages/repo/files.go

View check run for this annotation

Codecov / codecov/patch

server/ui/pages/repo/files.go#L401-L407

Added lines #L401 - L407 were not covered by tests
}

if bin {
f.path = filepath.Dir(f.path)
log.Printf("ui: files: file is binary")
return common.ErrorMsg(errBinaryFile)
}

c, err := fi.Bytes()
if err != nil {
f.path = filepath.Dir(f.path)
log.Printf("ui: files: error reading file %v", err)
return common.ErrorMsg(err)
}

f.lastSelected = append(f.lastSelected, f.selector.Index())
return FileContentMsg{string(c), i.entry.Name()}
}

log.Printf("ui: files: current item is not a file")
return common.ErrorMsg(errNoFileSelected)
}
Expand Down

0 comments on commit 10e9f88

Please sign in to comment.