all repos

mugit @ bcd986b2e2f7434b43cfac8791a66592218ca108

🐮 git server that your cow will love

mugit/internal/git/tree.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
git: change isIamge to property, 3 months ago
1
package git
2
3
import (
4
	"errors"
5
	"fmt"
6
	"io"
7
	"mime"
8
	"path"
9
	"path/filepath"
10
	"strings"
11
12
	"github.com/go-git/go-git/v5/plumbing/object"
13
)
14
15
type NiceTree struct {
16
	IsFile bool
17
	Name   string
18
	Commit *Commit
19
	Mode   string
20
	Size   int64
21
}
22
23
func (g *Repo) makeNiceTree(t *object.Tree, parent string) []NiceTree {
24
	var nts []NiceTree
25
	for _, e := range t.Entries {
26
		mode, _ := e.Mode.ToOSFileMode()
27
		sz, _ := t.Size(e.Name)
28
29
		// TODO: this should be cached, its pretty expensive
30
		lc, _ := g.lastCommitForFile(path.Join(parent, e.Name))
31
		nts = append(nts, NiceTree{
32
			Name:   e.Name,
33
			Mode:   mode.String(),
34
			IsFile: e.Mode.IsFile(),
35
			Commit: lc,
36
			Size:   sz,
37
		})
38
	}
39
	return nts
40
}
41
42
func (g *Repo) FileTree(path string) ([]NiceTree, error) {
43
	c, err := g.r.CommitObject(g.h)
44
	if err != nil {
45
		return nil, fmt.Errorf("commit object: %w", err)
46
	}
47
48
	tree, err := c.Tree()
49
	if err != nil {
50
		return nil, fmt.Errorf("file tree: %w", err)
51
	}
52
53
	var files []NiceTree
54
	if path == "" {
55
		files = g.makeNiceTree(tree, path)
56
	} else {
57
		o, err := tree.FindEntry(path)
58
		if err != nil {
59
			return nil, err
60
		}
61
62
		if !o.Mode.IsFile() {
63
			subtree, err := tree.Tree(path)
64
			if err != nil {
65
				return nil, err
66
			}
67
			files = g.makeNiceTree(subtree, path)
68
		}
69
	}
70
71
	return files, nil
72
}
73
74
type FileContent struct {
75
	IsBinary bool
76
	IsImage  bool
77
	Content  []byte
78
	Mime     string
79
	Size     int64
80
}
81
82
func (fc *FileContent) String() string {
83
	if fc.IsBinary || fc.IsImage {
84
		return ""
85
	}
86
	return string(fc.Content)
87
}
88
89
func (g *Repo) FileContent(path string) (*FileContent, error) {
90
	c, err := g.r.CommitObject(g.h)
91
	if err != nil {
92
		return &FileContent{}, fmt.Errorf("commit object: %w", err)
93
	}
94
95
	tree, err := c.Tree()
96
	if err != nil {
97
		return &FileContent{}, fmt.Errorf("file tree: %w", err)
98
	}
99
100
	file, err := tree.File(path)
101
	if err != nil {
102
		if errors.Is(err, object.ErrFileNotFound) {
103
			return &FileContent{}, ErrFileNotFound
104
		}
105
		return &FileContent{}, err
106
	}
107
108
	reader, err := file.Reader()
109
	if err != nil {
110
		return nil, fmt.Errorf("file reader: %w", err)
111
	}
112
	defer reader.Close()
113
114
	content, err := io.ReadAll(reader)
115
	if err != nil {
116
		return nil, fmt.Errorf("read file: %w", err)
117
	}
118
119
	isBin, _ := file.IsBinary()
120
	mimeType := mime.TypeByExtension(filepath.Ext(path))
121
	if mimeType == "" {
122
		mimeType = "text/plain"
123
		if isBin {
124
			mimeType = "application/octet-stream"
125
		}
126
	}
127
128
	return &FileContent{
129
		IsBinary: isBin,
130
		IsImage:  strings.HasPrefix(mimeType, "image/"),
131
		Content:  content,
132
		Mime:     mimeType,
133
		Size:     file.Size,
134
	}, nil
135
}