@@ -8,7 +8,7 @@ extern crate clap;
8
8
9
9
use colored:: Color ;
10
10
use colored:: * ;
11
- use git2:: Repository ;
11
+ use git2:: { Repository , Oid } ;
12
12
use license:: License ;
13
13
use clap:: { App , Arg } ;
14
14
use std:: {
@@ -28,13 +28,15 @@ type Result<T> = result::Result<T, Error>;
28
28
29
29
struct Info {
30
30
project_name : String ,
31
+ current_commit : CommitInfo ,
31
32
version : String ,
32
33
dominant_language : Language ,
33
34
languages : Vec < ( Language , f64 ) > ,
34
35
authors : Vec < String > ,
35
36
last_change : String ,
36
37
repo : String ,
37
38
commits : String ,
39
+ repo_size : String ,
38
40
number_of_lines : usize ,
39
41
license : String ,
40
42
}
@@ -54,6 +56,13 @@ impl fmt::Display for Info {
54
56
self . project_name
55
57
) ?;
56
58
59
+ writeln ! (
60
+ buffer,
61
+ "{}{}" ,
62
+ "HEAD: " . color( color) . bold( ) ,
63
+ self . current_commit
64
+ ) ?;
65
+
57
66
writeln ! (
58
67
buffer,
59
68
"{}{}" ,
@@ -122,6 +131,12 @@ impl fmt::Display for Info {
122
131
"Lines of code: " . color( color) . bold( ) ,
123
132
self . number_of_lines
124
133
) ?;
134
+ writeln ! (
135
+ buffer,
136
+ "{}{}" ,
137
+ "Repository size: " . color( color) . bold( ) ,
138
+ self . repo_size
139
+ ) ?;
125
140
writeln ! (
126
141
buffer,
127
142
"{}{}" ,
@@ -220,6 +235,30 @@ fn true_len(line: &str) -> usize {
220
235
. len ( )
221
236
}
222
237
238
+ struct CommitInfo {
239
+ commit : Oid ,
240
+ refs : Vec < String > ,
241
+ }
242
+
243
+ impl CommitInfo {
244
+ fn new ( commit : Oid , refs : Vec < String > ) -> CommitInfo {
245
+ CommitInfo { commit, refs }
246
+ }
247
+ }
248
+
249
+ impl fmt:: Display for CommitInfo {
250
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
251
+ if self . refs . len ( ) > 0 {
252
+ let refs_str = self . refs . iter ( ) . map ( |ref_name| {
253
+ ref_name. as_str ( )
254
+ } ) . collect :: < Vec < & str > > ( ) . join ( ", " ) ;
255
+ write ! ( f, "{} ({})" , self . commit, refs_str)
256
+ } else {
257
+ write ! ( f, "{}" , self . commit)
258
+ }
259
+ }
260
+ }
261
+
223
262
#[ derive( PartialEq , Eq , Hash , Clone ) ]
224
263
enum Language {
225
264
Assembly ,
@@ -303,20 +342,24 @@ fn main() -> Result<()> {
303
342
let dominant_language = languages_stat_vec[ 0 ] . 0 . clone ( ) ;
304
343
305
344
let authors = get_authors ( & dir, 3 ) ;
345
+ let current_commit_info = get_current_commit_info ( & dir) ?;
306
346
let config = get_configuration ( & dir) ?;
307
347
let version = get_version ( & dir) ?;
308
348
let commits = get_commits ( & dir) ?;
349
+ let repo_size = get_packed_size ( & dir) ?;
309
350
let last_change = get_last_change ( & dir) ?;
310
351
311
352
let info = Info {
312
353
project_name : config. repository_name ,
354
+ current_commit : current_commit_info,
313
355
version,
314
356
dominant_language,
315
357
languages : languages_stat_vec,
316
358
authors,
317
359
last_change,
318
360
repo : config. repository_url ,
319
361
commits,
362
+ repo_size,
320
363
number_of_lines : get_total_loc ( & tokei_langs) ,
321
364
license : project_license ( & dir) ?,
322
365
} ;
@@ -438,6 +481,26 @@ fn get_commits(dir: &str) -> Result<String> {
438
481
}
439
482
}
440
483
484
+ fn get_packed_size ( dir : & str ) -> Result < String > {
485
+ let output = Command :: new ( "git" )
486
+ . arg ( "-C" )
487
+ . arg ( dir)
488
+ . arg ( "count-objects" )
489
+ . arg ( "-vH" )
490
+ . output ( )
491
+ . expect ( "Failed to execute git." ) ;
492
+
493
+ let output = String :: from_utf8_lossy ( & output. stdout ) ;
494
+ let lines = output. to_string ( ) ;
495
+ let size_line = lines. split ( "\n " ) . find ( |line| {
496
+ line. starts_with ( "size-pack:" )
497
+ } ) ;
498
+ match size_line {
499
+ None => Ok ( "??" . into ( ) ) ,
500
+ Some ( size_str) => Ok ( size_str[ 11 ..] . into ( ) )
501
+ }
502
+ }
503
+
441
504
fn is_git_installed ( ) -> bool {
442
505
Command :: new ( "git" )
443
506
. arg ( "--version" )
@@ -527,6 +590,31 @@ fn get_authors(dir: &str, n: usize) -> Vec<String> {
527
590
authors
528
591
}
529
592
593
+ fn get_current_commit_info ( dir : & str ) -> Result < CommitInfo > {
594
+ let repo = Repository :: open ( dir) . map_err ( |_| Error :: NotGitRepo ) ?;
595
+ let head = repo. head ( ) . map_err ( |_| Error :: ReferenceInfoError ) ?;
596
+ let head_oid = head. target ( ) . ok_or ( Error :: ReferenceInfoError ) ?;
597
+ let refs = repo. references ( ) . map_err ( |_| Error :: ReferenceInfoError ) ?;
598
+ let refs_info = refs. into_iter ( ) . filter_map ( |reference| {
599
+ match reference {
600
+ Ok ( reference) => {
601
+ match ( reference. target ( ) , reference. shorthand ( ) ) {
602
+ ( Some ( oid) , Some ( shorthand) ) if oid == head_oid => {
603
+ Some ( if reference. is_tag ( ) {
604
+ String :: from ( "tags/" ) + shorthand
605
+ } else {
606
+ String :: from ( shorthand)
607
+ } )
608
+ } ,
609
+ _ => None
610
+ }
611
+ } ,
612
+ Err ( _) => None ,
613
+ }
614
+ } ) . collect :: < Vec < String > > ( ) ;
615
+ Ok ( CommitInfo :: new ( head_oid, refs_info) )
616
+ }
617
+
530
618
fn get_total_loc ( languages : & tokei:: Languages ) -> usize {
531
619
languages
532
620
. values ( )
@@ -670,6 +758,8 @@ enum Error {
670
758
ReadDirectory ,
671
759
/// Not in a Git Repo
672
760
NotGitRepo ,
761
+ /// Error while getting branch info
762
+ ReferenceInfoError ,
673
763
}
674
764
675
765
impl fmt:: Debug for Error {
@@ -680,6 +770,7 @@ impl fmt::Debug for Error {
680
770
Error :: NoGitData => "Could not retrieve git configuration data" ,
681
771
Error :: ReadDirectory => "Could not read directory" ,
682
772
Error :: NotGitRepo => "This is not a Git Repo" ,
773
+ Error :: ReferenceInfoError => "Error while retrieving reference information" ,
683
774
} ;
684
775
write ! ( f, "{}" , content)
685
776
}
0 commit comments