(** Transform dune-generated opam files for opam-repo overlay. *) (** Remove the "generated by dune" comment from the first line *) let strip_dune_comment content = let lines = String.split_on_char '\n' content in match lines with | first :: rest when String.starts_with ~prefix:"# This file is generated by dune" (String.trim first) -> String.concat "\n" rest | _ -> content (** Remove existing dev-repo line if present *) let remove_dev_repo_line content = let lines = String.split_on_char '\n' content in let lines = List.filter (fun line -> let trimmed = String.trim line in not (String.starts_with ~prefix:"dev-repo:" trimmed)) lines in String.concat "\n" lines (** Remove existing url { ... } section if present *) let remove_url_section content = let lines = String.split_on_char '\n' content in let rec process lines in_url_block acc = match lines with | [] -> List.rev acc | line :: rest -> let trimmed = String.trim line in if in_url_block then (* Inside url { ... }, skip until we see } *) if String.starts_with ~prefix:"}" trimmed then process rest false acc else process rest true acc else if trimmed = "url {" || String.starts_with ~prefix:"url {" trimmed then (* Start of url block *) if String.ends_with ~suffix:"}" trimmed then (* Single-line url block, skip it *) process rest false acc else process rest true acc else process rest false (line :: acc) in String.concat "\n" (process lines false []) (** Trim trailing blank lines and ensure single trailing newline *) let normalize_ending content = let lines = String.split_on_char '\n' content in let rec trim_trailing = function | [] -> [] | [ "" ] -> [] | "" :: rest -> ( match trim_trailing rest with [] -> [] | trimmed -> "" :: trimmed) | x :: rest -> x :: trim_trailing rest in let lines = List.rev (trim_trailing (List.rev lines)) in String.concat "\n" lines let transform ~content ~dev_repo ~url_src = (* Step 1: Strip the dune comment *) let content = strip_dune_comment content in (* Step 2: Remove any existing dev-repo and url sections *) let content = remove_dev_repo_line content in let content = remove_url_section content in (* Step 3: Normalize ending *) let content = normalize_ending content in (* Step 4: Append dev-repo and url section *) let dev_repo_line = Printf.sprintf {|dev-repo: "%s"|} dev_repo in let url_section = Printf.sprintf "url {\n src: \"%s\"\n}" url_src in content ^ "\n" ^ dev_repo_line ^ "\n" ^ url_section ^ "\n"