1
+ use std:: convert:: TryFrom ;
1
2
use std:: path:: Path ;
2
3
3
4
use git_repository as git;
4
5
5
6
pub mod entries;
6
7
8
+ mod information {
9
+ use git_repository as git;
10
+ use std:: convert:: TryFrom ;
11
+
12
+ #[ cfg_attr( feature = "serde1" , derive( serde:: Serialize ) ) ]
13
+ pub ( crate ) struct EntryKind {
14
+ dir : usize ,
15
+ file : usize ,
16
+ executable : usize ,
17
+ symlink : usize ,
18
+ submodule : usize ,
19
+ other : usize ,
20
+ }
21
+
22
+ #[ cfg_attr( feature = "serde1" , derive( serde:: Serialize ) ) ]
23
+ pub ( crate ) struct EntryFlag {
24
+ intent_to_add : usize ,
25
+ skip_worktree : usize ,
26
+ }
27
+
28
+ #[ cfg_attr( feature = "serde1" , derive( serde:: Serialize ) ) ]
29
+ pub ( crate ) struct Entries {
30
+ stage_0 : usize ,
31
+ stage_1 : usize ,
32
+ stage_2 : usize ,
33
+ kind : EntryKind ,
34
+ flags : EntryFlag ,
35
+ }
36
+
37
+ #[ cfg_attr( feature = "serde1" , derive( serde:: Serialize ) ) ]
38
+ pub ( crate ) struct Collection {
39
+ version : u8 ,
40
+ entries : Entries ,
41
+ }
42
+
43
+ impl TryFrom < git:: index:: File > for Collection {
44
+ type Error = anyhow:: Error ;
45
+
46
+ fn try_from ( f : git:: index:: File ) -> Result < Self , Self :: Error > {
47
+ Ok ( Collection {
48
+ version : f. version ( ) as u8 ,
49
+ entries : {
50
+ let ( mut stage_0, mut stage_1, mut stage_2) = ( 0 , 0 , 0 ) ;
51
+ let ( mut dir, mut file, mut executable, mut symlink, mut submodule, mut other) = ( 0 , 0 , 0 , 0 , 0 , 0 ) ;
52
+ let ( mut intent_to_add, mut skip_worktree) = ( 0 , 0 ) ;
53
+ for entry in f. entries ( ) {
54
+ match entry. flags . stage ( ) {
55
+ 0 => stage_0 += 1 ,
56
+ 1 => stage_1 += 1 ,
57
+ 2 => stage_2 += 1 ,
58
+ invalid => anyhow:: bail!( "Invalid stage {} encountered" , invalid) ,
59
+ }
60
+ match entry. mode {
61
+ git:: index:: entry:: Mode :: DIR => dir += 1 ,
62
+ git:: index:: entry:: Mode :: FILE => file += 1 ,
63
+ git:: index:: entry:: Mode :: FILE_EXECUTABLE => executable += 1 ,
64
+ git:: index:: entry:: Mode :: SYMLINK => symlink += 1 ,
65
+ git:: index:: entry:: Mode :: COMMIT => submodule += 1 ,
66
+ _ => other += 1 ,
67
+ }
68
+ if entry. flags . contains ( git:: index:: entry:: Flags :: INTENT_TO_ADD ) {
69
+ intent_to_add += 1 ;
70
+ }
71
+ if entry. flags . contains ( git:: index:: entry:: Flags :: SKIP_WORKTREE ) {
72
+ skip_worktree += 1 ;
73
+ }
74
+ }
75
+ Entries {
76
+ stage_0,
77
+ stage_1,
78
+ stage_2,
79
+ kind : EntryKind {
80
+ dir,
81
+ file,
82
+ executable,
83
+ symlink,
84
+ submodule,
85
+ other,
86
+ } ,
87
+ flags : EntryFlag {
88
+ intent_to_add,
89
+ skip_worktree,
90
+ } ,
91
+ }
92
+ } ,
93
+ } )
94
+ }
95
+ }
96
+ }
97
+
98
+ pub fn information (
99
+ index_path : impl AsRef < Path > ,
100
+ out : impl std:: io:: Write ,
101
+ entries:: Options { object_hash, format } : entries:: Options ,
102
+ ) -> anyhow:: Result < ( ) > {
103
+ use crate :: OutputFormat :: * ;
104
+ let info = information:: Collection :: try_from ( parse_file ( index_path, object_hash) ?) ?;
105
+ match format {
106
+ Human => {
107
+ anyhow:: bail!( "Only JSON output is implemented" ) ;
108
+ }
109
+ #[ cfg( feature = "serde1" ) ]
110
+ Json => serde_json:: to_writer_pretty ( out, & info) ?,
111
+ }
112
+ Ok ( ( ) )
113
+ }
114
+
7
115
pub fn entries (
8
116
index_path : impl AsRef < Path > ,
9
117
mut out : impl std:: io:: Write ,
10
118
entries:: Options { object_hash, format } : entries:: Options ,
11
119
) -> anyhow:: Result < ( ) > {
12
120
use crate :: OutputFormat :: * ;
13
- let file = git:: index:: File :: at (
14
- index_path. as_ref ( ) ,
15
- git:: index:: decode:: Options {
16
- object_hash,
17
- ..Default :: default ( )
18
- } ,
19
- ) ?;
121
+ let file = parse_file ( index_path, object_hash) ?;
20
122
21
123
#[ cfg( feature = "serde1" ) ]
22
124
if let Json = format {
@@ -38,3 +140,14 @@ pub fn entries(
38
140
}
39
141
Ok ( ( ) )
40
142
}
143
+
144
+ fn parse_file ( index_path : impl AsRef < Path > , object_hash : git:: hash:: Kind ) -> anyhow:: Result < git:: index:: File > {
145
+ git:: index:: File :: at (
146
+ index_path. as_ref ( ) ,
147
+ git:: index:: decode:: Options {
148
+ object_hash,
149
+ ..Default :: default ( )
150
+ } ,
151
+ )
152
+ . map_err ( Into :: into)
153
+ }
0 commit comments