123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161(**************************************************************************)(* *)(* Copyright 2012-2015 OCamlPro *)(* Copyright 2012 INRIA *)(* *)(* All rights reserved. This file is distributed under the terms of the *)(* GNU Lesser General Public License version 2.1, with the special *)(* exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)openOpamFilename.OpopenOpamProcess.Job.OpmoduleVCS=structletname=`darcsletexistsrepo_root=OpamFilename.exists_dir(repo_root/"_darcs")letdarcsrepo_root=letdir=OpamFilename.Dir.to_stringrepo_rootinfun?verbose?env?stdoutargs->OpamSystem.make_command~dir?verbose?env?stdout"darcs"argsletwith_tagrepo_url=matchrepo_url.OpamUrl.hashwith|None->funcmd->cmd|Somet->funcmd->cmd@["-t";t]letinitrepo_root_repo_url=OpamFilename.mkdirrepo_root;darcsrepo_root["init"]@@>funr->OpamSystem.raise_on_process_errorr;Done()letvc_dirrepo_root=repo_root/"_darcs"(* Darcs has no branches, no proper diff, no way to reset, can't return a
workdir diff including added/removed files... That makes it hard for
handling as a remote, and the following is a bit convoluted. *)letopam_remote_tag="opam-remote-tag"(* Marks the last fetched state *)letopam_reverse_commit="opam-revert-laststate"letopam_local_tag="opam-local-tag"(* Marks the current state, in the form of a reversing patch on top of the
fetched state *)letfetch?cache_dir:_repo_rootrepo_url=(* Just do a fresh pull into a temp directory, and replace _darcs/
There is no easy way to diff or make sure darcs forgets about local
patches otherwise. *)OpamFilename.with_tmp_dir_job@@fund->letrepodir=d/"repo"indarcsrepo_root(with_tagrepo_url["get";OpamUrl.base_urlrepo_url;"--repodir";OpamFilename.Dir.to_stringrepodir;"--quiet";"--lazy"])(* --no-working-dir would be fine, except it is stored in _darcs/format *)@@>funr->OpamSystem.raise_on_process_errorr;letdarcsdir=vc_dirrepo_rootinOpamFilename.rmdirdarcsdir;OpamFilename.move_dir~src:(vc_dirrepodir)~dst:darcsdir;(* We put the patch that reverts to the current state on top *)darcsrepo_root["tag";opam_remote_tag;"-A";"opam"]@@>funr->OpamSystem.raise_on_process_errorr;darcsrepo_root["record";"-l";"--boring";"--all";"-m";opam_reverse_commit;"-A";"opam"]@@>fun_r->(* May fail if patch empty, it's ok, we keep the two tags for comparison *)darcsrepo_root["tag";opam_local_tag;"-A";"opam"]@@>funr->OpamSystem.raise_on_process_errorr;Done()letreset_treerepo_root_repo_url=darcsrepo_root["obliterate";"--all";"-t";opam_local_tag]@@>funr->OpamSystem.raise_on_process_errorr;darcsrepo_root["obliterate";"--all";"-p";opam_reverse_commit]@@>funr->(* returns 0 even if patch doesn't exist *)OpamSystem.raise_on_process_errorr;Done()letpatch_applied__=Done()letrevisionrepo_root=(* 'Weak hash' is only supported from 2.10.3, so provide a fallback *)darcsrepo_root["show";"repo"]@@>funr->OpamSystem.raise_on_process_errorr;tryOpamStd.List.find_map(funs->matchOpamStd.String.rcut_ats' 'with|Some(label,value)whenOpamStd.String.contains~sub:"Weak Hash"label->Some(Done(Somevalue))|_->None)r.OpamProcess.r_stdoutwithNot_found->tryOpamStd.List.find_map(funs->matchOpamStd.String.rcut_ats' 'with|Some(label,value)whenOpamStd.String.contains~sub:"Num Patches"label->Some(Done(Some(Printf.sprintf"darcs-%s"value)))|_->None)r.OpamProcess.r_stdoutwithNot_found->DoneNoneletis_up_to_daterepo_root_repo_url=darcsrepo_root["log";"-p";opam_reverse_commit;"--last";"2"](* last 2 since the tag counts as one *)@@>function|{OpamProcess.r_code=0;_}->Donefalse|{OpamProcess.r_code=1;_}asr->OpamProcess.cleanup~force:truer;Donetrue|r->OpamSystem.process_errorrletdiffrepo_rootrepo_url=is_up_to_daterepo_rootrepo_url@@+function|true->DoneNone|false->letpatch_file=OpamSystem.temp_file~auto_clean:false"darcs-diff"inletfinalise()=OpamSystem.remove_filepatch_fileinOpamProcess.Job.catch(fune->finalise();raisee)@@fun()->darcsrepo_root~stdout:patch_file["diff";"--from-tag";opam_remote_tag;"--to-tag";opam_local_tag;"--diff-command";"diff -ruNa %2 %1";"--no-pause-for-gui";](* changing 'from' and 'to' doesn't work, so run a reverse diff command
instead*)@@>funr->OpamSystem.raise_on_process_errorr;ifOpamSystem.file_is_emptypatch_filethen(finalise();DoneNone)elseDone(Some(OpamFilename.of_stringpatch_file))letversioned_filesrepo_root=darcsrepo_root["show";"files"]@@>funr->OpamSystem.raise_on_process_errorr;Doner.OpamProcess.r_stdoutletcurrent_branch_dir=DoneNone(* No branches in Darcs *)letis_dirtydir=darcsdir["whatsnew";"--quiet";"--summary"]@@>funr->Done(OpamProcess.check_success_and_cleanupr)endmoduleB=OpamVCS.Make(VCS)