@@ -4,6 +4,7 @@ use std::{
4
4
ffi:: OsStr ,
5
5
fmt:: Debug ,
6
6
path:: { Path , PathBuf } ,
7
+ sync:: Arc ,
7
8
} ;
8
9
9
10
use anyhow:: Context ;
@@ -14,20 +15,19 @@ use tracing::{error, info, info_span, instrument, warn};
14
15
15
16
use crate :: database:: schema:: {
16
17
commit:: Commit ,
17
- prefixes:: TreePrefix ,
18
18
repository:: { Repository , RepositoryId } ,
19
19
tag:: { Tag , TagTree } ,
20
20
} ;
21
21
22
- pub fn run ( scan_path : & Path , db : & sled :: Db ) {
22
+ pub fn run ( scan_path : & Path , db : & Arc < rocksdb :: DB > ) {
23
23
let span = info_span ! ( "index_update" ) ;
24
24
let _entered = span. enter ( ) ;
25
25
26
26
info ! ( "Starting index update" ) ;
27
27
28
28
update_repository_metadata ( scan_path, db) ;
29
- update_repository_reflog ( scan_path, db) ;
30
- update_repository_tags ( scan_path, db) ;
29
+ update_repository_reflog ( scan_path, db. clone ( ) ) ;
30
+ update_repository_tags ( scan_path, db. clone ( ) ) ;
31
31
32
32
info ! ( "Flushing to disk" ) ;
33
33
@@ -39,7 +39,7 @@ pub fn run(scan_path: &Path, db: &sled::Db) {
39
39
}
40
40
41
41
#[ instrument( skip( db) ) ]
42
- fn update_repository_metadata ( scan_path : & Path , db : & sled :: Db ) {
42
+ fn update_repository_metadata ( scan_path : & Path , db : & rocksdb :: DB ) {
43
43
let mut discovered = Vec :: new ( ) ;
44
44
discover_repositories ( scan_path, & mut discovered) ;
45
45
@@ -49,7 +49,7 @@ fn update_repository_metadata(scan_path: &Path, db: &sled::Db) {
49
49
} ;
50
50
51
51
let id = match Repository :: open ( db, relative) {
52
- Ok ( v) => v. map_or_else ( || RepositoryId :: new ( db ) , |v| v. get ( ) . id ) ,
52
+ Ok ( v) => v. map_or_else ( RepositoryId :: new, |v| v. get ( ) . id ) ,
53
53
Err ( error) => {
54
54
// maybe we could nuke it ourselves, but we need to instantly trigger
55
55
// a reindex and we could enter into an infinite loop if there's a bug
@@ -75,7 +75,7 @@ fn update_repository_metadata(scan_path: &Path, db: &sled::Db) {
75
75
}
76
76
} ;
77
77
78
- Repository {
78
+ let res = Repository {
79
79
id,
80
80
name,
81
81
description,
@@ -88,6 +88,10 @@ fn update_repository_metadata(scan_path: &Path, db: &sled::Db) {
88
88
. map ( Cow :: Owned ) ,
89
89
}
90
90
. insert ( db, relative) ;
91
+
92
+ if let Err ( error) = res {
93
+ warn ! ( %error, "Failed to insert repository" ) ;
94
+ }
91
95
}
92
96
}
93
97
@@ -116,8 +120,8 @@ fn find_last_committed_time(repo: &git2::Repository) -> Result<OffsetDateTime, g
116
120
}
117
121
118
122
#[ instrument( skip( db) ) ]
119
- fn update_repository_reflog ( scan_path : & Path , db : & sled :: Db ) {
120
- let repos = match Repository :: fetch_all ( db) {
123
+ fn update_repository_reflog ( scan_path : & Path , db : Arc < rocksdb :: DB > ) {
124
+ let repos = match Repository :: fetch_all ( & db) {
121
125
Ok ( v) => v,
122
126
Err ( error) => {
123
127
error ! ( %error, "Failed to read repository index to update reflog, consider deleting database directory" ) ;
@@ -126,7 +130,7 @@ fn update_repository_reflog(scan_path: &Path, db: &sled::Db) {
126
130
} ;
127
131
128
132
for ( relative_path, db_repository) in repos {
129
- let Some ( git_repository) = open_repo ( scan_path, & relative_path, db_repository. get ( ) , db)
133
+ let Some ( git_repository) = open_repo ( scan_path, & relative_path, db_repository. get ( ) , & db)
130
134
else {
131
135
continue ;
132
136
} ;
@@ -139,6 +143,8 @@ fn update_repository_reflog(scan_path: &Path, db: &sled::Db) {
139
143
}
140
144
} ;
141
145
146
+ let mut valid_references = Vec :: new ( ) ;
147
+
142
148
for reference in references. filter_map ( Result :: ok) {
143
149
let reference_name = String :: from_utf8_lossy ( reference. name_bytes ( ) ) ;
144
150
if !reference_name. starts_with ( "refs/heads/" )
@@ -147,18 +153,24 @@ fn update_repository_reflog(scan_path: &Path, db: &sled::Db) {
147
153
continue ;
148
154
}
149
155
156
+ valid_references. push ( reference_name. to_string ( ) ) ;
157
+
150
158
if let Err ( error) = branch_index_update (
151
159
& reference,
152
160
& reference_name,
153
161
& relative_path,
154
162
db_repository. get ( ) ,
155
- db,
163
+ db. clone ( ) ,
156
164
& git_repository,
157
165
false ,
158
166
) {
159
167
error ! ( %error, "Failed to update reflog for {relative_path}@{reference_name}" ) ;
160
168
}
161
169
}
170
+
171
+ if let Err ( error) = db_repository. get ( ) . replace_heads ( & db, & valid_references) {
172
+ error ! ( %error, "Failed to update heads" ) ;
173
+ }
162
174
}
163
175
}
164
176
@@ -168,20 +180,21 @@ fn branch_index_update(
168
180
reference_name : & str ,
169
181
relative_path : & str ,
170
182
db_repository : & Repository < ' _ > ,
171
- db : & sled :: Db ,
183
+ db : Arc < rocksdb :: DB > ,
172
184
git_repository : & git2:: Repository ,
173
185
force_reindex : bool ,
174
186
) -> Result < ( ) , anyhow:: Error > {
175
187
info ! ( "Refreshing indexes" ) ;
176
188
189
+ let commit_tree = db_repository. commit_tree ( db. clone ( ) , reference_name) ;
190
+
177
191
if force_reindex {
178
- db . drop_tree ( TreePrefix :: commit_id ( db_repository . id , reference_name ) ) ?;
192
+ commit_tree . drop_commits ( ) ?;
179
193
}
180
194
181
195
let commit = reference. peel_to_commit ( ) ?;
182
- let commit_tree = db_repository. commit_tree ( db, reference_name) ?;
183
196
184
- let latest_indexed = if let Some ( latest_indexed) = commit_tree. fetch_latest_one ( ) {
197
+ let latest_indexed = if let Some ( latest_indexed) = commit_tree. fetch_latest_one ( ) ? {
185
198
if commit. id ( ) . as_bytes ( ) == & * latest_indexed. get ( ) . hash {
186
199
info ! ( "No commits since last index" ) ;
187
200
return Ok ( ( ) ) ;
@@ -196,7 +209,7 @@ fn branch_index_update(
196
209
revwalk. set_sorting ( Sort :: REVERSE ) ?;
197
210
revwalk. push_ref ( reference_name) ?;
198
211
199
- let tree_len = commit_tree. len ( ) ;
212
+ let tree_len = commit_tree. len ( ) ? ;
200
213
let mut seen = false ;
201
214
let mut i = 0 ;
202
215
for rev in revwalk {
@@ -220,7 +233,7 @@ fn branch_index_update(
220
233
let author = commit. author ( ) ;
221
234
let committer = commit. committer ( ) ;
222
235
223
- Commit :: new ( & commit, & author, & committer) . insert ( & commit_tree, tree_len + i) ;
236
+ Commit :: new ( & commit, & author, & committer) . insert ( & commit_tree, tree_len + i) ? ;
224
237
i += 1 ;
225
238
}
226
239
@@ -238,12 +251,14 @@ fn branch_index_update(
238
251
) ;
239
252
}
240
253
254
+ commit_tree. update_counter ( tree_len + i) ?;
255
+
241
256
Ok ( ( ) )
242
257
}
243
258
244
259
#[ instrument( skip( db) ) ]
245
- fn update_repository_tags ( scan_path : & Path , db : & sled :: Db ) {
246
- let repos = match Repository :: fetch_all ( db) {
260
+ fn update_repository_tags ( scan_path : & Path , db : Arc < rocksdb :: DB > ) {
261
+ let repos = match Repository :: fetch_all ( & db) {
247
262
Ok ( v) => v,
248
263
Err ( error) => {
249
264
error ! ( %error, "Failed to read repository index to update tags, consider deleting database directory" ) ;
@@ -252,13 +267,17 @@ fn update_repository_tags(scan_path: &Path, db: &sled::Db) {
252
267
} ;
253
268
254
269
for ( relative_path, db_repository) in repos {
255
- let Some ( git_repository) = open_repo ( scan_path, & relative_path, db_repository. get ( ) , db)
270
+ let Some ( git_repository) = open_repo ( scan_path, & relative_path, db_repository. get ( ) , & db)
256
271
else {
257
272
continue ;
258
273
} ;
259
274
260
- if let Err ( error) = tag_index_scan ( & relative_path, db_repository. get ( ) , db, & git_repository)
261
- {
275
+ if let Err ( error) = tag_index_scan (
276
+ & relative_path,
277
+ db_repository. get ( ) ,
278
+ db. clone ( ) ,
279
+ & git_repository,
280
+ ) {
262
281
error ! ( %error, "Failed to update tags for {relative_path}" ) ;
263
282
}
264
283
}
@@ -268,12 +287,10 @@ fn update_repository_tags(scan_path: &Path, db: &sled::Db) {
268
287
fn tag_index_scan (
269
288
relative_path : & str ,
270
289
db_repository : & Repository < ' _ > ,
271
- db : & sled :: Db ,
290
+ db : Arc < rocksdb :: DB > ,
272
291
git_repository : & git2:: Repository ,
273
292
) -> Result < ( ) , anyhow:: Error > {
274
- let tag_tree = db_repository
275
- . tag_tree ( db)
276
- . context ( "Failed to read tag index tree" ) ?;
293
+ let tag_tree = db_repository. tag_tree ( db) ;
277
294
278
295
let git_tags: HashSet < _ > = git_repository
279
296
. references ( )
@@ -282,7 +299,7 @@ fn tag_index_scan(
282
299
. filter ( |v| v. name_bytes ( ) . starts_with ( b"refs/tags/" ) )
283
300
. map ( |v| String :: from_utf8_lossy ( v. name_bytes ( ) ) . into_owned ( ) )
284
301
. collect ( ) ;
285
- let indexed_tags: HashSet < String > = tag_tree. list ( ) . into_iter ( ) . collect ( ) ;
302
+ let indexed_tags: HashSet < String > = tag_tree. list ( ) ? . into_iter ( ) . collect ( ) ;
286
303
287
304
// insert any git tags that are missing from the index
288
305
for tag_name in git_tags. difference ( & indexed_tags) {
@@ -330,7 +347,7 @@ fn open_repo<P: AsRef<Path> + Debug>(
330
347
scan_path : & Path ,
331
348
relative_path : P ,
332
349
db_repository : & Repository < ' _ > ,
333
- db : & sled :: Db ,
350
+ db : & rocksdb :: DB ,
334
351
) -> Option < git2:: Repository > {
335
352
match git2:: Repository :: open ( scan_path. join ( relative_path. as_ref ( ) ) ) {
336
353
Ok ( v) => Some ( v) ,
0 commit comments