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
144
145
146
|
package projects
import (
"encoding/json"
"html/template"
"log"
"math"
"os"
"path"
"strings"
)
type Link struct {
Title string
Href string
Class string `json:",omitempty"`
}
type Project struct {
Name string `json:"-"`
Title string
Description string
Shortdesc string
GoGet string `json:",omitempty"`
ReadmePath string `json:",omitempty"`
Git string `json:",omitempty"` // local git repo
License string `json:",omitempty"`
Links []Link
Tags []string
dir string `json:"-"`
FormattedReadme template.HTML `json:"-"`
}
func LoadProject(name string) (p Project, err error) {
f, err := os.Open(name)
if err != nil {
return p, err
}
defer f.Close()
dec := json.NewDecoder(f)
if err := dec.Decode(&p); err != nil {
return p, err
}
p.dir = path.Dir(name)
p.formatReadme()
nameParts := strings.Split(path.Base(name), ".")
p.Name = strings.Join(nameParts[:len(nameParts)-1], ".")
return
}
type ProjectRepo struct {
Dir string
Projects map[string]Project
Tags map[string]map[string]struct{}
Tagcloud map[string]TagcloudElem
}
const TAGCLOUD_SIZE_CATEGORIES = 5
type TagcloudElem struct {
Tag string
Size int
}
func NewProjectRepo(dir string) *ProjectRepo {
return &ProjectRepo{
Dir: dir,
Projects: make(map[string]Project),
Tags: make(map[string]map[string]struct{}),
Tagcloud: make(map[string]TagcloudElem),
}
}
func (repo *ProjectRepo) updateTags() {
tags := make(map[string]map[string]struct{})
tagcounts := make(map[string]int)
maxcount := 0
for name, proj := range repo.Projects {
for _, tag := range proj.Tags {
if _, ok := tags[tag]; !ok {
tags[tag] = make(map[string]struct{})
}
tags[tag][name] = struct{}{}
tagcount := tagcounts[tag] + 1
tagcounts[tag] = tagcount
if tagcount > maxcount {
maxcount = tagcount
}
}
}
tagcloud := make(map[string]TagcloudElem)
if maxcount > 0 {
for tag, count := range tagcounts {
tagcloud[tag] = TagcloudElem{
Tag: tag,
Size: int(math.Ceil((float64(count) / float64(maxcount)) * TAGCLOUD_SIZE_CATEGORIES)),
}
}
}
repo.Tags = tags
repo.Tagcloud = tagcloud
}
func (repo *ProjectRepo) ScanProjects() {
d, err := os.Open(repo.Dir)
if err != nil {
log.Printf("Failed scanning projects: Could not open dir: %s", err)
return
}
defer d.Close()
names, err := d.Readdirnames(0)
if err != nil {
log.Printf("Failed scanning projects: Could not readdir: %s", err)
return
}
projects := make(map[string]Project)
for _, fname := range names {
if path.Ext(fname) != ".json" {
continue
}
p, err := LoadProject(path.Join(repo.Dir, fname))
if err != nil {
log.Printf("Skip project file %s: %s", fname, err)
continue
}
projects[p.Name] = p
}
repo.Projects = projects
repo.updateTags()
}
|