fce44ae9 Andy McCall 1 month ago ↶
1
2
3
use super :: format:: plural;
4
use super :: open;
c6aa5bd9 Andy McCall 1 month ago ↶
5
use super :: json;
135212de Andy McCall 1 month ago ↶
6
use super :: ui;
fce44ae9 Andy McCall 1 month ago ↶
7
use anyhow:: { Context, Result } ;
8
use oxy_core:: repo:: Repo;
9
use std:: path:: PathBuf;
10
2863456a Andy McCall 1 month ago ↶
11
pub fn clone ( url : & str , dest : Option< PathBuf> , max_blob : Option< & str > , sparse : & [String], depth : Option< u32 > ) -> Result< i32 > {
fce44ae9 Andy McCall 1 month ago ↶
12
let dest = dest.unwrap_or_else ( | | {
13
let base = url.trim_end_matches ( ' /' ) .rsplit ( ' /' ) .next ( ) .unwrap_or ( " repo" ) ;
14
PathBuf:: from( base)
15
} ) ;
b3c5a59a Andy McCall 1 month ago ↶
16
let max_blob = max_blob.map ( oxy_core:: repo:: parse_size) .transpose ( ) ? ;
135212de Andy McCall 1 month ago ↶
17
let sp = ui:: spinner( & format! ( " Cloning {url} …" ) ) ;
2863456a Andy McCall 1 month ago ↶
18
let repo = match depth {
19
Some ( d) => Repo:: clone_shallow( url, & dest, d, max_blob, sparse) ? ,
20
None => Repo:: clone_with( url, & dest, max_blob, sparse) ? ,
21
} ;
fce44ae9 Andy McCall 1 month ago ↶
22
let heads = repo.bookmark_heads ( ) ? ;
94084087 Andy McCall 1 month ago ↶
23
sp.done ( & format! ( " {} into {} {} " , ui:: done( " Cloned" ) , ui:: path( repo.root ( ) .display ( ) ) , ui:: dim( format! ( " ({url} , {} with {} )" , ui:: bookmark( & repo.config.bookmark) , plural ( heads.len ( ) , " head" ) ) ) ) ) ;
fce44ae9 Andy McCall 1 month ago ↶
24
Ok ( 0 )
25
}
26
27
pub fn remote_add ( name : & str , url : & str ) -> Result< i32 > {
28
let mut repo = open ( ) ? ;
29
repo.config.set ( & format! ( " remote.{name} .url" ) , url) ? ;
30
repo.save_config ( ) ? ;
94084087 Andy McCall 1 month ago ↶
31
println! ( " {} remote {} {} {url} " , ui:: done( " Added" ) , ui:: bookmark( name) , ui:: dim( ui:: glyph( " →" , " ->" ) ) ) ;
fce44ae9 Andy McCall 1 month ago ↶
32
Ok ( 0 )
33
}
34
35
pub fn remote_remove ( name : & str ) -> Result< i32 > {
36
let mut repo = open ( ) ? ;
37
repo.config.set ( & format! ( " remote.{name} .url" ) , " " ) ? ;
38
repo.save_config ( ) ? ;
94084087 Andy McCall 1 month ago ↶
39
println! ( " {} remote {} " , ui:: done( " Removed" ) , ui:: bookmark( name) ) ;
fce44ae9 Andy McCall 1 month ago ↶
40
Ok ( 0 )
41
}
42
c6aa5bd9 Andy McCall 1 month ago ↶
43
pub fn remote_list ( as_json : bool ) -> Result< i32 > {
fce44ae9 Andy McCall 1 month ago ↶
44
let repo = open ( ) ? ;
45
let view = repo.view ( ) ? ;
c6aa5bd9 Andy McCall 1 month ago ↶
46
if as_json {
47
let items = repo.config.remotes.iter ( ) .map ( | ( name , url ) | {
48
let bms = view.remotes.get ( name) .map ( | b | {
49
json:: arr( b.iter ( ) .map ( | ( bm , st ) | {
50
let heads = repo.store ( ) .get_state ( st) .map ( | s | s.heads ) .unwrap_or_default ( ) ;
51
json:: obj( [ ( " name" , json:: s( bm) ) , ( " heads" , json:: hashes( & heads) ) ] )
52
} ) )
53
} ) ;
54
json:: obj( [ ( " name" , json:: s( name) ) , ( " url" , json:: s( url) ) , ( " bookmarks" , bms.unwrap_or_else ( | | " []" .into ( ) ) ) ] )
55
} ) ;
56
println! ( " {} " , json:: arr( items) ) ;
57
return Ok ( 0 ) ;
58
}
94084087 Andy McCall 1 month ago ↶
59
if repo.config.remotes.is_empty ( ) {
60
println! ( " {} " , ui:: dim( " No remotes; add one with oxy remote add <name> <url>." ) ) ;
61
}
fce44ae9 Andy McCall 1 month ago ↶
62
for ( name, url) in & repo.config.remotes {
94084087 Andy McCall 1 month ago ↶
63
println! ( " {} {} {} {} " , ui:: ok( ui:: glyph( " ⇄" , " <>" ) ) , ui:: bookmark( name) , ui:: sep( ) , ui:: dim( url) ) ;
fce44ae9 Andy McCall 1 month ago ↶
64
if let Some ( bms) = view.remotes.get ( name) {
65
for ( bm, st) in bms {
66
let heads = repo.store ( ) .get_state ( st) .map ( | s | s.heads.len ( ) ) .unwrap_or ( 0 ) ;
94084087 Andy McCall 1 month ago ↶
67
println! ( " {} {} {} {} " , ui:: dim( ui:: glyph( " ↳" , " ->" ) ) , ui:: id( format! ( " {name} /{bm} " ) ) , ui:: sep( ) , ui:: dim( plural ( heads, " head" ) ) ) ;
fce44ae9 Andy McCall 1 month ago ↶
68
}
69
}
70
}
71
Ok ( 0 )
72
}
73
74
fn remote_name ( remote : Option< & str > ) -> String {
75
remote.unwrap_or ( " origin" ) .to_string ( )
76
}
77
c6aa5bd9 Andy McCall 1 month ago ↶
78
pub fn fetch ( remote : Option< & str > , as_json : bool ) -> Result< i32 > {
fce44ae9 Andy McCall 1 month ago ↶
79
let repo = open ( ) ? ;
80
let remote = remote_name ( remote) ;
135212de Andy McCall 1 month ago ↶
81
let sp = ui:: spinner( & format! ( " Fetching from {remote} …" ) ) ;
83e0677b Andy McCall 1 month ago ↶
82
let report = repo.fetch ( & remote) ? ;
135212de Andy McCall 1 month ago ↶
83
sp.clear ( ) ;
c6aa5bd9 Andy McCall 1 month ago ↶
84
if as_json {
85
println! (
86
" {} " ,
87
json:: obj( [
88
( " remote" , json:: s( & remote) ) ,
89
( " refs" , json:: arr( report.refs.iter ( ) .map ( | ( name , heads , n ) | json:: obj( [ ( " name" , json:: s( name) ) , ( " heads" , json:: hashes( heads) ) , ( " new" , json:: n( * n) ) ] ) ) ) ) ,
90
( " new_tags" , json:: n( report.new_tags) ) ,
91
( " unverified" , json:: b( report.unverified) ) ,
92
] )
93
) ;
94
return Ok ( 0 ) ;
95
}
94084087 Andy McCall 1 month ago ↶
96
if report.refs.is_empty ( ) {
97
println! ( " {} {} " , ui:: done( " Fetched" ) , ui:: dim( format! ( " nothing new from {remote} " ) ) ) ;
98
}
83e0677b Andy McCall 1 month ago ↶
99
for ( name, heads, n) in & report.refs {
94084087 Andy McCall 1 month ago ↶
100
let what = if * n = = 0 { ui:: dim( " up to date" ) } else { ui:: ok( plural ( * n, " new change" ) ) } ;
101
println! ( " {} {} {} {} {} {what} " , ui:: done( " Fetched" ) , ui:: id( format! ( " {remote} /{name} " ) ) , ui:: sep( ) , ui:: dim( plural ( heads.len ( ) , " head" ) ) , ui:: sep( ) ) ;
83e0677b Andy McCall 1 month ago ↶
102
}
132b884b Andy McCall 1 month ago ↶
103
if report.new_tags > 0 {
94084087 Andy McCall 1 month ago ↶
104
println! ( " {} {} " , ui:: note( ) , ui:: dim( format! ( " {} adopted" , plural ( report.new_tags, " tag" ) ) ) ) ;
132b884b Andy McCall 1 month ago ↶
105
}
83e0677b Andy McCall 1 month ago ↶
106
if report.unverified {
94084087 Andy McCall 1 month ago ↶
107
eprintln! ( " {} {remote} has no trust policy; nothing fetched from it was verified" , ui:: caution( ) ) ;
fce44ae9 Andy McCall 1 month ago ↶
108
}
109
Ok ( 0 )
110
}
111
c6aa5bd9 Andy McCall 1 month ago ↶
112
pub fn pull ( remote : Option< & str > , as_json : bool ) -> Result< i32 > {
fce44ae9 Andy McCall 1 month ago ↶
113
let repo = open ( ) ? ;
114
let remote = remote_name ( remote) ;
135212de Andy McCall 1 month ago ↶
115
let sp = ui:: spinner( & format! ( " Pulling from {remote} …" ) ) ;
fce44ae9 Andy McCall 1 month ago ↶
116
let r = repo.pull ( & remote) ? ;
c6aa5bd9 Andy McCall 1 month ago ↶
117
if as_json {
118
sp.clear ( ) ;
119
let conflicted = repo.snapshot ( " oxy pull" ) ? .base_snapshot.is_conflicted ( ) ;
120
println! ( " {} " , json:: obj( [ ( " remote" , json:: s( & remote) ) , ( " heads" , json:: hashes( & r.heads) ) , ( " changed" , json:: b( r.changed) ) , ( " checked_out" , json:: b( r.checked_out) ) , ( " conflicted" , json:: b( conflicted) ) ] ) ) ;
121
return Ok ( 0 ) ;
122
}
fce44ae9 Andy McCall 1 month ago ↶
123
if ! r.changed {
94084087 Andy McCall 1 month ago ↶
124
sp.done ( & format! ( " {} {} " , ui:: ok( ui:: glyph( " ✔" , " *" ) ) , ui:: dim( " Already up to date." ) ) ) ;
fce44ae9 Andy McCall 1 month ago ↶
125
return Ok ( 0 ) ;
126
}
135212de Andy McCall 1 month ago ↶
127
sp.done ( & format! (
128
" {} {} now has {} {} " ,
94084087 Andy McCall 1 month ago ↶
129
ui:: done( " Pulled:" ) ,
130
ui:: bookmark( & repo.config.bookmark) ,
fce44ae9 Andy McCall 1 month ago ↶
131
plural ( r.heads.len ( ) , " head" ) ,
94084087 Andy McCall 1 month ago ↶
132
ui:: dim( if r.checked_out { " ; working copy updated" } else { " ; run oxy checkout to update the working copy" } )
135212de Andy McCall 1 month ago ↶
133
) ) ;
fce44ae9 Andy McCall 1 month ago ↶
134
let snap = repo.snapshot ( " oxy pull" ) ? ;
135
if snap.base_snapshot.is_conflicted ( ) {
94084087 Andy McCall 1 month ago ↶
136
println! ( " {} {} " , ui:: caution( ) , ui:: warn( " the result has conflicts; see oxy status" ) ) ;
fce44ae9 Andy McCall 1 month ago ↶
137
}
138
Ok ( 0 )
139
}
140
c6aa5bd9 Andy McCall 1 month ago ↶
141
pub fn push ( remote : Option< & str > , force : bool , bookmark : Option< & str > , as_json : bool ) -> Result< i32 > {
fce44ae9 Andy McCall 1 month ago ↶
142
let repo = open ( ) ? ;
143
let remote = remote_name ( remote) ;
135212de Andy McCall 1 month ago ↶
144
let sp = ui:: spinner( & format! ( " Pushing to {remote} …" ) ) ;
7b9809e6 Andy McCall 1 month ago ↶
145
let results = match bookmark {
146
Some ( b) => repo.push_bookmark ( & remote, b, force) ? ,
147
None => repo.push ( & remote, force) ? ,
148
} ;
135212de Andy McCall 1 month ago ↶
149
sp.clear ( ) ;
c6aa5bd9 Andy McCall 1 month ago ↶
150
if as_json {
151
println! ( " {} " , json:: arr( results.iter ( ) .map ( | r | json:: obj( [ ( " name" , json:: s( & r.name) ) , ( " ok" , json:: b( r.ok) ) , ( " reason" , json:: s( & r.reason) ) ] ) ) ) ) ;
152
return Ok ( if results.iter ( ) .all ( | r | r.ok ) { 0 } else { 1 } ) ;
153
}
fce44ae9 Andy McCall 1 month ago ↶
154
let mut code = 0 ;
135212de Andy McCall 1 month ago ↶
155
for r in results {
fce44ae9 Andy McCall 1 month ago ↶
156
if r.ok {
94084087 Andy McCall 1 month ago ↶
157
println! ( " {} {} {} {} " , ui:: done( " Pushed" ) , ui:: id( format! ( " {remote} /{} " , r.name) ) , ui:: sep( ) , ui:: dim( if r.reason.is_empty ( ) { " updated" } else { r.reason.as_str ( ) } ) ) ;
fce44ae9 Andy McCall 1 month ago ↶
158
} else {
94084087 Andy McCall 1 month ago ↶
159
println! ( " {} {} {} {} {} " , ui:: err( ui:: glyph( " ✖" , " x" ) ) , ui:: err( " Rejected" ) , ui:: id( format! ( " {remote} /{} " , r.name) ) , ui:: sep( ) , r.reason) ;
fce44ae9 Andy McCall 1 month ago ↶
160
code = 1 ;
161
}
162
}
163
Ok ( code)
164
}
165
2b5ee371 Andy McCall 1 month ago ↶
166
pub fn serve ( root : PathBuf, bind : & str , tokens : Vec< String> , tls : Option< ( PathBuf, PathBuf) > ) -> Result< i32 > {
fce44ae9 Andy McCall 1 month ago ↶
167
let listener = std:: net:: TcpListener:: bind( bind) .with_context ( | | format! ( " binding {bind} " ) ) ? ;
168
let root = root.canonicalize ( ) ? ;
2b5ee371 Andy McCall 1 month ago ↶
169
let tls = tls.map ( | ( cert , key ) | oxy_server:: TlsFiles { cert, key } ) ;
fce44ae9 Andy McCall 1 month ago ↶
170
println! (
2b5ee371 Andy McCall 1 month ago ↶
171
" Serving repositories under {} on {} ://{bind} /<repo>/oxy/v1/ ({} )" ,
fce44ae9 Andy McCall 1 month ago ↶
172
root.display ( ) ,
2b5ee371 Andy McCall 1 month ago ↶
173
if tls.is_some ( ) { " https" } else { " http" } ,
fce44ae9 Andy McCall 1 month ago ↶
174
if tokens.is_empty ( ) { " open: no push tokens configured" } else { " push requires a token" }
175
) ;
2b5ee371 Andy McCall 1 month ago ↶
176
if tls.is_none ( ) & & ! bind.starts_with ( " 127." ) & & ! bind.starts_with ( " localhost" ) & & ! bind.starts_with ( " [::1]" ) {
177
eprintln! ( " warning: serving plain HTTP on a non-loopback address; put a TLS terminator in front or pass --tls-cert/--tls-key" ) ;
178
}
179
oxy_server:: run_blocking( listener, oxy_server:: ServerConfig { root, tokens, tls } ) ? ;
fce44ae9 Andy McCall 1 month ago ↶
180
Ok ( 0 )
181
}
79ab8528 Andy McCall 1 month ago ↶
182
30ea9c1e Andy McCall 1 month ago ↶
183
pub fn git_export ( git_dir : & std:: path:: Path, branch : Option< & str > ) -> Result< i32 > {
79ab8528 Andy McCall 1 month ago ↶
184
let repo = open ( ) ? ;
135212de Andy McCall 1 month ago ↶
185
let sp = ui:: spinner( " Exporting to Git…" ) ;
30ea9c1e Andy McCall 1 month ago ↶
186
let r = match branch {
187
Some ( b) => repo.git_export_as ( git_dir, b) ? ,
188
None => repo.git_export ( git_dir) ? ,
189
} ;
135212de Andy McCall 1 month ago ↶
190
sp.clear ( ) ;
79ab8528 Andy McCall 1 month ago ↶
191
println! (
94084087 Andy McCall 1 month ago ↶
192
" {} {} to {} as branch {} {} " ,
193
ui:: done( " Exported" ) ,
e8b4e156 Andy McCall 1 month ago ↶
194
plural ( r.exported, " new state" ) ,
94084087 Andy McCall 1 month ago ↶
195
ui:: path( git_dir.display ( ) ) ,
196
ui:: bookmark( & r.branch) ,
197
ui:: dim( format! ( " (currently {} ; {} already exported)" , plural ( r.heads, " head" ) , r.skipped) )
79ab8528 Andy McCall 1 month ago ↶
198
) ;
199
Ok ( 0 )
200
}
c3069537 Andy McCall 1 month ago ↶
201
30ea9c1e Andy McCall 1 month ago ↶
202
pub fn git_fetch ( url : & str , branch : & str ) -> Result< i32 > {
203
let repo = open ( ) ? ;
204
let sp = ui:: spinner( & format! ( " Fetching {url} {branch} …" ) ) ;
205
let r = repo.git_fetch ( url, branch) ? ;
206
sp.clear ( ) ;
207
if r.commits = = 0 {
208
println! ( " {} {} " , ui:: done( " Fetched" ) , ui:: dim( format! ( " nothing new from {url} {branch} " ) ) ) ;
209
} else {
210
println! (
211
" {} {} ({} merges) from {} {} {} {} now has {} " ,
212
ui:: done( " Fetched" ) ,
213
plural ( r.commits, " new commit" ) ,
214
r.merges,
215
ui:: path( url) ,
216
ui:: bookmark( branch) ,
217
ui:: sep( ) ,
218
ui:: bookmark( & repo.config.bookmark) ,
219
plural ( r.heads, " head" )
220
) ;
221
if ! repo.snapshot ( " oxy git fetch" ) ? .changed {
222
println! ( " {} {} " , ui:: note( ) , ui:: dim( " working copy updated" ) ) ;
223
} else {
224
println! ( " {} {} " , ui:: note( ) , ui:: dim( " run oxy checkout to update the working copy" ) ) ;
225
}
226
}
4dee277c Andy McCall 1 month ago ↶
227
if r.submodules > 0 {
228
println! ( " {} {} " , ui:: note( ) , ui:: dim( format! ( " {} submodule {} imported as subrepos with Git pins" , r.submodules, if r.submodules = = 1 { " entry" } else { " entries" } ) ) ) ;
30ea9c1e Andy McCall 1 month ago ↶
229
}
230
Ok ( 0 )
231
}
232
233
pub fn git_push ( url : & str , branch : & str ) -> Result< i32 > {
234
let repo = open ( ) ? ;
235
let sp = ui:: spinner( & format! ( " Pushing to {url} {branch} …" ) ) ;
236
let r = repo.git_push ( url, branch) ? ;
237
sp.clear ( ) ;
238
println! (
239
" {} {} to {} {} {} " ,
240
ui:: done( " Pushed" ) ,
241
plural ( r.exported, " new commit" ) ,
242
ui:: path( url) ,
243
ui:: bookmark( & r.branch) ,
244
ui:: dim( format! ( " ({} already there)" , r.skipped) )
245
) ;
246
Ok ( 0 )
247
}
248
c3069537 Andy McCall 1 month ago ↶
249
pub fn git_import ( git_dir : & std:: path:: Path, dest : & std:: path:: Path, branch : & str ) -> Result< i32 > {
250
let repo = Repo:: init( dest) ? ;
251
let started = std:: time:: Instant:: now( ) ;
135212de Andy McCall 1 month ago ↶
252
let sp = ui:: spinner( & format! ( " Importing {} {branch} …" , git_dir.display ( ) ) ) ;
c3069537 Andy McCall 1 month ago ↶
253
let r = repo.import_git ( git_dir, branch) ? ;
135212de Andy McCall 1 month ago ↶
254
sp.clear ( ) ;
c3069537 Andy McCall 1 month ago ↶
255
println! (
94084087 Andy McCall 1 month ago ↶
256
" {} {} ({} merges) from {} {} into {} {} " ,
257
ui:: done( " Imported" ) ,
c3069537 Andy McCall 1 month ago ↶
258
plural ( r.commits, " commit" ) ,
259
r.merges,
94084087 Andy McCall 1 month ago ↶
260
ui:: path( git_dir.display ( ) ) ,
261
ui:: bookmark( branch) ,
262
ui:: path( repo.root ( ) .display ( ) ) ,
263
ui:: dim( format! ( " in {:.1?} ; {} now has {} " , started.elapsed ( ) , repo.config.bookmark, plural ( r.heads, " head" ) ) )
c3069537 Andy McCall 1 month ago ↶
264
) ;
4dee277c Andy McCall 1 month ago ↶
265
if r.submodules > 0 {
266
println! ( " {} {} " , ui:: note( ) , ui:: dim( format! ( " {} submodule {} imported as subrepos with Git pins" , r.submodules, if r.submodules = = 1 { " entry" } else { " entries" } ) ) ) ;
267
}
268
Ok ( 0 )
269
}
270
271
pub fn submodule_add ( url : & str , path : & str , bookmark : Option< & str > ) -> Result< i32 > {
272
let repo = open ( ) ? ;
273
let sp = ui:: spinner( & format! ( " Cloning {url} into {path} …" ) ) ;
274
let pin = repo.submodule_add ( url, path, bookmark) ? ;
275
sp.done ( & format! ( " {} subrepo {} {} {} " , ui:: done( " Added" ) , ui:: path( path) , ui:: dim( ui:: glyph( " →" , " ->" ) ) , ui:: dim( pin.summary ( ) ) ) ) ;
276
println! ( " {} {} " , ui:: note( ) , ui:: dim( " recorded in .oxymodules; commit to pin it" ) ) ;
277
Ok ( 0 )
278
}
279
280
pub fn submodule_update ( init : bool , paths : & [String]) -> Result< i32 > {
281
let repo = open ( ) ? ;
282
let sp = ui:: spinner( " Updating subrepos…" ) ;
283
let results = repo.submodule_update ( init, paths) ? ;
284
sp.clear ( ) ;
285
if results.is_empty ( ) {
286
println! ( " {} " , ui:: dim( " No subrepos." ) ) ;
287
}
288
let mut code = 0 ;
289
for ( path, r) in results {
290
use oxy_core:: repo:: SubrepoSync:: * ;
291
let line = match r {
292
Updated => ui:: done( " Updated" ) ,
293
UpToDate => ui:: ok( format! ( " {} up to date" , ui:: glyph( " ✔" , " *" ) ) ) ,
294
Missing => {
295
code = 1 ;
296
ui:: warn( format! ( " {} missing (pass --init to clone)" , ui:: glyph( " ⚠" , " !" ) ) )
297
}
298
Dirty => {
299
code = 1 ;
300
ui:: warn( format! ( " {} has uncommitted changes; left as is" , ui:: glyph( " ⚠" , " !" ) ) )
301
}
302
Failed( e) => {
303
code = 1 ;
304
ui:: err( format! ( " {} {e} " , ui:: glyph( " ✖" , " x" ) ) )
305
}
306
} ;
307
println! ( " {line} {} " , ui:: path( path) ) ;
308
}
309
Ok ( code)
310
}
311
c6aa5bd9 Andy McCall 1 month ago ↶
312
fn pin_json ( p : & oxy_core:: subrepo:: Pin) -> String {
313
match p {
314
oxy_core:: subrepo:: Pin:: Oxy { repo, heads, bookmark } => json:: obj( [ ( " kind" , json:: s( " oxy" ) ) , ( " repo" , json:: s( & repo.iter ( ) .map ( | b | format! ( " {b:02x} " ) ) .collect:: < String> ( ) ) ) , ( " heads" , json:: hashes( heads) ) , ( " bookmark" , json:: s( bookmark) ) ] ) ,
315
oxy_core:: subrepo:: Pin:: Git { sha, branch } => json:: obj( [ ( " kind" , json:: s( " git" ) ) , ( " sha" , json:: s( sha) ) , ( " branch" , json:: s( branch) ) ] ) ,
316
}
317
}
318
319
pub fn submodule_status ( as_json : bool ) -> Result< i32 > {
4dee277c Andy McCall 1 month ago ↶
320
let repo = open ( ) ? ;
321
let subs = repo.subrepos ( ) ? ;
c6aa5bd9 Andy McCall 1 month ago ↶
322
if as_json {
323
println! (
324
" {} " ,
325
json:: arr( subs.iter ( ) .map ( | s | {
326
json:: obj( [
327
( " path" , json:: s( & s.path) ) ,
328
( " pin" , pin_json ( & s.pin) ) ,
329
( " actual" , json:: opt( s.actual.as_ref ( ) , pin_json) ) ,
330
( " at_pin" , json:: b( s.actual.as_ref ( ) = = Some ( & s.pin) ) ) ,
331
( " dirty" , json:: b( s.dirty) ) ,
332
( " url" , json:: opt( s.url.as_deref ( ) , json:: s) ) ,
333
] )
334
} ) )
335
) ;
336
return Ok ( 0 ) ;
337
}
4dee277c Andy McCall 1 month ago ↶
338
if subs.is_empty ( ) {
339
println! ( " {} " , ui:: dim( " No subrepos." ) ) ;
94084087 Andy McCall 1 month ago ↶
340
}
4dee277c Andy McCall 1 month ago ↶
341
for s in subs {
342
let state = match ( & s.actual, s.dirty) {
343
( None , _ ) => ui:: warn( format! ( " {} missing" , ui:: glyph( " ⚠" , " !" ) ) ) ,
344
( Some ( a) , dirty) if * a = = s.pin => {
345
if dirty { ui:: warn( format! ( " {} at pin, uncommitted changes" , ui:: glyph( " ✎" , " ~" ) ) ) } else { ui:: ok( format! ( " {} at pin" , ui:: glyph( " ✔" , " *" ) ) ) }
346
}
347
( Some ( a) , _ ) => ui:: warn( format! ( " {} at {} " , ui:: glyph( " ↕" , " <>" ) , a.summary ( ) ) ) ,
348
} ;
349
println! ( " {} {} {} {} {} {state} " , ui:: ok( ui:: glyph( " ⧉" , " #" ) ) , ui:: path( & s.path) , ui:: sep( ) , ui:: dim( s.pin.summary ( ) ) , ui:: sep( ) ) ;
350
if let Some ( u) = s.url {
351
println! ( " {} {} " , ui:: dim( ui:: glyph( " ↳" , " ->" ) ) , ui:: dim( u) ) ;
352
}
353
}
354
Ok ( 0 )
355
}
356
357
pub fn submodule_remove ( path : & str ) -> Result< i32 > {
358
let repo = open ( ) ? ;
359
repo.submodule_remove ( path) ? ;
360
println! ( " {} subrepo {} {} " , ui:: done( " Removed" ) , ui:: path( path) , ui:: dim( " (directory left in place; commit to record the removal)" ) ) ;
c3069537 Andy McCall 1 month ago ↶
361
Ok ( 0 )
362
}
2863456a Andy McCall 1 month ago ↶
363
364
pub fn deepen ( remote : & str , depth : u32 ) -> Result< i32 > {
365
let repo = open ( ) ? ;
366
if ! repo.is_shallow ( ) {
367
println! ( " {} " , ui:: dim( " This repository is not shallow; nothing to deepen." ) ) ;
368
return Ok ( 0 ) ;
369
}
370
let sp = ui:: spinner( & format! ( " Fetching {depth} more levels from {remote} …" ) ) ;
371
let n = repo.deepen ( remote, depth) ? ;
372
sp.done ( & format! ( " {} {} ; {} " , ui:: ok( " Deepened by" ) , plural ( n, " change" ) , if repo.is_shallow ( ) { " still shallow" .to_string ( ) } else { ui:: ok( " history is now complete" ) } ) ) ;
373
Ok ( 0 )
374
}