Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file compare_core.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308openCoreopenImportletlines_of_contentscontents=letlines=Array.of_list(String.split_linescontents)inlethas_trailing_newline=letlength=String.lengthcontentsiniflength=0||Char.equalcontents.[length-1]'\n'then`With_trailing_newlineelse`Missing_trailing_newlineinlines,has_trailing_newline;;let%test_unit_=lettestcontents~expect=[%test_result:stringarray*[`With_trailing_newline|`Missing_trailing_newline]](lines_of_contentscontents)~expectintest""~expect:([||],`With_trailing_newline);test"hello"~expect:([|"hello"|],`Missing_trailing_newline);test"hello\nworld"~expect:([|"hello";"world"|],`Missing_trailing_newline);test"hello\nworld\n"~expect:([|"hello";"world"|],`With_trailing_newline);;(* Returns a Hunk.t list, ready to be printed *)letcompare_linesconfig~prev~next=letmoduleC=Configurationin(* Create the diff *)letcontext=config.C.contextinletkeep_ws=config.C.keep_wsinletsplit_long_lines=config.C.split_long_linesinletline_big_enough=config.C.line_big_enoughinlethunks=lettransform=ifkeep_wsthenFn.idelsePatdiff_core.remove_wsin(* Use external compare program? *)matchconfig.C.ext_cmpwith|None->Patience_diff.String.get_hunks~transform~context~big_enough:line_big_enough~prev~next|Someprog->letcomparexy=letcmd=sprintf"%s %S %S"progxyinmatchUnix.systemcmdwith|Ok()->0|Error(`Exit_non_zero1)->1|Error_->failwithf"External compare %S failed!"prog()inletmoduleP=Patience_diff.Make(structtypet=string[@@derivingsexp]lethash=String.hashletcompare=compareend)inP.get_hunks~transform~context~big_enough:line_big_enough~prev~nextinlethunks=matchconfig.C.float_tolerancewith|None->hunks|Sometolerance->Float_tolerance.applyhunkstolerance~contextin(* Refine if desired *)ifconfig.C.unrefinedthen(* Turn `Replace ranges into `Prev and `Next ranges.
`Replace's would otherwise be later interpreted as refined output *)Patience_diff.Hunks.unifiedhunkselse(letrules=config.C.rulesinletoutput=config.C.outputinletproduce_unified_lines=config.C.produce_unified_linesinletinterleave=config.C.interleaveinletword_big_enough=config.C.word_big_enoughinPatdiff_core.refine~rules~output~keep_ws~produce_unified_lines~split_long_lines~interleavehunks~word_big_enough);;letwarn_if_no_trailing_newline~warn_if_no_trailing_newline_in_both(prev_file_newline,prev_file)(next_file_newline,next_file)=letwarn=eprintf"No newline at the end of %s\n%!"inmatchprev_file_newline,next_file_newlinewith|`With_trailing_newline,`With_trailing_newline->()|`With_trailing_newline,`Missing_trailing_newline->warnnext_file|`Missing_trailing_newline,`With_trailing_newline->warnprev_file|`Missing_trailing_newline,`Missing_trailing_newline->ifwarn_if_no_trailing_newline_in_boththen(warnprev_file;warnnext_file);;(* Returns a Hunk.t list, ready to be printed *)letcompare_files(config:Configuration.t)~prev_file~next_file=letprev=In_channel.read_allprev_fileinletnext=In_channel.read_allnext_fileinComparison_result.createconfig~prev:{name=prev_file;text=prev}~next:{name=next_file;text=next}~compare_assuming_text:(funconfig~prev~next->letprev_lines,prev_file_newline=lines_of_contentsprev.textinletnext_lines,next_file_newline=lines_of_contentsnext.textinwarn_if_no_trailing_newline(prev_file_newline,prev.name)(next_file_newline,next.name)~warn_if_no_trailing_newline_in_both:config.warn_if_no_trailing_newline_in_both;compare_linesconfig~prev:prev_lines~next:next_lines);;letbinary_different_message~(config:Configuration.t)~prev_file~prev_is_binary~next_file~next_is_binary=matchconfig.location_stylewith|Diff->sprintf"Files %s%s and %s%s differ"prev_file(ifprev_is_binarythen" (binary)"else"")next_file(ifnext_is_binarythen" (binary)"else"")|Omake->String.concat[error_message_start~file:prev_file~line:1;"\n";" File \"";next_file;"\"\n";" binary files differ\n"];;(* Print hunks to stdout *)letprinthunks~prev_file~next_file~config=letmoduleC=ConfigurationinifComparison_result.has_no_diffhunksthen(ifconfig.C.double_checkthen(matchUnix.system(sprintf"cmp -s %s %s"prev_filenext_file)with|Ok()->()|Error(`Exit_non_zero1)->printf"There are no differences except those filtered by your settings\n%!"|Error_->()))elseif(* Only print if -quiet is not set *)notconfig.C.quietthen(letoutput=config.C.outputinletrules=config.C.rulesin(* Substitute prev/new_alt for the filenames in the final output *)letprev_file=Option.value~default:prev_fileconfig.C.old_altinletnext_file=Option.value~default:next_fileconfig.C.new_altinmatchhunkswith|Binary_same->assertfalse|Binary_different{prev_is_binary;next_is_binary}->Printf.printf"%s\n"(binary_different_message~config~prev_file~prev_is_binary~next_file~next_is_binary)|Hunkshunks->Patdiff_core.printhunks~prev_file~next_file~output~rules~location_style:config.location_style);;letdiff_filesconfig~prev_file~next_file=lethunks=compare_files~prev_file~next_fileconfiginprinthunks~prev_file~next_file~config;ifComparison_result.has_no_diffhunksthen`Sameelse`Different;;letdiff_strings?print_global_header(config:Configuration.t)~(prev:Patdiff_core.diff_input)~(next:Patdiff_core.diff_input)=letlines{Patdiff_core.name=_;text}=String.split_linestext|>Array.of_listinlethunks=Comparison_result.createconfig~prev~next~compare_assuming_text:(funconfig~prev~next->compare_linesconfig~prev:(linesprev)~next:(linesnext))inifComparison_result.has_no_diffhunksthen`Sameelse`Different(matchhunkswith|Binary_same->assertfalse|Binary_different{prev_is_binary;next_is_binary}->binary_different_message~config~prev_file:prev.name~prev_is_binary~next_file:next.name~next_is_binary|Hunkshunks->Patdiff_core.output_to_stringhunks?print_global_header~file_names:(prev.name,next.name)~output:config.output~rules:config.rules~location_style:config.location_style);;(* True if a file is a regular file *)letis_regpath=(Unix.statpath).Unix.st_kind=Unix.S_REGletis_dirpath=(Unix.statpath).Unix.st_kind=Unix.S_DIRletrecdiff_dirsconfig~prev_file~next_file~file_filter=letmoduleC=Configurationin(* Get a list of files for this directory only; do not descend farther
(We recursively call diff_dirs later if we need to descend.) *)letoptions={Find_files.Options.defaultwithmax_depth=Some1;filter=file_filter}inletset_of_filefile=letfiles=Find_files.find_all~optionsfileinletf(n,_s)=Filename_extended.make_relative~to_:fileninletnames=List.mapfiles~finString.Set.of_listnamesinletprev_set=set_of_fileprev_fileinletnext_set=set_of_filenext_filein(* Get unique files *)letunion=Set.unionprev_setnext_setinletprev_uniques=Set.diffunionnext_setinletnext_uniques=Set.diffunionprev_setinlethandle_uniquefile~dir~is_prev=printf"Only in %s: %s\n%!"dirfile;(* Diff unique files against /dev/null, if desired *)ifnotconfig.C.mask_uniquesthen(letpath=dir^/fileinifis_regpaththen(letdiff=diff_filesconfiginletnull="/dev/null"inifis_prevthenignore(diff~prev_file:path~next_file:null)elseignore(diff~prev_file:null~next_file:path)))inSet.iterprev_uniques~f:(handle_unique~dir:prev_file~is_prev:true);Set.iternext_uniques~f:(handle_unique~dir:next_file~is_prev:false);(* Get differences *)letinter=Set.interprev_setnext_setinletexit_code=ref`Sameinletdifffile=letprev_file=prev_file^/fileinletnext_file=next_file^/fileinifis_regprev_file&&is_regnext_filethen(lethunks=compare_files~prev_file~next_fileconfiginifnot(Comparison_result.has_no_diffhunks)then(exit_code:=`Different;(* Print the diff if not -quiet *)ifconfig.C.quiet=falsethenprinthunks~prev_file~next_file~configelseprintf"Files %s and %s differ\n%!"prev_filenext_file))elseifis_dirprev_file&&is_dirnext_filethenifnotconfig.C.shallowthen(matchdiff_dirs~prev_file~next_fileconfig~file_filterwith|`Same->()|`Different->exit_code:=`Different)elseprintf"Common subdirectories: %s and %s\n%!"prev_filenext_fileelse(exit_code:=`Different;printf"Files %s and %s are not the same type\n%!"prev_filenext_file)inSet.iterinter~f:diff;ifSet.is_emptyprev_uniques&&Set.is_emptynext_uniquesthen!exit_codeelse`Different;;