plz / commit / commit.v
179 lines · 162 sloc · 5.06 KB · d4104e7627c1594b9de8e026959b196932f293c8
Raw
1// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by a GPL license that can be found in the LICENSE file.
3module main
4
5import time
6
7struct Commit {
8mut:
9 id int @[primary; sql: serial]
10 author_id int
11 author string
12 hash string @[unique: 'commit']
13 created_at int
14 repo_id int @[unique: 'commit']
15 message string
16}
17
18struct BranchCommit {
19mut:
20 id int @[primary; sql: serial]
21 branch_id int @[unique: 'branch_commit']
22 commit_id int @[unique: 'branch_commit']
23}
24
25fn (commit Commit) relative() string {
26 return time.unix(commit.created_at).relative()
27}
28
29fn (commit Commit) short_hash() string {
30 if commit.hash.len <= 7 {
31 return commit.hash
32 }
33 return commit.hash[..7]
34}
35
36fn row_to_commit(row []string) Commit {
37 if row.len < 7 {
38 return Commit{}
39 }
40 return Commit{
41 id: row[0].int()
42 author_id: row[1].int()
43 author: row[2]
44 hash: row[3]
45 created_at: row[4].int()
46 repo_id: row[5].int()
47 message: row[6]
48 }
49}
50
51const commit_select_cols = 'c.id, c.author_id, c.author, c.hash, c.created_at, c.repo_id, c.message'
52
53fn (mut app App) commit_exists(repo_id int, branch_id int, hash string) bool {
54 rows := db_exec_values(mut app.db,
55 'select 1 from ${sql_table('Commit')} c join ${sql_table('BranchCommit')} bc on bc.commit_id = c.id where c.repo_id = ${repo_id} and bc.branch_id = ${branch_id} and c.hash = ${sql_literal(hash)} limit 1') or {
56 return false
57 }
58 return rows.len > 0
59}
60
61fn (mut app App) add_commit(repo_id int, branch_id int, last_hash string, author string, author_id int, message string, date int) ! {
62 mut existing := app.find_repo_commit_by_hash(repo_id, last_hash)
63 mut commit_id := existing.id
64 if commit_id == 0 {
65 new_commit := Commit{
66 author_id: author_id
67 author: author
68 hash: last_hash
69 created_at: date
70 repo_id: repo_id
71 message: message
72 }
73 sql app.db {
74 insert new_commit into Commit
75 }!
76 commit_id = db_last_insert_id(mut app.db)
77 }
78 link := BranchCommit{
79 branch_id: branch_id
80 commit_id: commit_id
81 }
82 sql app.db {
83 insert link into BranchCommit
84 }!
85}
86
87fn (mut app App) find_repo_commits_as_page(repo_id int, branch_id int, offset int) []Commit {
88 rows := db_exec_values(mut app.db,
89 'select ${commit_select_cols} from ${sql_table('Commit')} c join ${sql_table('BranchCommit')} bc on bc.commit_id = c.id where c.repo_id = ${repo_id} and bc.branch_id = ${branch_id} order by c.created_at desc limit 35 offset ${offset}') or {
90 return []Commit{}
91 }
92 mut commits := []Commit{cap: rows.len}
93 for row in rows {
94 commits << row_to_commit(row)
95 }
96 return commits
97}
98
99fn (mut app App) get_repo_commit_count(repo_id int, branch_id int) int {
100 rows := db_exec_values(mut app.db,
101 'select count(*) from ${sql_table('BranchCommit')} where branch_id = ${branch_id}') or {
102 return 0
103 }
104 if rows.len == 0 || rows[0].len == 0 {
105 return 0
106 }
107 return rows[0][0].int()
108}
109
110fn (mut app App) find_repo_commit_by_hash(repo_id int, hash string) Commit {
111 commits := sql app.db {
112 select from Commit where repo_id == repo_id && hash == hash
113 } or { []Commit{} }
114 if commits.len == 1 {
115 return commits[0]
116 }
117 return Commit{}
118}
119
120fn (mut app App) find_repo_last_commit(repo_id int, branch_id int) Commit {
121 rows := db_exec_values(mut app.db,
122 'select ${commit_select_cols} from ${sql_table('Commit')} c join ${sql_table('BranchCommit')} bc on bc.commit_id = c.id where c.repo_id = ${repo_id} and bc.branch_id = ${branch_id} order by c.created_at desc limit 1') or {
123 return Commit{}
124 }
125 if rows.len == 0 {
126 return Commit{}
127 }
128 return row_to_commit(rows[0])
129}
130
131fn (app App) find_repo_last_commit_time(repo_id int) int {
132 commits := sql app.db {
133 select from Commit where repo_id == repo_id order by created_at desc limit 1
134 } or { return 0 }
135 if commits.len == 0 {
136 return 0
137 }
138 return commits[0].created_at
139}
140
141const activity_weeks = 12
142
143fn (app App) get_repo_activity_buckets(repo_id int) []int {
144 week_seconds := 7 * 24 * 3600
145 now := int(time.now().unix())
146 cutoff := now - activity_weeks * week_seconds
147 commits := sql app.db {
148 select from Commit where repo_id == repo_id && created_at >= cutoff
149 } or { []Commit{} }
150 mut buckets := []int{len: activity_weeks}
151 for c in commits {
152 idx := (c.created_at - cutoff) / week_seconds
153 if idx >= 0 && idx < activity_weeks {
154 buckets[idx]++
155 }
156 }
157 return buckets
158}
159
160// get_user_daily_activity returns commit counts per day for the given user
161// over the past `days` days. Index 0 is the oldest day, index `days-1` is today.
162fn (app App) get_user_daily_activity(user_id int, days int) []int {
163 day_seconds := 24 * 3600
164 now := time.now()
165 // Anchor to the start of today (local), so today is always the last bucket.
166 today_start := i64(time.new(year: now.year, month: now.month, day: now.day).unix())
167 cutoff := int(today_start) - (days - 1) * day_seconds
168 commits := sql app.db {
169 select from Commit where author_id == user_id && created_at >= cutoff
170 } or { []Commit{} }
171 mut buckets := []int{len: days}
172 for c in commits {
173 idx := (c.created_at - cutoff) / day_seconds
174 if idx >= 0 && idx < days {
175 buckets[idx]++
176 }
177 }
178 return buckets
179}
180