1package random_bugs
2
3import (
4 "math/rand"
5 "strings"
6 "time"
7
8 "github.com/icrowley/fake"
9
10 "github.com/git-bug/git-bug/entities/bug"
11 "github.com/git-bug/git-bug/entities/identity"
12 "github.com/git-bug/git-bug/repository"
13)
14
15type opsGenerator func(bug.Interface, identity.Interface, int64)
16
17type Options struct {
18 BugNumber int
19 PersonNumber int
20 MinOp int
21 MaxOp int
22}
23
24func DefaultOptions() Options {
25 return Options{
26 BugNumber: 15,
27 PersonNumber: 5,
28 MinOp: 3,
29 MaxOp: 20,
30 }
31}
32
33func FillRepo(repo repository.ClockedRepo, bugNumber int) {
34 FillRepoWithSeed(repo, bugNumber, time.Now().UnixNano())
35}
36
37func FillRepoWithSeed(repo repository.ClockedRepo, bugNumber int, seed int64) {
38 options := DefaultOptions()
39 options.BugNumber = bugNumber
40
41 CommitRandomBugsWithSeed(repo, options, seed)
42}
43
44func CommitRandomBugs(repo repository.ClockedRepo, opts Options) {
45 CommitRandomBugsWithSeed(repo, opts, time.Now().UnixNano())
46}
47
48func CommitRandomBugsWithSeed(repo repository.ClockedRepo, opts Options, seed int64) {
49 generateRandomPersons(repo, opts.PersonNumber)
50
51 bugs := generateRandomBugsWithSeed(opts, seed)
52
53 for _, b := range bugs {
54 err := b.Commit(repo)
55 if err != nil {
56 panic(err)
57 }
58 }
59}
60
61func generateRandomBugsWithSeed(opts Options, seed int64) []*bug.Bug {
62 rand.Seed(seed)
63 fake.Seed(seed)
64
65 // At the moment git-bug has a risk of hash collision is simple
66 // operation (like open/close) are made with the same timestamp.
67 // As a temporary workaround, we use here an strictly increasing
68 // timestamp
69 timestamp := time.Now().Unix()
70
71 opsGenerators := []opsGenerator{
72 comment,
73 comment,
74 title,
75 labels,
76 open,
77 close,
78 }
79
80 result := make([]*bug.Bug, opts.BugNumber)
81
82 for i := 0; i < opts.BugNumber; i++ {
83 addedLabels = []string{}
84
85 b, _, err := bug.Create(
86 randomPerson(),
87 time.Now().Unix(),
88 fake.Sentence(),
89 paragraphs(),
90 nil, nil,
91 )
92
93 if err != nil {
94 panic(err)
95 }
96
97 nOps := opts.MinOp
98
99 if opts.MaxOp > opts.MinOp {
100 nOps += rand.Intn(opts.MaxOp - opts.MinOp)
101 }
102
103 for j := 0; j < nOps; j++ {
104 index := rand.Intn(len(opsGenerators))
105 opsGenerators[index](b, randomPerson(), timestamp)
106 timestamp++
107 }
108
109 result[i] = b
110 }
111
112 return result
113}
114
115func person(repo repository.RepoClock) (*identity.Identity, error) {
116 return identity.NewIdentity(repo, fake.FullName(), fake.EmailAddress())
117}
118
119var persons []*identity.Identity
120
121func generateRandomPersons(repo repository.ClockedRepo, n int) {
122 persons = make([]*identity.Identity, n)
123 for i := range persons {
124 p, err := person(repo)
125 if err != nil {
126 panic(err)
127 }
128 err = p.Commit(repo)
129 if err != nil {
130 panic(err)
131 }
132 persons[i] = p
133 }
134}
135
136func randomPerson() identity.Interface {
137 index := rand.Intn(len(persons))
138 return persons[index]
139}
140
141func paragraphs() string {
142 p := fake.Paragraphs()
143 return strings.Replace(p, "\t", "\n\n", -1)
144}
145
146func comment(b bug.Interface, p identity.Interface, timestamp int64) {
147 _, _, _ = bug.AddComment(b, p, timestamp, paragraphs(), nil, nil)
148}
149
150func title(b bug.Interface, p identity.Interface, timestamp int64) {
151 _, _ = bug.SetTitle(b, p, timestamp, fake.Sentence(), nil)
152}
153
154func open(b bug.Interface, p identity.Interface, timestamp int64) {
155 _, _ = bug.Open(b, p, timestamp, nil)
156}
157
158func close(b bug.Interface, p identity.Interface, timestamp int64) {
159 _, _ = bug.Close(b, p, timestamp, nil)
160}
161
162var addedLabels []string
163
164func labels(b bug.Interface, p identity.Interface, timestamp int64) {
165 var removed []string
166 nbRemoved := rand.Intn(3)
167 for nbRemoved > 0 && len(addedLabels) > 0 {
168 index := rand.Intn(len(addedLabels))
169 removed = append(removed, addedLabels[index])
170 addedLabels[index] = addedLabels[len(addedLabels)-1]
171 addedLabels = addedLabels[:len(addedLabels)-1]
172 nbRemoved--
173 }
174
175 var added []string
176 nbAdded := rand.Intn(3)
177 for i := 0; i < nbAdded; i++ {
178 label := fake.Word()
179 added = append(added, label)
180 addedLabels = append(addedLabels, label)
181 }
182
183 // ignore error
184 // if the randomisation produce no changes, no op
185 // is added to the bug
186 _, _, _ = bug.ChangeLabels(b, p, timestamp, added, removed, nil)
187}