Find git executable at run time
[git-darcs-import.git] / src / Darcs / Commands.lhs
blob88cf3be283213b7429d69c20ddabcf9ea3ecd36b
1 % Copyright (C) 2002,2003,2005 David Roundy
3 % This program is free software; you can redistribute it and/or modify
4 % it under the terms of the GNU General Public License as published by
5 % the Free Software Foundation; either version 2, or (at your option)
6 % any later version.
8 % This program is distributed in the hope that it will be useful,
9 % but WITHOUT ANY WARRANTY; without even the implied warranty of
10 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 % GNU General Public License for more details.
13 % You should have received a copy of the GNU General Public License
14 % along with this program; see the file COPYING. If not, write to
15 % the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 % Boston, MA 02110-1301, USA.
18 \begin{code}
19 module Darcs.Commands ( CommandControl( Command_data, Hidden_command, Group_name ),
20 DarcsCommand( DarcsCommand, command_name,
21 command_help, command_description,
22 command_basic_options, command_advanced_options,
23 command_command,
24 command_prereq,
25 command_extra_arg_help,
26 command_extra_args,
27 command_argdefaults,
28 command_get_arg_possibilities,
29 SuperCommand,
30 command_sub_commands ),
31 command_alias, command_stub,
32 command_options, command_alloptions,
33 disambiguate_commands, CommandArgs(..),
34 get_command_help, get_command_mini_help,
35 get_subcommands,
36 usage, subusage, chomp_newline,
37 extract_commands,
38 super_name,
39 nodefaults,
40 loggers,
41 ) where
43 import System.Console.GetOpt( OptDescr, usageInfo )
45 import Data.List ( sort, isPrefixOf )
46 import Darcs.Arguments
47 import Darcs.RepoPath ( AbsolutePath, rootDirectory )
48 import Darcs.Utils ( putStrLnError )
49 import Printer ( Doc, putDocLn )
50 \end{code}
52 The general format of a darcs command is
53 \begin{verbatim}
54 % darcs COMMAND OPTIONS ARGUMENTS ...
55 \end{verbatim}
56 Here \verb|COMMAND| is a command such as \verb|add| or \verb|record|, which of
57 course may have one or more arguments. Options have the form
58 \verb!--option! or \verb!-o!, while arguments vary from command to
59 command. There are many options which are common to a number of different
60 commands, which will be summarized here.
62 If you wish, you may use any unambiguous beginning of a command name as a
63 shortcut: for \verb!darcs record!, you could type \verb!darcs recor! or
64 \verb!darcs rec!, but not \verb!darcs re! since that could be confused with
65 \verb!darcs replace!, \verb!darcs revert! and \verb!darcs remove!.
67 In some cases, \verb|COMMAND| actually consists of two words, a
68 super-command and a subcommand. For example, the ``display the
69 manifest'' command has the form \verb|darcs query manifest|.
71 \paragraph{Command overview}
73 Not all commands modify the ``patches'' of your repository (that
74 is, the named patches which other users can pull); some commands only
75 affect the copy of the source tree you're working on (your ``working
76 directory''), and some affect both. This table summarizes what you should
77 expect from each one and will hopefully serve as guide when you're having
78 doubts about which command to use.
80 \begin{center}
81 \footnotetext[1]{But it affects the repository and working directory targeted
82 by the push}
83 \footnotetext[2]{As for the other end, see apply}
84 \begin{tabular}{|c|c|c|}
85 \hline
86 affects & patches & working directory\\
87 \hline
88 record & yes & no\\
89 \hline
90 unrecord & yes & no\\
91 \hline
92 rollback & yes & yes\\
93 \hline
94 revert & no & yes\\
95 \hline
96 unrevert & no & yes\\
97 \hline
98 pull & yes & yes\\
99 \hline
100 obliterate & yes & yes\\
101 \hline
102 apply & yes & yes\\
103 \hline
104 push\footnote{But it affects the repository and working directory targeted by
105 the push} & no & no\\
106 \hline
107 send\footnote{As for the other end, see apply} & no & no\\
108 \hline
109 put\footnote{Creates a new repository} & no & no\\
110 \hline
111 \end{tabular}
112 \end{center}
114 \begin{code}
115 extract_commands, extract_hidden_commands :: [CommandControl] -> [DarcsCommand]
116 extract_commands cs = concatMap (\x -> case x of { Command_data cmd_d -> [cmd_d]; _ -> []}) cs
117 extract_hidden_commands cs = concatMap (\x -> case x of { Hidden_command cmd_d -> [cmd_d]; _ -> []}) cs
118 \end{code}
120 \input{Darcs/Arguments.lhs}
122 \begin{code}
123 data CommandControl = Command_data DarcsCommand
124 | Hidden_command DarcsCommand
125 | Group_name String
127 data DarcsCommand =
128 DarcsCommand {command_name, command_help, command_description :: String,
129 command_extra_args :: Int,
130 command_extra_arg_help :: [String],
131 command_command :: [DarcsFlag] -> [String] -> IO (),
132 command_prereq :: [DarcsFlag] -> IO (Either String ()),
133 command_get_arg_possibilities :: IO [String],
134 command_argdefaults :: [DarcsFlag] -> AbsolutePath -> [String] -> IO [String],
135 command_basic_options :: [DarcsOption],
136 command_advanced_options :: [DarcsOption]}
137 | SuperCommand {command_name, command_help, command_description :: String,
138 command_prereq :: [DarcsFlag] -> IO (Either String ()),
139 command_sub_commands :: [CommandControl]}
141 command_alloptions :: DarcsCommand -> ([DarcsOption], [DarcsOption])
142 command_alloptions DarcsCommand { command_basic_options = opts1
143 , command_advanced_options = opts2 }
144 = (opts1 ++ [disable, help],
145 any_verbosity ++ opts2 ++
146 [posthook_cmd, posthook_prompt
147 ,prehook_cmd, prehook_prompt])
149 -- Supercommands cannot be disabled.
150 command_alloptions SuperCommand { } = ([help],[])
152 -- Obtain options suitable as input to
153 -- System.Console.Getopt, including the --disable option (which is
154 -- not listed explicitly in the DarcsCommand definitions).
155 command_options :: AbsolutePath -> DarcsCommand -> ([OptDescr DarcsFlag], [OptDescr DarcsFlag])
156 command_options cwd c = (convert basic, convert advanced)
157 where (basic, advanced) = command_alloptions c
158 convert = concatMap (option_from_darcsoption cwd)
160 nodefaults :: [DarcsFlag] -> AbsolutePath -> [String] -> IO [String]
161 nodefaults _ _ xs = return xs
163 get_subcommands :: DarcsCommand -> [CommandControl]
164 get_subcommands c@(SuperCommand {}) = command_sub_commands c
165 get_subcommands _ = []
167 command_alias :: String -> DarcsCommand -> DarcsCommand
168 command_alias n c =
169 c { command_name = n
170 , command_help = desc ++ "\n" ++ command_help c
171 , command_description = desc
173 where desc = "Alias for " ++ command_name c
175 command_stub :: String -> String -> String -> DarcsCommand -> DarcsCommand
176 command_stub n h d c =
177 c { command_name = n
178 , command_help = h
179 , command_description = d
180 , command_command = \_ _ -> putStr h
182 \end{code}
184 \begin{code}
185 usage :: [CommandControl] -> String
186 usage cs = "Usage: darcs COMMAND ...\n\nCommands:\n" ++
187 usage_helper cs ++ "\n" ++
188 "Use 'darcs COMMAND --help' for help on a single command.\n" ++
189 "Use 'darcs --version' to see the darcs version number.\n" ++
190 "Use 'darcs --exact-version' to get the exact version of this darcs instance.\n\n" ++
191 "Check bug reports at http://bugs.darcs.net/\n"
193 subusage :: DarcsCommand -> String
194 subusage super =
195 (usageInfo
196 ("Usage: darcs "++command_name super++" SUBCOMMAND ... " ++
197 "\n\n"++ command_description super++
198 "\n\nSubcommands:\n" ++ usage_helper (get_subcommands super) ++ "\nOptions:")
199 (option_from_darcsoption rootDirectory help))
200 ++ "\n" ++ command_help super
202 usage_helper :: [CommandControl] -> String
203 usage_helper [] = ""
204 usage_helper (Hidden_command _:cs) = usage_helper cs
205 usage_helper ((Command_data c):cs) = " "++pad_spaces (command_name c) 15 ++
206 chomp_newline (command_description c)++"\n"++usage_helper cs
207 usage_helper ((Group_name n):cs) = n ++ "\n" ++ usage_helper cs
209 chomp_newline :: String -> String
210 chomp_newline "" = ""
211 chomp_newline s = if last s == '\n' then init s else s
213 pad_spaces :: String -> Int -> String
214 pad_spaces s n = s ++ replicate (n - length s) ' '
216 super_name :: Maybe DarcsCommand -> String
217 super_name Nothing = ""
218 super_name (Just x) = command_name x ++ " "
220 get_command_mini_help :: Maybe DarcsCommand -> DarcsCommand -> String
221 get_command_mini_help msuper cmd =
222 get_command_help_core msuper cmd ++
223 "\n\nSee darcs help "
224 ++ (maybe "" (\c -> command_name c ++ " ") msuper)
225 ++ command_name cmd ++ " for details."
227 get_command_help :: Maybe DarcsCommand -> DarcsCommand -> String
228 get_command_help msuper cmd =
229 unlines (reverse basicR)
230 ++ (if null advanced then ""
231 else "\nAdvanced options:\n" ++ unlines (reverse advancedR))
232 ++ "\n" ++ command_help cmd
233 where -- we could just call usageInfo twice, but then the advanced
234 -- options might not line up with the basic ones (no short flags)
235 (advancedR, basicR) =
236 splitAt (length advanced) $ reverse $ lines combinedUsage
237 combinedUsage = usageInfo
238 (get_command_help_core msuper cmd ++ subcommands ++ "\n\nOptions:")
239 (basic ++ advanced)
240 (basic, advanced) = command_options rootDirectory cmd
241 subcommands =
242 case msuper of
243 Nothing -> case get_subcommands cmd of
244 [] -> []
245 s -> "\n\nSubcommands:\n" ++ (usage_helper s)
246 -- we don't want to list subcommands if we're already specifying them
247 Just _ -> ""
249 get_command_help_core :: Maybe DarcsCommand -> DarcsCommand -> String
250 get_command_help_core msuper cmd =
251 "Usage: darcs "++super_name msuper++command_name cmd++
252 " [OPTION]... " ++ unwords args_help ++
253 "\n"++ command_description cmd
254 where args_help = case cmd of
255 (DarcsCommand _ _ _ _ _ _ _ _ _ _ _) ->
256 command_extra_arg_help cmd
257 _ -> []
258 \end{code}
260 \begin{code}
261 data CommandArgs = CommandOnly DarcsCommand
262 | SuperCommandOnly DarcsCommand
263 | SuperCommandSub DarcsCommand DarcsCommand
265 -- Parses a darcs command line with potentially abbreviated commands
266 disambiguate_commands :: [CommandControl] -> String -> [String]
267 -> Either String (CommandArgs, [String])
268 disambiguate_commands allcs cmd args =
269 do c <- extract cmd allcs
270 case (get_subcommands c, args) of
271 ([], _) -> return (CommandOnly c, args)
272 (_ ,[]) -> return (SuperCommandOnly c, args)
273 (subcs, (a:as)) -> case extract a subcs of
274 Left _ -> return (SuperCommandOnly c, args)
275 Right sc -> return (SuperCommandSub c sc, as)
277 extract :: String -> [CommandControl] -> Either String DarcsCommand
278 extract cmd cs =
279 case [ c | c <- extract_commands cs, cmd `isPrefixOf` command_name c ] ++
280 [ h | h <- extract_hidden_commands cs, cmd == command_name h ] of
281 [] -> Left $ "No such command '" ++ cmd ++ "'\n"
282 [c] -> Right c
283 cs' -> Left $ "Ambiguous command...\n\n" ++
284 "The command '"++cmd++"' could mean one of:\n" ++
285 unwords (sort $ map command_name cs')
286 \end{code}
288 \begin{code}
289 -- | Output functions equivalent to (putStrLn, hPutStrLn stderr, putDocLn)
290 loggers :: [DarcsFlag] -> ( String -> IO ()
291 , String -> IO ()
292 , Doc -> IO ())
293 loggers _ = (putStrLn, putStrLnError, putDocLn)
294 \end{code}