123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231(********************************************************************************)(* crs - A tool for managing code review comments embedded in source code *)(* Copyright (C) 2024-2025 Mathieu Barbin <mathieu.barbin@gmail.com> *)(* *)(* This file is part of crs. *)(* *)(* crs is free software; you can redistribute it and/or modify it under the *)(* terms of the GNU Lesser General Public License as published by the Free *)(* Software Foundation either version 3 of the License, or any later version, *)(* with the LGPL-3.0 Linking Exception. *)(* *)(* crs is distributed in the hope that it will be useful, but WITHOUT ANY *)(* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *)(* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License and *)(* the file `NOTICE.md` at the root of this repository for more details. *)(* *)(* You should have received a copy of the GNU Lesser General Public License *)(* and the LGPL-3.0 Linking Exception along with this library. If not, see *)(* <http://www.gnu.org/licenses/> and <https://spdx.org>, respectively. *)(********************************************************************************)(* This module is derived from Iron (v0.9.114.44+47), file
* [./hg/cr_comment.ml], which is released under Apache 2.0:
*
* Copyright (c) 2016-2017 Jane Street Group, LLC <opensource-contacts@janestreet.com>
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* See the file `NOTICE.md` at the root of this repository for more details.
*
* Changes:
*
* - Remove dependency to [Core] - make small adjustments to use [Base] instead.
* - Remove dependency to [Async] - replace by [Shexp] and [Stdio].
* - Remove the [Stable] module - do not version the code.
* - Remove [bin_io] and [bin_digest] expect tests.
* - Remove [hash_consing] constructs - do not share the values.
* - Replace [Relpath] by [Vcs.Path_in_repo].
* - Remove [of_sexp] constructs.
* - Replace [Unresolved_name] by [Vcs.User_handle].
* - Remove [deriving fields] ppx constructs.
* - Remove alternate names and aliases resolution.
* - Remove incremental computation features.
* - Remove summary tables.
* - Introduce a local module for digests.
* - Remove verbose and debug logs.
* - Rewrite [String.slice] calls as equivalent [String.sub] calls.
* - Remove invariant checks.
* - Use [Vcs] instead of [Hg].
* - Remove [Crs_due_now_and_soon].
* - Remove support for in-file `Properties.
* - Remove support for extra headers.
* - Remove support for attributes.
* - Remove assignee computation (left as external work).
* - Replace [is_xcr] by a variant type [Kind.t].
* - Make [reported_by] mandatory.
* - Refactor [Raw], make [t] a record with a processed part that may fail.
* - Compute [digest_of_condensed_content] for all CR kinds.
* - Rename [Processed] to [Header].
* - Remove support for printing CRs without their content.
* - Compute positions and offsets with [Loc].
* - Some minor changes to the [reindented] content rendering.
*)moduleDigest_hex=structtypet=string[@@derivingcompare,equal,sexp_of]letto_stringt=tletcreatestr=str|>Stdlib.Digest.string|>Stdlib.Digest.to_hexendmoduleHeader=structmoduleT=struct[@@@coverageoff]typet={kind:Kind.tLoc.Txt.t;due:Due.tLoc.Txt.t;reported_by:Vcs.User_handle.tLoc.Txt.t;for_:Vcs.User_handle.tLoc.Txt.toption}[@@derivingequal,sexp_of]endincludeTmoduleWith_loc=structletreported_byt=t.reported_byletfor_t=t.for_letkindt=t.kindletduet=t.dueendletcreate~kind~due~reported_by~for_={kind;due;reported_by;for_}letreported_byt=t.reported_by.txtletfor_t=Option.mapt.for_~f:Loc.Txt.txtletkindt=t.kind.txtletduet=t.due.txtendmoduleT=struct[@@@coverageoff]typet={path:Vcs.Path_in_repo.t;whole_loc:Loc.t;header:Header.tOr_error.t;digest_of_condensed_content:Digest_hex.t;content:string}[@@derivingequal,sexp_of]endincludeTletpatht=t.pathletcontentt=t.contentletwhole_loct=t.whole_locletheadert=t.headerletcreate~path~whole_loc~header~digest_of_condensed_content~content={path;whole_loc;header;digest_of_condensed_content;content};;letdigest_ignoring_minor_text_changest=t.digest_of_condensed_contentmoduleFor_sorted_output:sigtypenonrect=t[@@derivingcompare]end=structtypenonrect=tletcomparet1t2=letc=Vcs.Path_in_repo.comparet1.patht2.pathinifc<>0thencelse(letc=Int.compare(Loc.start_linet1.whole_loc)(Loc.start_linet2.whole_loc)inifc<>0thencelseInt.compare(Loc.start_offsett1.whole_loc)(Loc.start_offsett2.whole_loc));;endletreindented_contentt=letindent=letlen=matcht.headerwith|Error_->letstart=Loc.startt.whole_locin(* The len of the indentation is a heuristic in this case. *)start.pos_cnum-start.pos_bol+3|Okh->letstart=Loc.starth.kind.locinstart.pos_cnum-start.pos_bolinString.makelen' 'inletstr=t.contentinletlines=String.splitstr~on:'\n'inmatchList.mapilines~f:(funis->lets=String.rstripsinifString.is_emptysthen""else(matchString.chop_prefixs~prefix:indentwith|None->ifi=0then" "^selseraiseStdlib.Exit|Somes->" "^s))with|exceptionStdlib.Exit->str|lines->String.concatlines~sep:"\n";;letsortts=List.sortts~compare:For_sorted_output.compareletduet=matcht.headerwith|Error_->Due.Now|Okp->Header.duep;;letkindt=matcht.headerwith|Error_->Kind.CR|Okp->Header.kindp;;letwork_ont:Due.t=matcht.headerwith|Error_->Now|Okp->(matchHeader.kindpwith|XCR->Now|CR->Header.duep);;letto_stringt=String.concat~sep:"\n"[Loc.to_stringt.whole_loc;reindented_contentt;""];;letoutput_one~include_delimcr~oc=letstr=to_stringcrinletnl=ifinclude_delimthen"\n"else""inOut_channel.output_stringoc(Printf.sprintf"%s%s"nlstr);;letoutput_listcrs~oc=letcrs=sortcrsinletinclude_delim=reffalseinList.itercrs~f:(funcr->output_one~include_delim:!include_delimcr~oc;include_delim:=true);;letprint_listcrs=output_listcrs~oc:Stdlib.stdoutmodulePrivate=structmoduleHeader=Headerletcreate=createend