11pub mod auth;
22pub mod cli;
33pub mod juniper_hyper;
4+ pub mod trace;
45
56#[ macro_use]
67extern crate lazy_static;
@@ -108,19 +109,44 @@ pub struct RepoUpdate {
108109 pub context_propagator : std:: collections:: HashMap < String , String > ,
109110}
110111
112+ #[ derive( serde:: Serialize , serde:: Deserialize , Debug ) ]
113+ #[ serde( default ) ]
114+ pub struct PushOptions {
115+ pub merge : bool ,
116+ pub create : bool ,
117+ pub force : bool ,
118+ pub base : Option < String > ,
119+ pub author : Option < String > ,
120+ }
121+
122+ impl Default for PushOptions {
123+ fn default ( ) -> Self {
124+ PushOptions {
125+ merge : false ,
126+ create : false ,
127+ force : false ,
128+ base : None ,
129+ author : None ,
130+ }
131+ }
132+ }
133+
111134pub fn process_repo_update ( repo_update : RepoUpdate ) -> josh:: JoshResult < String > {
112- let p = std:: path:: PathBuf :: from ( & repo_update. git_dir )
135+ let push_options_path = std:: path:: PathBuf :: from ( & repo_update. git_dir )
113136 . join ( "refs/namespaces" )
114137 . join ( & repo_update. git_ns )
115138 . join ( "push_options" ) ;
116139
117- let push_options_string = std:: fs:: read_to_string ( p ) ?;
118- let push_options: std :: collections :: HashMap < String , String > =
119- serde_json :: from_str ( & push_options_string ) ?;
140+ let push_options = std:: fs:: read_to_string ( push_options_path ) ?;
141+ let push_options: PushOptions = serde_json :: from_str ( & push_options )
142+ . map_err ( |e| josh_error ( & format ! ( "Failed to parse push options: {}" , e ) ) ) ?;
120143
121- for ( refname, ( old, new) ) in repo_update. refs . iter ( ) {
122- tracing:: debug!( "REPO_UPDATE env ok" ) ;
144+ tracing:: debug!(
145+ push_options = ?push_options,
146+ "process_repo_update"
147+ ) ;
123148
149+ for ( refname, ( old, new) ) in repo_update. refs . iter ( ) {
124150 let transaction = josh:: cache:: Transaction :: open (
125151 std:: path:: Path :: new ( & repo_update. git_dir ) ,
126152 Some ( & format ! ( "refs/josh/upstream/{}/" , repo_update. base_ns) ) ,
@@ -141,28 +167,34 @@ pub fn process_repo_update(repo_update: RepoUpdate) -> josh::JoshResult<String>
141167 ) ?;
142168
143169 let old = git2:: Oid :: from_str ( old) ?;
144-
145170 let ( baseref, push_to, options, push_mode) = baseref_and_options ( refname) ?;
146- let josh_merge = push_options. contains_key ( "merge" ) ;
147-
148- tracing:: debug!( "push options: {:?}" , push_options) ;
149- tracing:: debug!( "josh-merge: {:?}" , josh_merge) ;
150171
151172 let old = if old == git2:: Oid :: zero ( ) {
152173 let rev = format ! ( "refs/namespaces/{}/{}" , repo_update. git_ns, & baseref) ;
153- let oid = if let Ok ( x ) = transaction. repo ( ) . revparse_single ( & rev) {
154- x . id ( )
174+ let oid = if let Ok ( resolved ) = transaction. repo ( ) . revparse_single ( & rev) {
175+ resolved . id ( )
155176 } else {
156177 old
157178 } ;
158- tracing:: debug!( "push: old oid: {:?}, rev: {:?}" , oid, rev) ;
179+
180+ tracing:: debug!(
181+ old_oid = ?oid,
182+ rev = %rev,
183+ "resolve_old"
184+ ) ;
185+
159186 oid
160187 } else {
161- tracing:: debug!( "push: old oid: {:?}, refname: {:?}" , old, refname) ;
188+ tracing:: debug!(
189+ old_oid = ?old,
190+ refname = %refname,
191+ "resolve_old"
192+ ) ;
193+
162194 old
163195 } ;
164196
165- let original_target_ref = if let Some ( base) = push_options. get ( " base" ) {
197+ let original_target_ref = if let Some ( base) = & push_options. base {
166198 // Allow user to use just the branchname as the base:
167199 let full_path_base_refname =
168200 transaction_mirror. refname ( & format ! ( "refs/heads/{}" , base) ) ;
@@ -173,7 +205,7 @@ pub fn process_repo_update(repo_update: RepoUpdate) -> josh::JoshResult<String>
173205 {
174206 full_path_base_refname
175207 } else {
176- transaction_mirror. refname ( base)
208+ transaction_mirror. refname ( & base)
177209 }
178210 } else {
179211 transaction_mirror. refname ( & baseref)
@@ -184,12 +216,18 @@ pub fn process_repo_update(repo_update: RepoUpdate) -> josh::JoshResult<String>
184216 . refname_to_id ( & original_target_ref)
185217 {
186218 tracing:: debug!(
187- "push: original_target oid: {:?}, original_target_ref: {:?}" ,
188- oid ,
189- original_target_ref
219+ original_target_oid = ?oid ,
220+ original_target_ref = %original_target_ref ,
221+ "resolve_original_target"
190222 ) ;
223+
191224 oid
192225 } else {
226+ tracing:: debug!(
227+ original_target_ref = %original_target_ref,
228+ "resolve_original_target"
229+ ) ;
230+
193231 return Err ( josh:: josh_error ( & unindent:: unindent ( & format ! (
194232 r###"
195233 Reference {:?} does not exist on remote.
@@ -200,14 +238,14 @@ pub fn process_repo_update(repo_update: RepoUpdate) -> josh::JoshResult<String>
200238 ) ) ) ) ;
201239 } ;
202240
203- let reparent_orphans = if push_options. contains_key ( " create" ) {
241+ let reparent_orphans = if push_options. create {
204242 Some ( original_target)
205243 } else {
206244 None
207245 } ;
208246
209- let author = if let Some ( p ) = push_options. get ( " author" ) {
210- p . to_string ( )
247+ let author = if let Some ( author ) = & push_options. author {
248+ author . to_string ( )
211249 } else {
212250 "" . to_string ( )
213251 } ;
@@ -219,26 +257,30 @@ pub fn process_repo_update(repo_update: RepoUpdate) -> josh::JoshResult<String>
219257 None
220258 } ;
221259
222- let filterobj = josh:: filter:: parse ( & repo_update. filter_spec ) ?;
260+ let filter = josh:: filter:: parse ( & repo_update. filter_spec ) ?;
223261 let new_oid = git2:: Oid :: from_str ( new) ?;
224262 let backward_new_oid = {
225- tracing:: debug!( "=== MORE" ) ;
226-
227- tracing:: debug!( "=== processed_old {:?}" , old) ;
228-
229- josh:: history:: unapply_filter (
263+ let unapply_result = josh:: history:: unapply_filter (
230264 & transaction,
231- filterobj ,
265+ filter ,
232266 original_target,
233267 old,
234268 new_oid,
235- josh_merge ,
269+ push_options . merge ,
236270 reparent_orphans,
237271 & mut changes,
238- ) ?
272+ ) ?;
273+
274+ tracing:: debug!(
275+ processed_old = ?old,
276+ unapply_result = ?unapply_result,
277+ "unapply_filter"
278+ ) ;
279+
280+ unapply_result
239281 } ;
240282
241- let oid_to_push = if josh_merge {
283+ let oid_to_push = if push_options . merge {
242284 let backward_commit = transaction. repo ( ) . find_commit ( backward_new_oid) ?;
243285 if let Ok ( base_commit_id) = transaction_mirror
244286 . repo ( )
@@ -301,6 +343,8 @@ pub fn process_repo_update(repo_update: RepoUpdate) -> josh::JoshResult<String>
301343 let mut resp = vec ! [ ] ;
302344
303345 for ( reference, oid, display_name) in to_push {
346+ let force_push = push_mode != PushMode :: Normal || push_options. force ;
347+
304348 let ( text, status) = push_head_url (
305349 transaction. repo ( ) ,
306350 & format ! ( "{}/objects" , repo_update. mirror_git_dir) ,
@@ -310,17 +354,17 @@ pub fn process_repo_update(repo_update: RepoUpdate) -> josh::JoshResult<String>
310354 & repo_update. remote_auth ,
311355 & repo_update. git_ns ,
312356 & display_name,
313- push_mode != PushMode :: Normal ,
357+ force_push ,
314358 ) ?;
359+
315360 if status != 0 {
316361 return Err ( josh:: josh_error ( & text) ) ;
317362 }
318363
319364 resp. push ( text. to_string ( ) ) ;
320-
321365 let mut warnings = josh:: filter:: compute_warnings (
322366 & transaction,
323- filterobj ,
367+ filter ,
324368 transaction. repo ( ) . find_commit ( oid) ?. tree ( ) ?,
325369 ) ;
326370
@@ -331,7 +375,7 @@ pub fn process_repo_update(repo_update: RepoUpdate) -> josh::JoshResult<String>
331375 }
332376
333377 let reapply = josh:: filter:: apply_to_commit (
334- filterobj ,
378+ filter ,
335379 & transaction. repo ( ) . find_commit ( oid_to_push) ?,
336380 & transaction,
337381 ) ?;
@@ -342,16 +386,22 @@ pub fn process_repo_update(repo_update: RepoUpdate) -> josh::JoshResult<String>
342386 & format ! (
343387 "refs/josh/rewrites/{}/{:?}/r_{}" ,
344388 repo_update. base_ns,
345- filterobj . id( ) ,
389+ filter . id( ) ,
346390 reapply
347391 ) ,
348392 reapply,
349393 true ,
350394 "reapply" ,
351395 ) ?;
352396 }
397+
398+ tracing:: debug!(
399+ new_oid = ?new_oid,
400+ reapply = ?reapply,
401+ "rewrite"
402+ ) ;
403+
353404 let text = format ! ( "REWRITE({} -> {})" , new_oid, reapply) ;
354- tracing:: debug!( "{}" , text) ;
355405 resp. push ( text) ;
356406 }
357407
@@ -437,27 +487,29 @@ pub fn push_head_url(
437487 display_name : & str ,
438488 force : bool ,
439489) -> josh:: JoshResult < ( String , i32 ) > {
440- let rn = format ! ( "refs/{}" , & namespace) ;
441-
442- let spec = format ! ( "{}:{}" , & rn, & refname) ;
490+ let push_temp_ref = format ! ( "refs/{}" , & namespace) ;
491+ let push_refspec = format ! ( "{}:{}" , & push_temp_ref, & refname) ;
443492
444493 let mut cmd = vec ! [ "git" , "push" ] ;
445494 if force {
446495 cmd. push ( "--force" )
447496 }
448497 cmd. push ( url) ;
449- cmd. push ( & spec ) ;
498+ cmd. push ( & push_refspec ) ;
450499
451- let mut fakehead = repo. reference ( & rn , oid, true , "push_head_url" ) ?;
500+ let mut fake_head = repo. reference ( & push_temp_ref , oid, true , "push_head_url" ) ?;
452501 let ( stdout, stderr, status) =
453502 run_git_with_auth ( repo. path ( ) , & cmd, remote_auth, Some ( alternate. to_owned ( ) ) ) ?;
454- fakehead. delete ( ) ?;
455-
456- tracing:: debug!( "{}" , & stderr) ;
457- tracing:: debug!( "{}" , & stdout) ;
503+ fake_head. delete ( ) ?;
458504
459- let stderr = stderr. replace ( & rn, display_name) ;
505+ tracing:: debug!(
506+ stdout = %stdout,
507+ stderr = %stderr,
508+ status = %status,
509+ "push_head_url: run_git"
510+ ) ;
460511
512+ let stderr = stderr. replace ( & push_temp_ref, display_name) ;
461513 Ok ( ( stderr, status) )
462514}
463515
0 commit comments