% Copyright (C) 2004,2007 David Roundy
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2, or (at your option)
% any later version.
%
% This program 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 General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; see the file COPYING. If not, write to
% the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
% Boston, MA 02110-1301, USA.
\darcsCommand{amend-record}
\begin{code}

moduleDarcs.Commands.AmendRecord(amendrecord)whereimportData.List(sort)importData.Maybe(isJust)importSystem.Directory(removeFile)importSystem.Exit(ExitCode(..),exitWith)importControl.Monad(when)importDarcs.Flags(DarcsFlag(Author,LogFile,PatchName,AskDeps,EditLongComment,PromptLongComment,KeepDate))importDarcs.Lock(worldReadableTemp)importDarcs.RepoPath(toFilePath)importDarcs.Hopefully(PatchInfoAnd,n2pia,hopefully,info)importDarcs.Repository(Repository,withRepoLock,($-),withGutsOf,tentativelyRemovePatches,tentativelyAddPatch,finalizeRepositoryChanges,amInRepository,invalidateIndex,unrecordedChanges)importDarcs.Patch(RepoPatch,description,Prim,fromPrims,infopatch,getdeps,adddeps,effect,)importDarcs.Patch.Prim(canonizeFL)importDarcs.Patch.Info(piAuthor,piName,piLog,piDateString,PatchInfo,patchinfo,isInverted,invertName,)importDarcs.Patch.Split(primSplitter)importDarcs.Witnesses.Ordered(FL(..),(:>)(..),(+>+),nullFL)importDarcs.SelectChanges(selectChanges,WhichChanges(..),selectionContextPrim,runSelection,withSelectedPatchFromRepo)importDarcs.Commands(DarcsCommand(..),nodefaults)importDarcs.Commands.Record(getDate,getLog,askAboutDepends)importDarcs.Arguments(DarcsFlag(All),areFileArgs,fixSubPaths,defineChanges,allInteractive,ignoretimes,askLongComment,askdeps,keepDate,author,patchnameOption,leaveTestDir,nocompress,lookforadds,workingRepoDir,matchOneNontag,umaskOption,test,listRegisteredFiles,getEasyAuthor,setScriptsExecutableOption)importDarcs.Utils(askUser,clarifyErrors)importPrinter(putDocLn)#include "gadts.h"amendrecordDescription::StringamendrecordDescription="Improve a patch before it leaves your repository."amendrecordHelp::StringamendrecordHelp="Amend-record updates a `draft' patch with additions or improvements,\n"++"resulting in a single `finished' patch. This is better than recording\n"++"the additions and improvements as separate patches, because then\n"++"whenever the `draft' patch is copied between repositories, you would\n"++"need to make sure all the extra patches are copied, too.\n"++"\n"++"Do not copy draft patches between repositories, because a finished\n"++"patch cannot be copied into a repository that contains a draft of the\n"++"same patch. If this has already happened, `darcs obliterate' can be\n"++"used to remove the draft patch.\n"++"\n"++-- FIXME: is the following still true in Darcs 2.1? --twb"Do not run amend-record in repository that other developers can pull\n"++"from, because if they pull while an amend-record is in progress, their\n"++"repository may be corrupted.\n"++"\n"++"When recording a draft patch, it is a good idea to start the name with\n"++"`DRAFT:' so that other developers know it is not finished. When\n"++"finished, remove it with `darcs amend-record --edit-long-comment'.\n"++"To change the patch name without starting an editor, use --patch-name.\n"++"\n"++"Like `darcs record', if you call amend-record with files as arguments,\n"++"you will only be asked about changes to those files. So to amend a\n"++"patch to foo.c with improvements in bar.c, you would run:\n"++"\n"++" darcs amend-record --match 'touch foo.c' bar.c\n"++"\n"++"It is usually a bad idea to amend another developer's patch. To make\n"++"amend-record only ask about your own patches by default, you can add\n"++"something like `amend-record match David Roundy' to ~/.darcs/defaults, \n"++"where `David Roundy' is your name. "++"On Windows use C:/Documents And Settings/user/Application Data/darcs/defaults\n"amendrecord::DarcsCommandamendrecord=DarcsCommand{commandProgramName="darcs",commandName="amend-record",commandHelp=amendrecordHelp,commandDescription=amendrecordDescription,commandExtraArgs=-1,commandExtraArgHelp=["[FILE or DIRECTORY]..."],commandCommand=amendrecordCmd,commandPrereq=amInRepository,commandGetArgPossibilities=listRegisteredFiles,commandArgdefaults=nodefaults,commandAdvancedOptions=[nocompress,ignoretimes,umaskOption,setScriptsExecutableOption],commandBasicOptions=[matchOneNontag,test,leaveTestDir,allInteractive,author,patchnameOption,askdeps,askLongComment,keepDate,lookforadds,workingRepoDir]}amendrecordCmd::[DarcsFlag]->[String]->IO()amendrecordCmdoptsargs=withRepoLockopts$-\(repository::RepositorypC(rur))->dofiles<-sort`fmap`fixSubPathsoptsargswhen(areFileArgsfiles)$putStrLn$"Amending changes in "++unwords(mapshowfiles)++":\n"withSelectedPatchFromRepo"amend"repositoryopts$\(_:>oldp)->doch<-unrecordedChangesoptsrepositoryfilescasechofNilFL|not(hasEditMetadataopts)->putStrLn"No changes!"_->doletcontext=selectionContextPrim"add"(filter(==All)opts)(JustprimSplitter)(maptoFilePathfiles)chosenPatches<-runSelection(selectChangesFirstch)contextaddChangesToPatchoptsrepositoryoldpchosenPatchesaddChangesToPatch::forallpC(rutxy).(RepoPatchp)=>[DarcsFlag]->RepositorypC(rut)->PatchInfoAndpC(xt)->(FLPrim:>FLPrim)C(ty)->IO()addChangesToPatchoptsrepositoryoldp(chs:>_)=if(nullFLchs&&not(hasEditMetadataopts))thenputStrLn"You don't want to record anything!"elsedoinvalidateIndexrepositorywithGutsOfrepository$dorepository'<-tentativelyRemovePatchesrepositoryopts(oldp:>:NilFL)(mlogf,newp)<-updatePatchHeaderoptsrepository'oldpchsdefineChangesnewprepository''<-tentativelyAddPatchrepository'optsnewpletfailmsg=maybe""(\lf->"\nLogfile left in "++lf++".")mlogffinalizeRepositoryChangesrepository''`clarifyErrors`failmsgmaybe(return())removeFilemlogfputStrLn"Finished amending patch:"putDocLn$descriptionnewpupdatePatchHeader::forallpC(xyrut).(RepoPatchp)=>[DarcsFlag]->RepositorypC(rut)->PatchInfoAndpC(tx)->FLPrimC(xy)->IO(MaybeString,PatchInfoAndpC(ty))updatePatchHeaderoptsrepositoryoldpchs=doletnewchs=canonizeFL(effectoldp+>+chs)letold_pdeps=getdeps$hopefullyoldpnewdeps<-ifAskDeps`elem`optsthenaskAboutDependsrepositorynewchsoptsold_pdepselsereturnold_pdepsletold_pinf=infooldpprior=(piNameold_pinf,piLogold_pinf)make_log=worldReadableTemp"darcs-amend-record"old_author=piAuthorold_pinfdate<-ifKeepDate`elem`optsthenreturn(piDateStringold_pinf)elsegetDateoptswarnIfHijackingoptsold_author(new_name,new_log,mlogf)<-getLogopts(Justprior)make_logchsletnew_author=casegetAuthoroptsofJusta->aNothing->piAuthorold_pinfmaybe_invert=ifisInvertedold_pinftheninvertNameelseidnew_pinf<-maybe_invert`fmap`patchinfodatenew_namenew_authornew_logletnewp=n2pia(adddeps(infopatchnew_pinf(fromPrimsnewchs))newdeps)return(mlogf,newp)warnIfHijacking::[DarcsFlag]->String->IO()warnIfHijackingoptsold_author=doauthor_here<-getEasyAuthorcaseauthor_hereofNothing->return()Justah->letedit_author=isJust(getAuthoropts)inif(edit_author||ah==old_author)thenreturn()elsedoyorn<-askUser$"You're not "++old_author++"! Amend anyway? "caseyornof('y':_)->return()_->exitWith$ExitSuccesshasEditMetadata::[DarcsFlag]->BoolhasEditMetadata(Author_:_)=TruehasEditMetadata(LogFile_:_)=TruehasEditMetadata(PatchName_:_)=TruehasEditMetadata(EditLongComment:_)=TruehasEditMetadata(PromptLongComment:_)=TruehasEditMetadata(AskDeps:_)=TruehasEditMetadata(_:fs)=hasEditMetadatafshasEditMetadata[]=FalsegetAuthor::[DarcsFlag]->MaybeStringgetAuthor(Authora:_)=JustagetAuthor(_:as)=getAuthorasgetAuthor[]=Nothing