@@ -13,6 +13,8 @@ use snafu::{OptionExt, ResultExt as _, Snafu};
1313use tracing_indicatif:: IndicatifLayer ;
1414use tracing_subscriber:: { layer:: SubscriberExt as _, util:: SubscriberInitExt as _} ;
1515
16+ use crate :: utils:: setup_git_credentials;
17+
1618#[ derive( clap:: Parser ) ]
1719struct ProductVersion {
1820 /// The product name slug (such as druid)
@@ -164,6 +166,10 @@ enum Cmd {
164166 /// Check out the base commit, without applying patches
165167 #[ clap( long) ]
166168 base_only : bool ,
169+
170+ /// Use SSH for git operations
171+ #[ clap( long) ]
172+ ssh : bool ,
167173 } ,
168174
169175 /// Export the patches from the source tree at docker-images/<PRODUCT>/patchable-work/worktree/<VERSION>
@@ -185,8 +191,13 @@ enum Cmd {
185191 #[ clap( long) ]
186192 base : String ,
187193
194+ /// Mirror the product version to the default mirror repository
188195 #[ clap( long) ]
189196 mirror : bool ,
197+
198+ /// Use SSH for git operations
199+ #[ clap( long) ]
200+ ssh : bool ,
190201 } ,
191202
192203 /// Shows the patch directory for a given product version
@@ -235,6 +246,9 @@ pub enum Error {
235246 path : PathBuf ,
236247 } ,
237248
249+ #[ snafu( display( "failed to rewrite URL for SSH: {source}" ) ) ]
250+ UrlRewrite { source : utils:: UrlRewriteError } ,
251+
238252 #[ snafu( display(
239253 "mirroring requested, but default-mirror is not configured in product configuration"
240254 ) ) ]
@@ -326,7 +340,7 @@ fn main() -> Result<()> {
326340 }
327341 } ;
328342 match opts. cmd {
329- Cmd :: Checkout { pv, base_only } => {
343+ Cmd :: Checkout { pv, base_only, ssh } => {
330344 let ctx = ProductVersionContext {
331345 pv,
332346 images_repo_root,
@@ -337,13 +351,20 @@ fn main() -> Result<()> {
337351 let product_repo = repo:: ensure_bare_repo ( & product_repo_root)
338352 . context ( OpenProductRepoForCheckoutSnafu ) ?;
339353
354+ let mut upstream = version_config. mirror . unwrap_or_else ( || {
355+ tracing:: warn!( "this product version is not mirrored, re-init it with --mirror before merging it" ) ;
356+ product_config. upstream
357+ } ) ;
358+
359+ if ssh {
360+ upstream =
361+ utils:: rewrite_git_https_url_to_ssh ( & upstream) . context ( UrlRewriteSnafu ) ?;
362+ }
363+
340364 let base_commit = repo:: resolve_and_fetch_commitish (
341365 & product_repo,
342366 & version_config. base . to_string ( ) ,
343- version_config. mirror . as_deref ( ) . unwrap_or_else ( || {
344- tracing:: warn!( "this product version is not mirrored, re-init it with --mirror before merging it" ) ;
345- & product_config. upstream
346- } ) ,
367+ & upstream,
347368 )
348369 . context ( FetchBaseCommitSnafu ) ?;
349370 let base_branch = ctx. base_branch ( ) ;
@@ -453,7 +474,12 @@ fn main() -> Result<()> {
453474 ) ;
454475 }
455476
456- Cmd :: Init { pv, base, mirror } => {
477+ Cmd :: Init {
478+ pv,
479+ base,
480+ mirror,
481+ ssh,
482+ } => {
457483 let ctx = ProductVersionContext {
458484 pv,
459485 images_repo_root,
@@ -468,7 +494,11 @@ fn main() -> Result<()> {
468494 . context ( OpenProductRepoForCheckoutSnafu ) ?;
469495
470496 let config = ctx. load_product_config ( ) ?;
471- let upstream = config. upstream ;
497+ let upstream = if ssh {
498+ utils:: rewrite_git_https_url_to_ssh ( & config. upstream ) . context ( UrlRewriteSnafu ) ?
499+ } else {
500+ config. upstream
501+ } ;
472502
473503 // --base can be a reference, but patchable.toml should always have a resolved commit id,
474504 // so that it cannot be changed under our feet (without us knowing so, anyway...).
@@ -478,10 +508,13 @@ fn main() -> Result<()> {
478508 tracing:: info!( ?base, base. commit = ?base_commit, "resolved base commit" ) ;
479509
480510 let mirror_url = if mirror {
481- let mirror_url = config
511+ let mut mirror_url = config
482512 . default_mirror
483513 . context ( InitMirrorNotConfiguredSnafu ) ?;
484-
514+ if ssh {
515+ mirror_url =
516+ utils:: rewrite_git_https_url_to_ssh ( & mirror_url) . context ( UrlRewriteSnafu ) ?
517+ } ;
485518 // Add mirror remote
486519 let mut mirror_remote =
487520 product_repo
@@ -492,15 +525,7 @@ fn main() -> Result<()> {
492525
493526 // Push the base commit to the mirror
494527 tracing:: info!( commit = %base_commit, base = base, url = mirror_url, "pushing commit to mirror" ) ;
495- let mut callbacks = git2:: RemoteCallbacks :: new ( ) ;
496- callbacks. credentials ( |url, username_from_url, _allowed_types| {
497- git2:: Cred :: credential_helper (
498- & git2:: Config :: open_default ( )
499- . expect ( "failed to open default Git configuration" ) , // Use default git config,
500- url,
501- username_from_url,
502- )
503- } ) ;
528+ let mut callbacks = setup_git_credentials ( ) ;
504529
505530 // Add progress tracking for push operation
506531 let ( span_push, mut quant_push) =
0 commit comments