%  Copyright (C) 2003-2004 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.

\subsection{darcs tag}
\begin{code}
module Darcs.Commands.Tag ( tag ) where
import Control.Monad ( when )

import Darcs.Commands
import Darcs.Arguments
import Darcs.Utils ( askUser )
import Darcs.Repository ( amInRepository, withRepoLock, read_repo,
                    tentativelyAddPatch, finalizeRepositoryChanges, 
                  )
import Darcs.Repository.Checkpoint ( write_recorded_checkpoint )
import Darcs.Patch
import Darcs.Patch.Info
import Darcs.Patch.Depends
import Darcs.Commands.Record ( get_date )
\end{code}
\begin{code}
tag_description :: String
tag_description =
 "Tag the contents of the repository with a version name."
\end{code}

\options{tag}

\haskell{tag_help} Tag differs from record in that it doesn't record any
new changes, and it always depends on all patches residing in the
repository when it is tagged.  This means that one can later reproduce this
version of the repository by calling, for example:
\begin{verbatim}
% darcs get --tag "darcs 3.14" REPOLOCATION
\end{verbatim}

\begin{code}
tag_help :: String
tag_help =
 "Tag is used to name a version of this repository (i.e. the whole tree).\n"
\end{code}
\begin{code}
tag :: DarcsCommand
tag = DarcsCommand {command_name = "tag",
                    command_help = tag_help,
                    command_description = tag_description,
                    command_extra_args = -1,
                    command_extra_arg_help = ["[TAGNAME]"],
                    command_command = tag_cmd,
                    command_prereq = amInRepository,
                    command_get_arg_possibilities = return [],
                    command_argdefaults = nodefaults,
                    command_darcsoptions = [patchname_option, author,
                                            checkpoint, nocompress,
                                            pipe_interactive, verbose,
                                            working_repo_dir,
                                            umask_option]}
\end{code}
\begin{code}
tag_cmd :: [DarcsFlag] -> [String] -> IO ()
tag_cmd opts args = withRepoLock opts $ \repository -> do
    date <- get_date opts
    the_author <- get_author opts
    deps <- get_tags_right `fmap` read_repo repository
    name <- if (not . null) args
            then return $ "TAG " ++ unwords args
            else get_patchname opts
    let mypatch = namepatch date name the_author [] null_patch
        myinfo = patchinfo date name the_author []
       in do
       tentativelyAddPatch repository opts $ adddeps mypatch deps
       finalizeRepositoryChanges repository
       when (CheckPoint `elem` opts) $ write_recorded_checkpoint repository myinfo
       putStrLn $ "Finished tagging patch '"++name++"'"
\end{code}
Each tagged version has a version name.
\begin{code}
get_patchname :: [DarcsFlag] -> IO String
get_patchname (PatchName n:_) = return $ "TAG "++n
get_patchname (_:flags) = get_patchname flags
get_patchname [] = do
    n <- askUser "What is the version name? "
    if n == "" then get_patchname []
               else return $ "TAG "++n
\end{code}
The version is also flagged with the person who tagged it (taken by default
from the `DARCS\_EMAIL' or `EMAIL' environment variable).  The date is also
included in the version information.

A tagged version automatically depends on all patches in the repository.  This
allows you to later reproduce precisely that version.  The tag does this by
depending on all patches in the repository, except for those which are depended
upon by other tags already in the repository.  In the common case of a sequential
series of tags, this means that the tag depends on all patches since the
last tag, plus that tag itself.

\begin{options}
--checkpoint
\end{options}
The \verb!--checkpoint! option allows the tag be used later with the
\verb!--partial! flag to \verb!get! or \verb!check!.

A partial repository only contains patches from after the checkpoint.  A
partial repository works just like a normal repository, but any command that
needs to look at the contents of a missing patch will complain and abort.

\begin{options}
--pipe
\end{options}

If you run tag with the \verb!--pipe! option, you will be prompted for the
tag name and date.  This interface is intended for scripting darcs, in
particular for writing repository conversion scripts.  The prompts are
intended mostly as useful guide (since scripts won't need them), to help
you understand the format in which to provide the input. Here's an example
of what the \verb!--pipe! prompts looks like:

\begin{verbatim}
 What is the date? Mon Nov 15 13:38:01 EST 2004
 Who is the author? David Roundy
 What is the version name? 3.0
 Finished tagging patch 'TAG 3.0'
\end{verbatim}

Using \verb!tag! creates an entry in the repository history just like \verb!record!.
It will show up with \verb!darcs changes! appearing in the format:

\begin{verbatim}
 tagged My Tag Name
\end{verbatim}

To display all tags in the repository, use the ``\verb!darcs query tags!''
command.
