all repos — legit @ 8791732b834d7e71bf72c8a04239e43297a128e0

Machine Telecom's Fork of Legit; the Official Git Frontend of Machine Telecom.

routes/util.go (view raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
package routes

import (
	"context"
	"io/fs"
	"log"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"git.icyphox.sh/legit/git"
	"github.com/alexedwards/flow"
	"github.com/dustin/go-humanize"
)

func isGoModule(gr *git.GitRepo) bool {
	_, err := gr.FileContent("go.mod")
	return err == nil
}

func getDescription(path string) (desc string) {
	db, err := os.ReadFile(filepath.Join(path, "description"))
	if err == nil {
		desc = string(db)
	} else {
		desc = ""
	}
	return
}

func (d *deps) isIgnored(name string) bool {
	for _, i := range d.c.Repo.Ignore {
		if name == i {
			return true
		}
	}

	return false
}

type repository struct {
	Name        string
	Category    string
	Path        string
	Slug        string
	Description string
	LastCommit  string
}

type entry struct {
	Name         string
	Repositories []*repository
}

type entries struct {
	Children []*entry
	c        map[string]*entry
}

func (ent *entries) Add(r repository) {
	if r.Category == "" {
		ent.Children = append(ent.Children, &entry{
			Name:         r.Name,
			Repositories: []*repository{&r},
		})
		return
	}
	t, ok := ent.c[r.Category]
	if !ok {
		t := &entry{
			Name:         r.Category,
			Repositories: []*repository{&r},
		}
		ent.c[r.Category] = t
		ent.Children = append(ent.Children, t)
		return
	}
	t.Repositories = append(t.Repositories, &r)
}

func (d *deps) getAllRepos() (*entries, error) {
	entries := &entries{
		Children: []*entry{},
		c:        map[string]*entry{},
	}
	max := strings.Count(d.c.Repo.ScanPath, string(os.PathSeparator)) + 2

	err := filepath.WalkDir(d.c.Repo.ScanPath, func(path string, de fs.DirEntry, err error) error {
		if err != nil {
			return err
		}

		if de.IsDir() {
			// Check if we've exceeded our recursion depth
			if strings.Count(path, string(os.PathSeparator)) > max {
				return fs.SkipDir
			}

			if d.isIgnored(path) {
				return fs.SkipDir
			}

			// A bare repo should always have at least a HEAD file, if it
			// doesn't we can continue recursing
			if _, err := os.Lstat(filepath.Join(path, "HEAD")); err == nil {
				repo, err := git.Open(path, "")
				if err != nil {
					log.Println(err)
				} else {
					relpath, _ := filepath.Rel(d.c.Repo.ScanPath, path)
					category := strings.Split(relpath, string(os.PathSeparator))[0]
					r := repository{
						Name:        filepath.Base(path),
						Category:    category,
						Path:        path,
						Slug:        relpath,
						Description: getDescription(path),
					}
					if c, err := repo.LastCommit(); err == nil {
						r.LastCommit = humanize.Time(c.Author.When)
					}
					entries.Add(r)
					// Since we found a Git repo, we don't want to recurse
					// further
					return fs.SkipDir
				}
			}
		}
		return nil
	})
	sort.Slice(entries.Children, func(i, j int) bool {
		return entries.Children[i].Name < entries.Children[j].Name
	})
	return entries, err
}

func repoPath(ctx context.Context) string {
	return filepath.Join(
		filepath.Clean(flow.Param(ctx, "category")),
		filepath.Clean(flow.Param(ctx, "name")),
	)
}