packages feed

darcs-2.1.2.1: src/Darcs/Commands/Tag.lhs

%  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 ( DarcsCommand(DarcsCommand, command_name, command_help,
                        command_description, command_extra_args,
                        command_extra_arg_help, command_command, command_prereq,
                        command_get_arg_possibilities, command_argdefaults,
                        command_advanced_options, command_basic_options),
                        nodefaults )
import Darcs.Arguments ( nocompress, umask_option, patchname_option, author,
                         checkpoint, pipe_interactive, ask_long_comment,
                         working_repo_dir, get_author )
import Darcs.Hopefully ( n2pia )
import Darcs.Repository ( amInRepository, withRepoLock, ($-), read_repo,
                    tentativelyAddPatch, finalizeRepositoryChanges, 
                  )
import Darcs.Repository.Checkpoint ( write_recorded_checkpoint )
import Darcs.Patch ( infopatch, identity, adddeps )
import Darcs.Patch.Info ( patchinfo )
import Darcs.Patch.Depends ( get_tags_right )
import Darcs.Commands.Record ( get_date, get_log )
import Darcs.Ordered ( FL(..) )
import Darcs.Lock ( world_readable_temp )
import Darcs.Flags ( DarcsFlag(..) )
import System.IO ( hPutStr, stderr )
\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_advanced_options = [nocompress,umask_option],
                    command_basic_options = [patchname_option, author,
                                            checkpoint,
                                            pipe_interactive,
                                            ask_long_comment,
                                            working_repo_dir]}
\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, long_comment)  <- get_name_log opts args
    myinfo <- patchinfo date name the_author long_comment
    let mypatch = infopatch myinfo identity
    tentativelyAddPatch repository opts $ n2pia $ adddeps mypatch deps
    finalizeRepositoryChanges repository
    when (CheckPoint `elem` opts) $ write_recorded_checkpoint repository myinfo
    putStrLn $ "Finished tagging patch '"++name++"'"
  where  get_name_log :: [DarcsFlag] -> [String] -> IO (String, [String])
         get_name_log o a = do let o2 = if null a then o else (add_patch_name o (unwords a))
                               (name, comment, _) <- get_log o2 Nothing (world_readable_temp "darcs-tag") NilFL
                               when (length name < 2) $ hPutStr stderr $
                                 "Do you really want to tag '"
                                 ++name++"'? If not type: darcs obliterate --last=1\n"
                               return ("TAG " ++ name, comment)
         add_patch_name :: [DarcsFlag] -> String -> [DarcsFlag]
         add_patch_name o a| has_patch_name o = o
                           | otherwise = [PatchName a] ++ o
         has_patch_name (PatchName _:_) = True
         has_patch_name (_:fs) = has_patch_name fs
         has_patch_name [] = False

\end{code}
Each tagged version has a version name.
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 date and author.  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.