Monorepo management for opam overlays
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

git_cli: handle cloning empty remote repos

When the remote repo has no branches (newly created empty repo), git
clone with --branch fails. This change detects that error and instead
initializes a local repo with the branch, adds the remote, and
configures receive.denyCurrentBranch=updateInstead so subtree pushes
work.

+27 -5
+24 -3
lib/git_cli.ml
··· 150 150 let cwd = Eio.Path.(fs / Fpath.to_string parent) in 151 151 let target_name = Fpath.basename target in 152 152 let url_str = Uri.to_string url in 153 - run_git_ok_with_retry ~proc ~cwd 154 - [ "clone"; "--branch"; branch; url_str; target_name ] 155 - |> Result.map ignore 153 + let result = 154 + run_git_ok_with_retry ~proc ~cwd 155 + [ "clone"; "--branch"; branch; url_str; target_name ] 156 + in 157 + match result with 158 + | Ok _ -> Ok () 159 + | Error (Command_failed (_, r)) 160 + when string_contains ~needle:"Remote branch" r.stderr 161 + && string_contains ~needle:"not found" r.stderr -> 162 + (* Empty remote repo - init locally and add remote *) 163 + let target_dir = Eio.Path.(cwd / target_name) in 164 + (try Eio.Path.mkdir ~perm:0o755 target_dir with Eio.Io _ -> ()); 165 + let ( let* ) = Result.bind in 166 + let* _ = run_git_ok ~proc ~cwd:target_dir [ "init"; "-b"; branch ] in 167 + (* Allow pushes to this non-bare repo (needed for subtree push) *) 168 + let* _ = 169 + run_git_ok ~proc ~cwd:target_dir 170 + [ "config"; "receive.denyCurrentBranch"; "updateInstead" ] 171 + in 172 + let* _ = 173 + run_git_ok ~proc ~cwd:target_dir [ "remote"; "add"; "origin"; url_str ] 174 + in 175 + Ok () 176 + | Error e -> Error e 156 177 157 178 let fetch ~proc ~fs ?(remote = "origin") path = 158 179 let cwd = path_to_eio ~fs path in
+3 -2
lib/git_cli.mli
··· 40 40 branch:string -> 41 41 Fpath.t -> 42 42 (unit, error) result 43 - (** [clone ~proc ~fs ~url ~branch target] clones a repository. 43 + (** [clone ~proc ~fs ~url ~branch target] clones a repository. If the remote is 44 + empty (no branches), initializes a local repository and adds the remote. 44 45 45 46 @param proc Eio process manager 46 47 @param fs Eio filesystem 47 48 @param url Git remote URL 48 - @param branch Branch to checkout 49 + @param branch Branch to checkout (or create for empty remotes) 49 50 @param target Destination directory *) 50 51 51 52 val fetch :