@@ -4,6 +4,7 @@ use anyhow::{Context, Result};
44
55use bstr:: ByteSlice as _;
66use hm_common:: app_runtime:: AppRuntime ;
7+ use hm_common:: git:: { GitBranch , GitRemote , GitRepo } ;
78use hm_dsl_engine:: { DslEngine , detect} ;
89use human_units:: FormatSize as _;
910
@@ -129,14 +130,18 @@ pub async fn handle(args: RunArgs, ctx: RunContext) -> Result<i32> {
129130 ) ;
130131 }
131132
132- // 7. Assemble the run request. Read branch, commit, and repo name from git
133- // in one borrow of `repo_root` (best-effort; an explicit `--branch` wins,
134- // and missing values fall back to `HEAD` / the zero SHA). The block yields
135- // owned strings so `repo_root` is free to move into the request below.
136- let git = AppRuntime :: git ( ) ;
137- let ( branch, commit, repo_name) = {
133+ // 7. Assemble the run request. Open the worktree's repo and its `origin`
134+ // remote once, and read every git-derived field from that single pair of
135+ // handles — all best-effort. An explicit `--branch` wins; a missing branch
136+ // or commit falls back to `HEAD` / the zero SHA. The block yields owned
137+ // strings so `repo_root` can move into the request, and the cloud paths
138+ // below reuse `remote_url` / `default_branch` instead of re-shelling to git.
139+ let ( branch, commit, repo_name, remote_url, default_branch) = {
140+ let git = AppRuntime :: git ( ) ;
138141 let repo = git. repo ( & repo_root) . ok ( ) ;
139- let head = repo. as_ref ( ) . and_then ( hm_common:: git:: GitRepo :: current_branch) ;
142+ let head = repo. as_ref ( ) . and_then ( GitRepo :: current_branch) ;
143+ let remote = repo. as_ref ( ) . and_then ( |r| r. remote ( "origin" ) ) ;
144+
140145 let branch = args
141146 . branch
142147 . clone ( )
@@ -145,15 +150,25 @@ pub async fn handle(args: RunArgs, ctx: RunContext) -> Result<i32> {
145150 . unwrap_or_else ( || "HEAD" . to_string ( ) ) ;
146151 let commit = head
147152 . as_ref ( )
148- . and_then ( hm_common :: git :: GitBranch :: head_commit)
153+ . and_then ( GitBranch :: head_commit)
149154 . map ( |c| c. to_str_lossy ( ) . into_owned ( ) )
150155 . filter ( |s| !s. is_empty ( ) )
151156 . unwrap_or_else ( || "0" . repeat ( 40 ) ) ;
152- let repo_name = repo
157+ let repo_name = remote
153158 . as_ref ( )
154- . and_then ( |r| r . remote ( "origin" ) ? . gh_repo_name ( ) )
159+ . and_then ( GitRemote :: gh_repo_name)
155160 . map ( |n| n. to_str_lossy ( ) . into_owned ( ) ) ;
156- ( branch, commit, repo_name)
161+ let remote_url = remote
162+ . as_ref ( )
163+ . map ( |r| r. url ( ) . to_str_lossy ( ) . into_owned ( ) )
164+ . filter ( |u| !u. is_empty ( ) ) ;
165+ // `origin/HEAD`; `None` when unset (fresh clones without `set-head`).
166+ let default_branch = remote
167+ . as_ref ( )
168+ . and_then ( GitRemote :: default_branch)
169+ . map ( |b| b. name ( ) . to_str_lossy ( ) . into_owned ( ) ) ;
170+
171+ ( branch, commit, repo_name, remote_url, default_branch)
157172 } ;
158173 let mut req = hm_exec:: RunRequest {
159174 plan,
@@ -183,20 +198,8 @@ pub async fn handle(args: RunArgs, ctx: RunContext) -> Result<i32> {
183198 if let Some ( slug) = ctx. config . cloud . pipeline . clone ( ) {
184199 req. cloud_pipeline_slug = Some ( slug) ;
185200 } else if req. source . repo_name . is_none ( ) {
186- // Default branch from `origin/HEAD`; falls back to the run's branch
187- // when unset (fresh clones without `git remote set-head`).
188- let default_branch = git
189- . repo ( & req. repo_root )
190- . ok ( )
191- . and_then ( |r| {
192- Some (
193- r. remote ( "origin" ) ?
194- . default_branch ( ) ?
195- . name ( )
196- . to_str_lossy ( )
197- . into_owned ( ) ,
198- )
199- } )
201+ let default_branch = default_branch
202+ . clone ( )
200203 . unwrap_or_else ( || req. source . branch . clone ( ) ) ;
201204 let slug = register_remoteless_pipeline (
202205 client,
@@ -210,32 +213,16 @@ pub async fn handle(args: RunArgs, ctx: RunContext) -> Result<i32> {
210213 }
211214 }
212215
213- // Cloud-only auto-create context. Borrow `req` here (before it's moved into
214- // `start`): the repository URL and default branch come from the worktree's
215- // git remote; the pipeline name is the in-repo source slug.
216+ // Cloud-only auto-create context, from the git fields read in step 7: the
217+ // `origin` remote URL is the pipeline's `repository`, `default_branch` falls
218+ // back to the run's branch, and the pipeline name is the in-repo source slug.
216219 let autocreate = autocreate_client. map ( |( client, org) | AutoCreate {
217220 client,
218221 org,
219222 repo_name : req. source . repo_name . clone ( ) ,
220- // The pipeline's `repository`: the worktree's `origin` remote URL.
221- repository : git. repo ( & req. repo_root ) . ok ( ) . and_then ( |r| {
222- let url = r. remote ( "origin" ) ?. url ( ) . to_str_lossy ( ) . into_owned ( ) ;
223- ( !url. is_empty ( ) ) . then_some ( url)
224- } ) ,
223+ repository : remote_url,
225224 name : req. pipeline_slug . clone ( ) ,
226- default_branch : git
227- . repo ( & req. repo_root )
228- . ok ( )
229- . and_then ( |r| {
230- Some (
231- r. remote ( "origin" ) ?
232- . default_branch ( ) ?
233- . name ( )
234- . to_str_lossy ( )
235- . into_owned ( ) ,
236- )
237- } )
238- . unwrap_or_else ( || req. source . branch . clone ( ) ) ,
225+ default_branch : default_branch. unwrap_or_else ( || req. source . branch . clone ( ) ) ,
239226 } ) ;
240227
241228 // 8. Start, drive events, own Ctrl-C, await the outcome.
0 commit comments