@@ -191,6 +191,12 @@ pub fn blame_line(
191
191
} )
192
192
}
193
193
194
+ // attributes on expressions are not allowed
195
+ // however, in our macro its possible that sometimes the
196
+ // assignment to the mutable variable will not be read.
197
+ //
198
+ // when the last line has no expected blame commit
199
+ #[ allow( unused_assignments) ]
194
200
#[ cfg( test) ]
195
201
mod test {
196
202
use std:: fs:: File ;
@@ -199,75 +205,144 @@ mod test {
199
205
200
206
use super :: * ;
201
207
202
- macro_rules! assert_blamed_lines {
203
- ( $repo: ident, $file: ident @ $( $commit_msg: literal => $( $line: literal $expected: literal) ,+) ;+ $( ; ) ?) => { {
208
+ macro_rules! no_commit_flag {
209
+ ( no_commit, $commit_msg: literal) => {
210
+ false
211
+ } ;
212
+ ( , $commit_msg: literal) => {
213
+ true
214
+ } ;
215
+ ( $any: tt, $commit_msg: literal) => {
216
+ compile_error!( concat!(
217
+ "expected no_commit or nothing for commit " ,
218
+ $commit_msg
219
+ ) )
220
+ } ;
221
+ }
222
+
223
+ macro_rules! add_flag {
224
+ ( add, $commit_msg: literal, $line: expr) => {
225
+ true
226
+ } ;
227
+ ( , $commit_msg: literal, $line: expr) => {
228
+ false
229
+ } ;
230
+ ( $any: tt, $commit_msg: literal, $line: expr) => {
231
+ compile_error!( concat!(
232
+ "expected no_commit or nothing for commit " ,
233
+ $commit_msg,
234
+ " line " ,
235
+ $line
236
+ ) )
237
+ } ;
238
+ }
239
+
240
+ /// Helper macro to create a history of the same file being modified.
241
+ ///
242
+ /// Each $commit_msg is a unique identifier for a commit message.
243
+ /// Each $line is a string line of the file. These $lines are collected into a single String
244
+ /// which then becomes the new contents of the $file
245
+ ///
246
+ /// Each $line gets blamed using blame_line. The $expected is the commit identifier that we are expecting for that line.
247
+ macro_rules! assert_line_blame_progress {
248
+ ( $( $commit_msg: literal $( $no_commit: ident) ? => $( $line: literal $( $expected: literal) ? $( $added: ident) ? ) ,+) ;+ $( ; ) ?) => { {
204
249
use std:: fs:: OpenOptions ;
205
250
use std:: io:: Write ;
206
251
252
+ let repo = empty_git_repo( ) ;
253
+ let file = repo. path( ) . join( "file.txt" ) ;
254
+ File :: create( & file) . expect( "could not create file" ) ;
255
+
207
256
let write_file = |content: & str | {
208
257
let mut f = OpenOptions :: new( )
209
258
. write( true )
210
259
. truncate( true )
211
- . open( & $ file)
260
+ . open( & file)
212
261
. unwrap( ) ;
213
262
f. write_all( content. as_bytes( ) ) . unwrap( ) ;
214
263
} ;
215
264
216
- let commit = |msg| create_commit_with_message( $ repo. path( ) , true , msg) ;
265
+ let commit = |msg| create_commit_with_message( repo. path( ) , true , msg) ;
217
266
218
267
$(
219
268
let file_content = concat!( $( $line, "\n " ) ,* ) ;
269
+ eprintln!( "at commit {}:\n \n {file_content}" , stringify!( $commit_msg) ) ;
220
270
write_file( file_content) ;
221
- commit( stringify!( $commit_msg) ) ;
271
+
272
+ let should_commit = no_commit_flag!( $( $no_commit) ?, $commit_msg) ;
273
+ if should_commit {
274
+ commit( stringify!( $commit_msg) ) ;
275
+ }
222
276
223
277
let mut line_number = 0 ;
278
+ let mut added_lines = 0 ;
224
279
225
280
$(
226
281
line_number += 1 ;
227
- let blame_result = blame_line( & $file, line_number, 0 , 0 ) . unwrap( ) . commit_message;
228
- assert_eq!(
229
- blame_result,
230
- Some ( concat!( stringify!( $expected) , "\n " ) . to_owned( ) ) ,
231
- "Blame mismatch at line {}: expected '{}', got {:?}" ,
232
- line_number,
233
- stringify!( $expected) ,
234
- blame_result
235
- ) ;
282
+ let has_add_flag = add_flag!( $( $added) ?, $commit_msg, $line) ;
283
+ if has_add_flag {
284
+ added_lines += 1 ;
285
+ }
286
+ // if there is no $expected, then we don't care what blame_line returns
287
+ // because we won't show it to the user.
288
+ $(
289
+
290
+ let blame_result = blame_line( & file, line_number, added_lines, 0 ) . unwrap( ) . commit_message;
291
+ assert_eq!(
292
+ blame_result,
293
+ Some ( concat!( stringify!( $expected) , "\n " ) . to_owned( ) ) ,
294
+ "Blame mismatch\n at commit: {}\n at line: {}\n line contents: {}\n expected commit: {}\n but got commit: {}" ,
295
+ $commit_msg,
296
+ line_number,
297
+ file_content. lines( ) . nth( line_number. try_into( ) . unwrap( ) ) . unwrap( ) ,
298
+ stringify!( $expected) ,
299
+ blame_result. as_ref( ) . map( |blame| blame. trim_end( ) ) . unwrap_or( "<no commit>" )
300
+ ) ;
301
+ ) ?
236
302
) *
237
303
) *
238
304
} } ;
239
305
}
240
306
241
- fn bob ( ) -> BlameInformation {
242
- BlameInformation {
243
- commit_hash : Some ( "f14ab1cf" . to_owned ( ) ) ,
244
- author_name : Some ( "Bob TheBuilder" . to_owned ( ) ) ,
245
- author_email : Some ( "[email protected] " . to_owned ( ) ) ,
246
- commit_date : Some ( "2028-01-10" . to_owned ( ) ) ,
247
- commit_message : Some ( "feat!: extend house" . to_owned ( ) ) ,
248
- commit_body : Some ( "BREAKING CHANGE: Removed door" . to_owned ( ) ) ,
249
- }
250
- }
251
-
252
307
#[ test]
253
- pub fn blame_lin ( ) {
254
- let repo = empty_git_repo ( ) ;
255
- let file = repo. path ( ) . join ( "file.txt" ) ;
256
- File :: create ( & file) . unwrap ( ) ;
257
-
258
- assert_blamed_lines ! {
259
- repo, file @
308
+ pub fn blamed_lines ( ) {
309
+ assert_line_blame_progress ! {
260
310
1 =>
261
311
"fn main() {" 1 ,
262
312
"" 1 ,
263
313
"}" 1 ;
264
314
2 =>
265
315
"fn main() {" 1 ,
266
- " lol" 2 ,
316
+ " one" 2 ,
317
+ "}" 1 ;
318
+ 3 =>
319
+ "fn main() {" 1 ,
320
+ " one" 2 ,
321
+ " two" 3 ,
322
+ "}" 1 ;
323
+ 4 =>
324
+ "fn main() {" 1 ,
325
+ " two" 3 ,
326
+ "}" 1 ;
327
+ 5 no_commit =>
328
+ "fn main() {" 1 ,
329
+ " hello world" add,
330
+ " two" 3 ,
267
331
"}" 1 ;
268
332
} ;
269
333
}
270
334
335
+ fn bob ( ) -> BlameInformation {
336
+ BlameInformation {
337
+ commit_hash : Some ( "f14ab1cf" . to_owned ( ) ) ,
338
+ author_name : Some ( "Bob TheBuilder" . to_owned ( ) ) ,
339
+ author_email : Some ( "[email protected] " . to_owned ( ) ) ,
340
+ commit_date : Some ( "2028-01-10" . to_owned ( ) ) ,
341
+ commit_message : Some ( "feat!: extend house" . to_owned ( ) ) ,
342
+ commit_body : Some ( "BREAKING CHANGE: Removed door" . to_owned ( ) ) ,
343
+ }
344
+ }
345
+
271
346
#[ test]
272
347
pub fn inline_blame_format_parser ( ) {
273
348
let default_values = "{author}, {date} • {message} • {commit}" ;
0 commit comments