Monorepo management for opam overlays
0
fork

Configure Feed

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

merge

+135 -76
+2 -2
bin/main.ml
··· 43 43 List.fold_left 44 44 (fun cfg (name, override) -> 45 45 let open Monopam.Verse_config in 46 - Monopam.Config.with_package_override cfg ~name 47 - ?branch:override.branch ?dev_repo:override.dev_repo ()) 46 + Monopam.Config.with_package_override cfg ~name ?branch:override.branch 47 + ()) 48 48 base_config 49 49 (Monopam.Verse_config.packages verse_config) 50 50 in
+7 -12
lib/config.ml
··· 1 1 module Package_config = struct 2 - type t = { 3 - branch : string option; 4 - dev_repo : string option; (** Override dev-repo URL for vendored packages *) 5 - } 2 + type t = { branch : string option } 6 3 7 4 let branch t = t.branch 8 - let dev_repo t = t.dev_repo 9 5 10 6 let codec : t Tomlt.t = 11 7 Tomlt.( 12 8 Table.( 13 - obj (fun branch dev_repo -> { branch; dev_repo }) 9 + obj (fun branch -> { branch }) 14 10 |> opt_mem "branch" string ~enc:(fun c -> c.branch) 15 - |> opt_mem "dev_repo" string ~enc:(fun c -> c.dev_repo) 16 11 |> finish)) 17 12 end 18 13 ··· 36 31 let create ~opam_repo ~checkouts ~monorepo ?(default_branch = "main") () = 37 32 { opam_repo; checkouts; monorepo; default_branch; packages = [] } 38 33 39 - let with_package_override t ~name ?branch:branch_opt ?dev_repo:dev_repo_opt () = 34 + let with_package_override t ~name ?branch:branch_opt () = 40 35 let existing = List.assoc_opt name t.packages in 41 36 let existing_branch = Option.bind existing Package_config.branch in 42 - let existing_dev_repo = Option.bind existing Package_config.dev_repo in 43 - let new_branch = match branch_opt with Some _ -> branch_opt | None -> existing_branch in 44 - let new_dev_repo = match dev_repo_opt with Some _ -> dev_repo_opt | None -> existing_dev_repo in 45 - let pkg_config = Package_config.{ branch = new_branch; dev_repo = new_dev_repo } in 37 + let new_branch = 38 + match branch_opt with Some _ -> branch_opt | None -> existing_branch 39 + in 40 + let pkg_config = Package_config.{ branch = new_branch } in 46 41 let packages = (name, pkg_config) :: List.remove_assoc name t.packages in 47 42 { t with packages } 48 43
+4 -10
lib/config.mli
··· 14 14 15 15 val branch : t -> string option 16 16 (** [branch t] returns the branch override for this package, if set. *) 17 - 18 - val dev_repo : t -> string option 19 - (** [dev_repo t] returns the dev-repo URL override for this package, if set. 20 - Use this to override the source URL for vendored packages. *) 21 17 end 22 18 23 19 type t ··· 112 108 @param monorepo Path to the monorepo 113 109 @param default_branch Default branch to track (default: "main") *) 114 110 115 - val with_package_override : 116 - t -> name:string -> ?branch:string -> ?dev_repo:string -> unit -> t 117 - (** [with_package_override t ~name ?branch ?dev_repo ()] returns a new config 111 + val with_package_override : t -> name:string -> ?branch:string -> unit -> t 112 + (** [with_package_override t ~name ?branch ()] returns a new config 118 113 with overrides for the named package. 119 114 120 115 @param branch Override the git branch for this package 121 - @param dev_repo Override the dev-repo URL for vendored packages. 122 - Use this when you've forked someone else's project and want the opam-repo 123 - to point to your fork instead of the original. *) 116 + 117 + Note: For dev-repo URL overrides, use [sources.toml] in the monorepo root. *) 124 118 125 119 (** {1 Pretty Printing} *) 126 120
+42 -40
lib/fork_join.ml
··· 187 187 match push_result with 188 188 | Error _ as e -> e 189 189 | Ok () -> 190 - (* Update sources.toml with fork entry *) 191 - let sources_path = Fpath.(monorepo / "sources.toml") in 192 - let sources = 193 - match Sources_registry.load ~fs:(fs :> _ Eio.Path.t) sources_path with 194 - | Ok s -> s 195 - | Error _ -> Sources_registry.empty 196 - in 197 - let url = match push_url with 198 - | Some u -> u 199 - | None -> "file://" ^ Fpath.to_string src_path 200 - in 201 - let entry = Sources_registry.{ 202 - url; 203 - upstream = None; 204 - branch = Some "main"; 205 - reason = Some "Forked from monorepo"; 206 - origin = Some Fork; 207 - } in 208 - let sources = Sources_registry.add sources ~subtree:name entry in 209 - (match Sources_registry.save ~fs:(fs :> _ Eio.Path.t) sources_path sources with 210 - | Ok () -> () 211 - | Error msg -> Logs.warn (fun m -> m "Failed to update sources.toml: %s" msg)); 190 + (* Only update sources.toml if there's a push URL *) 191 + (match push_url with 192 + | Some url -> 193 + let sources_path = Fpath.(monorepo / "sources.toml") in 194 + let sources = 195 + match Sources_registry.load ~fs:(fs :> _ Eio.Path.t) sources_path with 196 + | Ok s -> s 197 + | Error _ -> Sources_registry.empty 198 + in 199 + let entry = Sources_registry.{ 200 + url = normalize_git_url url; 201 + upstream = None; 202 + branch = Some "main"; 203 + reason = None; 204 + origin = Some Fork; 205 + } in 206 + let sources = Sources_registry.add sources ~subtree:name entry in 207 + (match Sources_registry.save ~fs:(fs :> _ Eio.Path.t) sources_path sources with 208 + | Ok () -> () 209 + | Error msg -> Logs.warn (fun m -> m "Failed to update sources.toml: %s" msg)) 210 + | None -> ()); 212 211 Ok { name; split_commit; src_path; push_url; packages_created = packages })) 213 212 end 214 213 end ··· 240 239 | Ok () -> 241 240 (* Find .opam files in the new subtree *) 242 241 let packages = find_opam_files ~fs subtree_path in 243 - (* Update sources.toml with join entry *) 244 - let sources_path = Fpath.(monorepo / "sources.toml") in 245 - let sources = 246 - match Sources_registry.load ~fs:(fs :> _ Eio.Path.t) sources_path with 247 - | Ok s -> s 248 - | Error _ -> Sources_registry.empty 249 - in 250 - let entry = Sources_registry.{ 251 - url = normalize_git_url url; 252 - upstream = Option.map normalize_git_url upstream; 253 - branch = Some branch; 254 - reason = Some "Joined to monorepo"; 255 - origin = Some Join; 256 - } in 257 - let sources = Sources_registry.add sources ~subtree:name entry in 258 - (match Sources_registry.save ~fs:(fs :> _ Eio.Path.t) sources_path sources with 259 - | Ok () -> () 260 - | Error msg -> Logs.warn (fun m -> m "Failed to update sources.toml: %s" msg)); 242 + (* Only update sources.toml if there's an upstream to track *) 243 + (match upstream with 244 + | Some _ -> 245 + let sources_path = Fpath.(monorepo / "sources.toml") in 246 + let sources = 247 + match Sources_registry.load ~fs:(fs :> _ Eio.Path.t) sources_path with 248 + | Ok s -> s 249 + | Error _ -> Sources_registry.empty 250 + in 251 + let entry = Sources_registry.{ 252 + url = normalize_git_url url; 253 + upstream = Option.map normalize_git_url upstream; 254 + branch = Some branch; 255 + reason = None; 256 + origin = Some Join; 257 + } in 258 + let sources = Sources_registry.add sources ~subtree:name entry in 259 + (match Sources_registry.save ~fs:(fs :> _ Eio.Path.t) sources_path sources with 260 + | Ok () -> () 261 + | Error msg -> Logs.warn (fun m -> m "Failed to update sources.toml: %s" msg)) 262 + | None -> ()); 261 263 Ok { name; source_url = url; upstream_url = upstream; packages_added = packages; from_handle = None } 262 264 end 263 265
+71 -4
lib/monopam.ml
··· 246 246 in 247 247 248 248 (* URL resolution order: 249 - 1. sources.toml override 250 - 2. dune-project source/homepage 251 - 3. existing opam-repo dev-repo (fallback) *) 252 - (* URL resolution order: 253 249 1. Explicit sources.toml entry for this subtree 254 250 2. dune-project source/homepage 255 251 3. sources.toml default_url_base + subtree name *) ··· 1479 1475 if !updated > 0 then 1480 1476 Log.info (fun m -> m "Regenerated %d opam-repo entries from monorepo" !updated) 1481 1477 1478 + (** Clone monorepo and opam-repo from verse registry if they don't exist locally. 1479 + This enables `monopam sync` to work in a fresh devcontainer. *) 1480 + let clone_from_verse_if_needed ~proc ~fs ~config () = 1481 + let monorepo = Config.Paths.monorepo config in 1482 + let opam_repo = Config.Paths.opam_repo config in 1483 + let monorepo_exists = Git.is_repo ~proc ~fs monorepo in 1484 + let opam_repo_exists = Git.is_repo ~proc ~fs opam_repo in 1485 + 1486 + (* If both exist, nothing to do *) 1487 + if monorepo_exists && opam_repo_exists then Ok () 1488 + else 1489 + (* Try to load verse config to get handle *) 1490 + match Verse_config.load ~fs () with 1491 + | Error _ -> 1492 + (* No verse config - can't clone from registry *) 1493 + Log.debug (fun m -> m "No verse config found, will initialize fresh repos"); 1494 + Ok () 1495 + | Ok verse_config -> 1496 + let handle = Verse_config.handle verse_config in 1497 + Log.info (fun m -> m "Found verse config for handle: %s" handle); 1498 + (* Load registry to look up URLs *) 1499 + match Verse_registry.clone_or_pull ~proc ~fs ~config:verse_config () with 1500 + | Error msg -> 1501 + Log.warn (fun m -> m "Could not load verse registry: %s" msg); 1502 + Ok () (* Continue without cloning - will init fresh *) 1503 + | Ok registry -> 1504 + match Verse_registry.find_member registry ~handle with 1505 + | None -> 1506 + Log.warn (fun m -> m "Handle %s not found in registry" handle); 1507 + Ok () 1508 + | Some member -> 1509 + (* Clone monorepo if needed *) 1510 + let result = 1511 + if monorepo_exists then Ok () 1512 + else begin 1513 + Log.app (fun m -> m "Cloning monorepo from %s..." member.monorepo); 1514 + let url = Uri.of_string member.monorepo in 1515 + let branch = Option.value ~default:"main" member.monorepo_branch in 1516 + match Git.clone ~proc ~fs ~url ~branch monorepo with 1517 + | Ok () -> 1518 + Log.app (fun m -> m "Monorepo cloned successfully"); 1519 + Ok () 1520 + | Error e -> 1521 + Log.err (fun m -> m "Failed to clone monorepo: %a" Git.pp_error e); 1522 + Error (Git_error e) 1523 + end 1524 + in 1525 + match result with 1526 + | Error e -> Error e 1527 + | Ok () -> 1528 + (* Clone opam-repo if needed *) 1529 + if opam_repo_exists then Ok () 1530 + else begin 1531 + Log.app (fun m -> m "Cloning opam-repo from %s..." member.opamrepo); 1532 + let url = Uri.of_string member.opamrepo in 1533 + let branch = Option.value ~default:"main" member.opamrepo_branch in 1534 + match Git.clone ~proc ~fs ~url ~branch opam_repo with 1535 + | Ok () -> 1536 + Log.app (fun m -> m "Opam-repo cloned successfully"); 1537 + Ok () 1538 + | Error e -> 1539 + Log.err (fun m -> m "Failed to clone opam-repo: %a" Git.pp_error e); 1540 + Error (Git_error e) 1541 + end 1542 + 1482 1543 let sync ~proc ~fs ~config ?package ?(remote = false) ?(skip_push = false) 1483 1544 ?(skip_pull = false) () = 1484 1545 let fs_t = fs_typed fs in 1546 + 1547 + (* Clone from verse registry if repos don't exist *) 1548 + match clone_from_verse_if_needed ~proc ~fs:fs_t ~config () with 1549 + | Error e -> Error e 1550 + | Ok () -> 1551 + 1485 1552 (* Update the opam repo first - clone if needed *) 1486 1553 let opam_repo = Config.Paths.opam_repo config in 1487 1554 if (not skip_pull) && Git.is_repo ~proc ~fs:fs_t opam_repo then begin
+3 -5
lib/verse_config.ml
··· 2 2 3 3 (** Package-level override for vendored packages *) 4 4 type package_override = { 5 - dev_repo : string option; (** Override dev-repo URL *) 6 5 branch : string option; (** Override branch *) 7 6 } 8 7 ··· 95 94 handle = "anil.recoil.org" 96 95 knot = "git.recoil.org" 97 96 98 - # Optional package overrides for vendored projects 97 + # Optional package overrides (branch only; URL overrides go in sources.toml) 99 98 [packages.braid] 100 - dev_repo = "git+https://github.com/avsm/braid" 99 + branch = "backport-fix" 101 100 *) 102 101 103 102 type workspace_section = { w_root : Fpath.t } ··· 123 122 let package_override_codec : package_override Tomlt.t = 124 123 Tomlt.( 125 124 Table.( 126 - obj (fun dev_repo branch -> { dev_repo; branch }) 127 - |> opt_mem "dev_repo" string ~enc:(fun p -> p.dev_repo) 125 + obj (fun branch -> { branch }) 128 126 |> opt_mem "branch" string ~enc:(fun p -> p.branch) 129 127 |> finish)) 130 128
+6 -3
lib/verse_config.mli
··· 12 12 13 13 (** {1 Types} *) 14 14 15 - (** Package-level override for vendored packages. *) 15 + (** Package-level override for vendored packages. 16 + 17 + Note: For dev-repo URL overrides, use [sources.toml] in the monorepo root instead. 18 + This type only supports branch overrides. *) 16 19 type package_override = { 17 - dev_repo : string option; (** Override dev-repo URL for opam-repo generation *) 18 20 branch : string option; (** Override git branch *) 19 21 } 20 22 ··· 38 40 Each entry is [(subtree_name, override)] where subtree_name is the 39 41 directory name in the monorepo (e.g., "braid" for mono/braid/). 40 42 41 - Use this to override dev-repo URLs for vendored packages. *) 43 + Use this to override git branches. For dev-repo URL overrides, 44 + use [sources.toml] in the monorepo root instead. *) 42 45 43 46 (** {1 Derived Paths} *) 44 47