@@ -11,13 +11,19 @@ pub struct Options {
11
11
pub shallow : gix:: remote:: fetch:: Shallow ,
12
12
pub handshake_info : bool ,
13
13
pub negotiation_info : bool ,
14
+ pub open_negotiation_graph : Option < std:: path:: PathBuf > ,
14
15
}
15
16
16
17
pub const PROGRESS_RANGE : std:: ops:: RangeInclusive < u8 > = 1 ..=3 ;
17
18
18
19
pub ( crate ) mod function {
19
20
use anyhow:: bail;
20
21
use gix:: { prelude:: ObjectIdExt , refspec:: match_group:: validate:: Fix , remote:: fetch:: Status } ;
22
+ use layout:: backends:: svg:: SVGWriter ;
23
+ use layout:: core:: base:: Orientation ;
24
+ use layout:: core:: geometry:: Point ;
25
+ use layout:: core:: style:: StyleAttr ;
26
+ use layout:: std_shapes:: shapes:: { Arrow , Element , ShapeKind } ;
21
27
22
28
use super :: Options ;
23
29
use crate :: OutputFormat ;
@@ -33,6 +39,7 @@ pub(crate) mod function {
33
39
remote,
34
40
handshake_info,
35
41
negotiation_info,
42
+ open_negotiation_graph,
36
43
shallow,
37
44
ref_specs,
38
45
} : Options ,
@@ -82,6 +89,11 @@ pub(crate) mod function {
82
89
if negotiation_info {
83
90
print_negotiate_info ( & mut out, negotiate. as_ref ( ) ) ?;
84
91
}
92
+ if let Some ( ( negotiate, path) ) =
93
+ open_negotiation_graph. and_then ( |path| negotiate. as_ref ( ) . map ( |n| ( n, path) ) )
94
+ {
95
+ render_graph ( & repo, & negotiate. graph , & path, progress) ?;
96
+ }
85
97
Ok :: < _ , anyhow:: Error > ( ( ) )
86
98
}
87
99
Status :: Change {
@@ -99,6 +111,9 @@ pub(crate) mod function {
99
111
if negotiation_info {
100
112
print_negotiate_info ( & mut out, Some ( & negotiate) ) ?;
101
113
}
114
+ if let Some ( path) = open_negotiation_graph {
115
+ render_graph ( & repo, & negotiate. graph , & path, progress) ?;
116
+ }
102
117
Ok ( ( ) )
103
118
}
104
119
} ?;
@@ -108,6 +123,66 @@ pub(crate) mod function {
108
123
Ok ( ( ) )
109
124
}
110
125
126
+ fn render_graph (
127
+ repo : & gix:: Repository ,
128
+ graph : & gix:: negotiate:: IdMap ,
129
+ path : & std:: path:: Path ,
130
+ mut progress : impl gix:: Progress ,
131
+ ) -> anyhow:: Result < ( ) > {
132
+ progress. init ( Some ( graph. len ( ) ) , gix:: progress:: count ( "commits" ) ) ;
133
+ progress. set_name ( "building graph" ) ;
134
+
135
+ let mut map = gix:: hashtable:: HashMap :: default ( ) ;
136
+ let mut vg = layout:: topo:: layout:: VisualGraph :: new ( Orientation :: TopToBottom ) ;
137
+
138
+ for ( id, commit) in graph. iter ( ) . inspect ( |_| progress. inc ( ) ) {
139
+ let source = match map. get ( id) {
140
+ Some ( handle) => * handle,
141
+ None => {
142
+ let handle = vg. add_node ( new_node ( id. attach ( repo) , commit. data . flags ) ) ;
143
+ map. insert ( * id, handle) ;
144
+ handle
145
+ }
146
+ } ;
147
+
148
+ for parent_id in & commit. parents {
149
+ let dest = match map. get ( parent_id) {
150
+ Some ( handle) => * handle,
151
+ None => {
152
+ let flags = match graph. get ( parent_id) {
153
+ Some ( c) => c. data . flags ,
154
+ None => continue ,
155
+ } ;
156
+ let dest = vg. add_node ( new_node ( parent_id. attach ( repo) , flags) ) ;
157
+ map. insert ( * parent_id, dest) ;
158
+ dest
159
+ }
160
+ } ;
161
+ let arrow = Arrow :: simple ( "" ) ;
162
+ vg. add_edge ( arrow, source, dest) ;
163
+ }
164
+ }
165
+
166
+ let start = std:: time:: Instant :: now ( ) ;
167
+ progress. set_name ( "layout graph" ) ;
168
+ progress. info ( format ! ( "writing {path:?}…" ) ) ;
169
+ let mut svg = SVGWriter :: new ( ) ;
170
+ vg. do_it ( false , false , false , & mut svg) ;
171
+ std:: fs:: write ( path, svg. finalize ( ) . as_bytes ( ) ) ?;
172
+ open:: that ( path) ?;
173
+ progress. show_throughput ( start) ;
174
+
175
+ return Ok ( ( ) ) ;
176
+
177
+ fn new_node ( id : gix:: Id < ' _ > , flags : gix:: negotiate:: Flags ) -> Element {
178
+ let pt = Point :: new ( 250. , 50. ) ;
179
+ let name = format ! ( "{}\n \n {flags:?}" , id. shorten_or_id( ) ) ;
180
+ let shape = ShapeKind :: new_box ( name. as_str ( ) ) ;
181
+ let style = StyleAttr :: simple ( ) ;
182
+ Element :: create ( shape, style, Orientation :: LeftToRight , pt)
183
+ }
184
+ }
185
+
111
186
fn print_negotiate_info (
112
187
mut out : impl std:: io:: Write ,
113
188
negotiate : Option < & gix:: remote:: fetch:: outcome:: Negotiate > ,
0 commit comments