Monorepo management for opam overlays
0
fork

Configure Feed

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

Remove str and ptime.clock.os dependencies from monopam

Replace Str regex in git.ml with plain string operations for parsing
subtree commit messages. Change generate_aggregated and changes_since
to take explicit ~now:Ptime.t parameter instead of using Ptime_clock,
allowing callers to provide the current time from Eio clock.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

+44 -24
+1 -2
lib/changes.ml
··· 770 770 771 771 (** Generate an aggregated daily file from individual daily json files. 772 772 This creates a YYYYMMDD.json file in the .changes directory. *) 773 - let generate_aggregated ~fs ~monorepo ~date ~git_head = 773 + let generate_aggregated ~fs ~monorepo ~date ~git_head ~now = 774 774 let changes_dir = Eio.Path.(fs / Fpath.to_string monorepo / ".changes") in 775 775 776 776 (* List all *-<date>.json files (new per-day format) *) ··· 804 804 ) daily_files in 805 805 806 806 (* Convert to aggregated format *) 807 - let now = Ptime_clock.now () in 808 807 let agg_entries = List.map (fun (repo_name, (e : daily_entry)) -> 809 808 let change_type = infer_change_type e.summary in 810 809 Changes_aggregated.{
+4 -2
lib/changes.mli
··· 225 225 monorepo:Fpath.t -> 226 226 date:string -> 227 227 git_head:string -> 228 + now:Ptime.t -> 228 229 (unit, string) result 229 - (** [generate_aggregated ~fs ~monorepo ~date ~git_head] generates an aggregated 230 + (** [generate_aggregated ~fs ~monorepo ~date ~git_head ~now] generates an aggregated 230 231 JSON file from all daily JSON files. 231 232 232 233 This creates a .changes/YYYYMMDD.json file containing all repository entries ··· 235 236 @param fs Filesystem path 236 237 @param monorepo Path to the monorepo root 237 238 @param date Date in YYYY-MM-DD format 238 - @param git_head Short git hash of the monorepo HEAD at generation time *) 239 + @param git_head Short git hash of the monorepo HEAD at generation time 240 + @param now Current time for the generated_at field *)
+3 -4
lib/changes_query.ml
··· 8 8 This module provides convenient functions for querying changes since a 9 9 specific timestamp and formatting them for broadcast. *) 10 10 11 - let changes_since ~fs ~changes_dir ~since = 11 + let changes_since ~fs ~changes_dir ~since ~now = 12 12 (* Get the date part of since for filtering *) 13 13 let since_date = 14 14 let (y, m, d), _ = Ptime.to_date_time since in 15 15 Printf.sprintf "%04d-%02d-%02d" y m d 16 16 in 17 17 (* Get current date for range end *) 18 - let now = Ptime_clock.now () in 19 18 let now_date = 20 19 let (y, m, d), _ = Ptime.to_date_time now in 21 20 Printf.sprintf "%04d-%02d-%02d" y m d ··· 32 31 in 33 32 Ok entries 34 33 35 - let has_new_changes ~fs ~changes_dir ~since = 36 - match changes_since ~fs ~changes_dir ~since with 34 + let has_new_changes ~fs ~changes_dir ~since ~now = 35 + match changes_since ~fs ~changes_dir ~since ~now with 37 36 | Ok entries -> entries <> [] 38 37 | Error _ -> false 39 38
+6 -2
lib/changes_query.mli
··· 14 14 fs:_ Eio.Path.t -> 15 15 changes_dir:Fpath.t -> 16 16 since:Ptime.t -> 17 + now:Ptime.t -> 17 18 (Changes_aggregated.entry list, string) result 18 19 (** Get all change entries from aggregated files created after [since]. 19 - Returns entries from all days after the timestamp. *) 20 + Returns entries from all days after the timestamp. 21 + @param now Current time for determining the date range end. *) 20 22 21 23 val has_new_changes : 22 24 fs:_ Eio.Path.t -> 23 25 changes_dir:Fpath.t -> 24 26 since:Ptime.t -> 27 + now:Ptime.t -> 25 28 bool 26 - (** Check if there are any new changes since the given timestamp. *) 29 + (** Check if there are any new changes since the given timestamp. 30 + @param now Current time for determining the date range end. *) 27 31 28 32 (** {1 Formatting} *) 29 33
+1 -1
lib/dune
··· 1 1 (library 2 2 (name monopam) 3 3 (public_name monopam) 4 - (libraries eio tomlt tomlt.eio xdge opam-file-format fmt logs uri fpath claude jsont jsont.bytesrw ptime ptime.clock.os str)) 4 + (libraries eio tomlt tomlt.eio xdge opam-file-format fmt logs uri fpath claude jsont jsont.bytesrw ptime))
+28 -12
lib/git.ml
··· 262 262 or "Squashed 'prefix/' content from commit abc123" 263 263 Returns the end commit (most recent) if found. *) 264 264 let parse_subtree_message subject = 265 - (* Pattern: Squashed 'prefix/' changes from abc123..def456 *) 266 - let re_range = Str.regexp {|Squashed '[^']+/' changes from [a-f0-9]+\.\.\([a-f0-9]+\)|} in 267 - (* Pattern: Squashed 'prefix/' content from commit abc123 *) 268 - let re_single = Str.regexp {|Squashed '[^']+/' content from commit \([a-f0-9]+\)|} in 269 - (* Pattern: Add 'prefix/' from commit abc123 *) 270 - let re_add = Str.regexp {|Add '[^']+/' from commit \([a-f0-9]+\)|} in 271 - if Str.string_match re_range subject 0 then 272 - Some (Str.matched_group 1 subject) 273 - else if Str.string_match re_single subject 0 then 274 - Some (Str.matched_group 1 subject) 275 - else if Str.string_match re_add subject 0 then 276 - Some (Str.matched_group 1 subject) 265 + (* Helper to extract hex commit hash starting at position *) 266 + let extract_hex s start = 267 + let len = String.length s in 268 + let rec find_end i = 269 + if i >= len then i 270 + else match s.[i] with 271 + | '0'..'9' | 'a'..'f' -> find_end (i + 1) 272 + | _ -> i 273 + in 274 + let end_pos = find_end start in 275 + if end_pos > start then Some (String.sub s start (end_pos - start)) 276 + else None 277 + in 278 + (* Pattern 1: "Squashed 'prefix/' changes from abc123..def456" *) 279 + if String.starts_with ~prefix:"Squashed '" subject then 280 + match String.index_opt subject '.' with 281 + | Some i when i + 1 < String.length subject && subject.[i + 1] = '.' -> 282 + extract_hex subject (i + 2) 283 + | _ -> 284 + (* Pattern 2: "Squashed 'prefix/' content from commit abc123" *) 285 + (match String.split_on_char ' ' subject |> List.rev with 286 + | last :: "commit" :: "from" :: _ -> extract_hex last 0 287 + | _ -> None) 288 + (* Pattern 3: "Add 'prefix/' from commit abc123" *) 289 + else if String.starts_with ~prefix:"Add '" subject then 290 + match String.split_on_char ' ' subject |> List.rev with 291 + | last :: "commit" :: "from" :: _ -> extract_hex last 0 292 + | _ -> None 277 293 else 278 294 None 279 295
+1 -1
lib/monopam.ml
··· 1594 1594 | Ok hash -> String.sub hash 0 (min 7 (String.length hash)) 1595 1595 | Error _ -> "unknown" 1596 1596 in 1597 - match Changes.generate_aggregated ~fs:fs_t ~monorepo ~date:today ~git_head with 1597 + match Changes.generate_aggregated ~fs:fs_t ~monorepo ~date:today ~git_head ~now:now_ptime with 1598 1598 | Ok () -> Log.app (fun m -> m "Generated aggregated file .changes/%s.json" 1599 1599 (String.concat "" (String.split_on_char '-' today))) 1600 1600 | Error e -> Log.warn (fun m -> m "Failed to generate aggregated file: %s" e)