The unified diff between revisions [869f0c37..] and [e24ccc23..] is displayed below. It can also be downloaded as a raw diff.

This diff has been restricted to the following files: 'monotone.texi'

#
#
# patch "monotone.texi"
#  from [28008d0dc7e6abd7e2e40cab143add9c4faecbca]
#    to [131933a2c2cd95c13bf8e3b8c988b8e4bc97664d]
#
============================================================
--- monotone.texi	28008d0dc7e6abd7e2e40cab143add9c4faecbca
+++ monotone.texi	131933a2c2cd95c13bf8e3b8c988b8e4bc97664d
@@ -77,6 +77,7 @@ @top Top
 * Hook Reference::      Functions which extend monotone
 * Special Topics::      Extra explanations and details
 * Man Page::            That other document
+* Default hooks::       The standard hook definitions
 * Index::               Index of concepts and functions
 @end menu

@@ -5280,10 +5281,27 @@ @chapter Hook Reference
 using the @option{--rcfile=@var{file}} option; hooks defined in files
 specified on the command-line will shadow hooks from the the automatic
 files.
+By specifying @option{--rcfile=@var{directory}} you can automatically
+load all the files contained into @var{directory}.

-The remainder of this section documents the existing hook functions
-and their default definitions.
+Monotone also makes available to hook writers a number of helper
+functions exposing functionality not available with standard lua.

+For the complete source of the default hooks see @ref{Default
+hooks}.
+
+@menu
+* Hooks::                     All hooks called by monotone.
+* Additional Lua Functions::  Extra functionality availabe to hook writers.
+@end menu
+
+@page
+@node   Hooks
+@section Hooks
+
+This section documents the existing hook functions and their default
+definitions.
+
 @ftable @code
 @item note_commit (@var{new_id}, @var{certs})

@@ -5380,46 +5398,8 @@ @chapter Hook Reference
 a successful commit, the contents of @file{MT/log} are erased setting
 the system up for another edit/commit cycle.

-The default definition of this hook is:
+For the default definition of this hook, see @ref{Default hooks}.

-@smallexample
-@group
-function edit_comment(commentary, user_log_message)
-        local exe = "vi"
-        local visual = os.getenv("VISUAL")
-        if (visual ~= nil) then exe = visual end
-        local editor = os.getenv("EDITOR")
-        if (editor ~= nil) then exe = editor end
-
-        local tmp, tname = temp_file()
-        if (tmp == nil) then return nil end
-        commentary = "MT: " .. string.gsub(commentary, "\n", "\nMT: ")
-        tmp:write(user_log_message)
-        tmp:write(commentary)
-        io.close(tmp)
-
-        if (os.execute(string.format("%s %s", exe, tname)) ~= 0) then
-                os.remove(tname)
-                return nil
-        end
-
-        tmp = io.open(tname, "r")
-        if (tmp == nil) then os.remove(tname); return nil end
-        local res = ""
-        local line = tmp:read()
-        while(line ~= nil) do
-                if (not string.find(line, "^MT:")) then
-                        res = res .. line .. "\n"
-                end
-                line = tmp:read()
-        end
-        io.close(tmp)
-        os.remove(tname)
-        return res
-end
-@end group
-@end smallexample
-
 @item persist_phrase_ok ()

 Returns @code{true} if you want monotone to remember the passphrase of
@@ -5520,34 +5500,9 @@ @chapter Hook Reference
 Returns @code{true} if @var{filename} should be ignored while adding,
 dropping, or moving files. Otherwise returns @code{false}. This is
 most important when performing recursive actions on directories, which
-may affect multiple files simultaneously. The default definition of
-this hook is:
+may affect multiple files simultaneously.
+For the default definition of this hook, see @ref{Default hooks}.

-@smallexample
-@group
-function ignore_file(name)
-   if (string.find(name, "%.a$")) then return true end
-   if (string.find(name, "%.so$")) then return true end
-   if (string.find(name, "%.o$")) then return true end
-   if (string.find(name, "%.la$")) then return true end
-   if (string.find(name, "%.lo$")) then return true end
-   if (string.find(name, "%.aux$")) then return true end
-   if (string.find(name, "%.bak$")) then return true end
-   if (string.find(name, "%.orig$")) then return true end
-   if (string.find(name, "%.rej$")) then return true end
-   if (string.find(name, "%~$")) then return true end
-   if (string.find(name, "/core$")) then return true end
-   if (string.find(name, "^CVS/")) then return true end
-   if (string.find(name, "/CVS/")) then return true end
-   if (string.find(name, "^%.svn/")) then return true end
-   if (string.find(name, "/%.svn/")) then return true end
-   if (string.find(name, "^SCCS/")) then return true end
-   if (string.find(name, "/SCCS/")) then return true end
-   return false;
-end
-@end group
-@end smallexample
-
 @item ignore_branch (@var{branchname})

 Returns @code{true} if @var{branchname} should be ignored while listing
@@ -5646,61 +5601,10 @@ @chapter Hook Reference
 strings, which are the contents of the @var{left} and @var{right}
 nodes of a file fork which monotone was unable to automatically
 merge. The merge should either call an intelligent merge program or
-interact with the user. The default definition of this hook is:
+interact with the user.
+For the default definition of this hook, see @ref{Default hooks}.

-@smallexample
-@group

-function merge2 (left_path, right_path, merged_path, left, right)
-   local ret = nil
-   local tbl = @{@}
-
-   tbl.lfile = nil
-   tbl.rfile = nil
-   tbl.outfile = nil
-   tbl.meld_exists = false
-
-   tbl.lfile = write_to_temporary_file (left)
-   tbl.rfile = write_to_temporary_file (right)
-   tbl.outfile = write_to_temporary_file ("")
-
-   if tbl.lfile ~= nil and tbl.rfile ~= nil and tbl.outfile ~= nil
-   then
-      tbl.left_path = left_path
-      tbl.right_path = right_path
-      tbl.merged_path = merged_path
-
-      local cmd = get_preferred_merge2_command (tbl)
-
-      if cmd ~=nil
-      then
-         io.write (
-					string.format("executing external 2-way merge command\n"))
-         cmd ()
-         if tbl.meld_exists
-         then
-            ret = read_contents_of_file (tbl.lfile)
-         else
-            ret = read_contents_of_file (tbl.outfile)
-         end
-         if string.len (ret) == 0
-         then
-            ret = nil
-         end
-      else
-         io.write ("no external 2-way merge command found\n")
-      end
-   end
-
-   os.remove (tbl.lfile)
-   os.remove (tbl.rfile)
-   os.remove (tbl.outfile)
-
-   return ret
-end
-@end group
-@end smallexample
-
 @anchor{get_preferred_merge2_command}
 @item get_preferred_merge2_command(@var{tbl})

@@ -5710,58 +5614,7 @@ @chapter Hook Reference
 that you would like to use to perform merge2 operations, override
 this hook to specify it.

-@smallexample
-@group

-function get_preferred_merge2_command (tbl)
-   local cmd = nil
-   local left_path = tbl.left_path
-   local right_path = tbl.right_path
-   local merged_path = tbl.merged_path
-   local lfile = tbl.lfile
-   local rfile = tbl.rfile
-   local outfile = tbl.outfile
-
-   local editor = string.lower(os.getenv("EDITOR"))
-
-
-   if program_exists_in_path("kdiff3") then
-      cmd =   merge2_kdiff3_cmd (left_path, right_path, merged_path,
-								 lfile, rfile, outfile)
-   elseif program_exists_in_path ("meld") then
-      tbl.meld_exists = true
-      io.write (string.format(
-			"\nWARNING: 'meld' was choosen to perform external 2-way merge.\n"..
-      "You should merge all changes to *LEFT* file due to limitation of program\n"..
-      "arguments.\n\n"))
-      cmd = merge2_meld_cmd (lfile, rfile)
-   elseif program_exists_in_path ("xxdiff") then
-      cmd = merge2_xxdiff_cmd (left_path, right_path, merged_path,
-							lfile, rfile, outfile)
-   else
-     if string.find(editor, "emacs") ~= nil
-				or string.find(editor, "gnu") ~= nil
-		 then
-       if program_exists_in_path ("emacs") then
-          cmd = merge2_emacs_cmd ("emacs", lfile, rfile, outfile)
-       elseif program_exists_in_path ("xemacs") then
-          cmd = merge2_emacs_cmd ("xemacs", lfile, rfile, outfile)
-       end
-     else if string.find(editor, "vim") ~= nil then
-       if os.getenv ("DISPLAY") ~= nil
-					and program_exists_in_path ("gvim")
-			 then
-          cmd = merge2_vim_cmd ("gvim", lfile, rfile, outfile)
-       elseif program_exists_in_path ("vim") then
-          cmd = merge2_vim_cmd ("vim", lfile, rfile, outfile)
-       end
-     end
-   end
-   return cmd
-end
-@end group
-@end smallexample
-
 @anchor{merge3}
 @item merge3 (@var{ancestor}, @var{left}, @var{right})

@@ -5769,65 +5622,10 @@ @chapter Hook Reference
 strings, which are the contents of @var{left} and @var{right} nodes,
 and least common @var{ancestor}, of a file fork which monotone was
 unable to automatically merge. This hook delegates the actual merge
-to the result of @ref{get_preferred_merge3_command}. The default
-definition of this hook is:
+to the result of @ref{get_preferred_merge3_command}.
+For the default definition of this hook, see @ref{Default hooks}.

-@smallexample
-@group
-function merge3 (anc_path, left_path, right_path, merged_path,
-								 ancestor, left, right)
-   local ret
-   local tbl = @{@}
-
-   tbl.anc_path = anc_path
-   tbl.left_path = left_path
-   tbl.right_path = right_path

-   tbl.merged_path = merged_path
-   tbl.afile = nil
-   tbl.lfile = nil
-   tbl.rfile = nil
-   tbl.outfile = nil
-   tbl.meld_exists = false
-   tbl.lfile = write_to_temporary_file (left)
-   tbl.afile =   write_to_temporary_file (ancestor)
-   tbl.rfile =   write_to_temporary_file (right)
-   tbl.outfile = write_to_temporary_file ("")
-
-   if tbl.lfile ~= nil and tbl.rfile ~= nil
-			and tbl.afile ~= nil and tbl.outfile ~= nil
-   then
-      local cmd =   get_preferred_merge3_command (tbl)
-      if cmd ~=nil
-      then
-         io.write (string.format(
-						"executing external 3-way merge command\n"))
-         cmd ()
-         if tbl.meld_exists
-         then
-            ret = read_contents_of_file (tbl.afile)
-         else
-            ret = read_contents_of_file (tbl.outfile)
-         end
-         if string.len (ret) == 0
-         then
-            ret = nil
-         end
-      else
-         io.write ("no external 3-way merge command found\n")
-      end
-   end
-
-   os.remove (tbl.lfile)
-   os.remove (tbl.rfile)
-   os.remove (tbl.afile)
-   os.remove (tbl.outfile)
-
-   return ret
-end
-@end group
-@end smallexample
-
 @anchor{get_preferred_merge3_command}
 @item get_preferred_merge3_command(@var{tbl})

@@ -5837,65 +5635,6 @@ @chapter Hook Reference
 that you would like to use to perform merge3 operations, override
 this hook to specify it.

-@smallexample
-@group
-function get_preferred_merge3_command (tbl)
-   local cmd = nil
-   local left_path = tbl.left_path
-   local anc_path = tbl.anc_path
-   local right_path = tbl.right_path
-   local merged_path = tbl.merged_path
-   local lfile = tbl.lfile
-   local afile = tbl.afile
-   local rfile = tbl.rfile
-   local outfile = tbl.outfile
-
-   local editor = string.lower(os.getenv("EDITOR"))
-
-   if program_exists_in_path("kdiff3") then
-      cmd = merge3_kdiff3_cmd (left_path, anc_path, right_path,
-								merged_path, lfile, afile, rfile, outfile)
-   elseif program_exists_in_path ("meld") then
-      tbl.meld_exists = true
-      io.write (string.format(
-					"\nWARNING: 'meld' was choosen to perform external 3-way merge.\n"..
-          "You should merge all changes to *CENTER* file due to limitation of program\n"..
-          "arguments.\n\n"))
-      cmd = merge3_meld_cmd (lfile, afile, rfile)
-   elseif program_exists_in_path ("xxdiff") then
-      cmd = merge3_xxdiff_cmd (left_path, anc_path, right_path,
-								merged_path, lfile, afile, rfile, outfile)
-   else
-     -- prefer emacs/xemacs
-     if string.find(editor, "emacs") ~= nil
-				or string.find(editor, "gnu") ~= nil
-		 then
-       if program_exists_in_path ("xemacs") then
-          cmd = merge3_emacs_cmd ("xemacs", lfile, afile,
-									rfile, outfile)
-       elseif program_exists_in_path ("emacs") then
-          cmd = merge3_emacs_cmd ("emacs", lfile, afile,
-									rfile, outfile)
-       end
-     elseif string.find(editor, "vim") ~= nil then  -- prefer vim
-       if os.getenv ("DISPLAY") ~= nil
-					and program_exists_in_path ("gvim")
-			 then
-          cmd = merge3_vim_cmd ("gvim", lfile, afile,
-									rfile, outfile)
-       elseif program_exists_in_path ("vim") then
-          cmd = merge3_vim_cmd ("vim", lfile, afile,
-									rfile, outfile)
-       end
-     end
-   end
-
-   return cmd
-end
-@end group
-@end smallexample
-
-
 @item expand_selector (@var{str})

 Attempts to expand @var{str} as a selector. Expansion generally means
@@ -5903,115 +5642,18 @@ @chapter Hook Reference
 authors or @code{d:} for dates. Expansion may also mean recognizing
 and interpreting special words such as @code{yesterday} or @code{6
 months ago} and converting them into well formed selectors. For more
-detail on the use of selectors, see @ref{Selectors}. The default
-definition of this hook is:
+detail on the use of selectors, see @ref{Selectors}.
+For the default definition of this hook, see @ref{Default hooks}.

-@smallexample
-@group
-function expand_selector(str)
-
-   -- something which looks like a generic cert pattern
-   if string.find(str, "^[^=]*=.*$")
-   then
-      return ("c:" .. str)
-   end
-
-   -- something which looks like an email address
-   if string.find(str, "[%w%-_]+@@[%w%-_]+")
-   then
-      return ("a:" .. str)
-   end
-
-   -- something which looks like a branch name
-   if string.find(str, "[%w%-]+%.[%w%-]+")
-   then
-      return ("b:" .. str)
-   end
-
-   -- a sequence of nothing but hex digits
-   if string.find(str, "^%x+$")
-   then
-      return ("i:" .. str)
-   end
-
-   -- tries to expand as a date
-   local dtstr = expand_date(str)
-   if  dtstr ~= nil
-   then
-      return ("d:" .. dtstr)
-   end
-
-   return nil
-end
-@end group
-@end smallexample
-
 @item expand_date (@var{str})

 Attempts to expand @var{str} as a date expression. Expansion means recognizing
 and interpreting special words such as @code{yesterday} or @code{6
 months ago} and converting them into well formed date expressions. For more
-detail on the use of selectors, see @ref{Selectors}. The default
-definition of this hook is:
+detail on the use of selectors, see @ref{Selectors}.
+For the default definition of this hook, see @ref{Default hooks}.

-@smallexample
-@group
-function expand_date(str)
-   -- simple date patterns
-   if string.find(str, "^19%d%d%-%d%d")
-      or string.find(str, "^20%d%d%-%d%d")
-   then
-      return (str)
-   end

-   -- "now"
-   if str == "now"
-   then
-      local t = os.time(os.date('!*t'))
-      return os.date("%FT%T", t)
-   end
-
-    -- today don't uses the time
-   if str == "today"
-   then
-      local t = os.time(os.date('!*t'))
-      return os.date("%F", t)
-   end
-
-   -- "yesterday", the source of all hangovers
-   if str == "yesterday"
-   then
-      local t = os.time(os.date('!*t'))
-      return os.date("%F", t - 86400)
-   end
-
-   -- "CVS style" relative dates such as "3 weeks ago"
-   local trans = @{
-      minute = 60;
-      hour = 3600;
-      day = 86400;
-      week = 604800;
-      month = 2678400;
-      year = 31536000
-   @}
-   local pos, len, n, type = string.find(str, "(%d+) ([minutehordaywk]+)s? ago")
-   if trans[type] ~= nil
-   then
-      local t = os.time(os.date('!*t'))
-      if trans[type] <= 3600
-      then
-	return os.date("%FT%T", t - (n * trans[type]))
-      else
-	return os.date("%F", t - (n * trans[type]))
-      end
-   end
-
-   return nil
-end
-@end group
-@end smallexample
-
-
 @item get_system_linesep ()

 Returns a string which defines the default system line separator.
@@ -6133,41 +5775,124 @@ @chapter Hook Reference
 @end group
 @end smallexample

-The @code{binary_file} function is also defined as a lua hook as
-follows:
-
+The @code{binary_file} function is also defined as a lua hook. See
+@ref{Default hooks}.
+
+@end ftable
+
+@page
+@node   Additional Lua Functions
+@section Additional Lua Functions
+
+This section documents the additional lua functions made available to
+hook writers.
+
+@ftable @code
+
+@item existonpath(@var{possible_command})
+
+This function receives a string containing the name of an external
+program and returns 0 if it exists on path and is executable, -1
+otherwise.
+As an example, @code{existonpath("xxdiff")} returns 0 if the
+program xxdiff is available.
+On windows, this function automatically appends ``.exe'' to the
+program name. In the previous example, @code{existonpath} would search
+for ``xxdiff.exe''.
+
+@item guess_binary(@var{filespec})
+
+Returns true if the file appears to be binary, i.e. contains one or
+more of the following characters:
 @smallexample
 @group
-function binary_file(name)
-   local lowname=string.lower(name)
-   -- some known binaries, return true
-   if (string.find(lowname, "%.gif$")) then return true end
-   if (string.find(lowname, "%.jpe?g$")) then return true end
-   if (string.find(lowname, "%.png$")) then return true end
-   if (string.find(lowname, "%.bz2$")) then return true end
-   if (string.find(lowname, "%.gz$")) then return true end
-   if (string.find(lowname, "%.zip$")) then return true end
-   -- some known text, return false
-   if (string.find(lowname, "%.cc?$")) then return false end
-   if (string.find(lowname, "%.cxx$")) then return false end
-   if (string.find(lowname, "%.hh?$")) then return false end
-   if (string.find(lowname, "%.hxx$")) then return false end
-   if (string.find(lowname, "%.lua$")) then return false end
-   if (string.find(lowname, "%.texi$")) then return false end
-   if (string.find(lowname, "%.sql$")) then return false end
-   -- unknown - read file and use the guess-binary built-in
-   -- monotone function
-   filedata=read_contents_of_file(name)
-   if (filedata ~= nil) then return guess_binary(filedata) end
-   -- if still unknown, treat as binary
-   return true
-end
+0x00 thru 0x06
+0x0E thru 0x1a
+0x1c thru 0x1f
 @end group
 @end smallexample

+@item include(@var{scriptfile})

+This function tries to load and execute the script contained into
+scriptfile.  It returns true for success and false if there is an
+error.
+
+@item includedir(@var{scriptpath})
+
+This function loads and executes in alphabetical order all the scripts
+contained into the directory scriptpath.
+If one of the scripts has an error, the functions doesn't process the
+remaining scripts and immediately returns false.
+
+@item is_executable(@var{filespec})
+
+This function returns true if the file is executable, false
+otherwise.  On windows this function returns always false.
+
+@item kill(@var{pid} [, @var{signal}])
+
+This function calls the kill() C library function on posix systems and
+TerminateProcess on Win32 (in that case @var{pid} is the process
+handle).  If the optional @var{signal} parameter is missing, SIGTERM
+will be used.
+Returns 0 on succes, -1 on error.
+
+@item make_executable(@var{filespec})
+
+This function marks the named file as executable.  On windows has no
+effect.
+
+@item mkstemp(@var{template})
+
+Like its C library counterpart,  mkstemp creates a unique name and
+returns a file descriptor for the newly created file.
+The value of template should be a pointer to a character buffer loaded
+with a null-terminated string that consists of contiguous, legal file
+ad path name characters followed by six Xs.
+The function mkstemp replaces the Xs by an alpha-numeric sequence
+that is chosen to ensure that no file in the chosen directory has that
+name.
+Furthermore, subsequent calls to mkstemp within the same process
+each yield different file names.
+Unlike other implementations, monotone mkstemp allows the template
+string to contain a complete path, not only a filename, allowing users
+to create temporary files outside the current directory.
+
+@strong{Important notice:}@*
+To create a temporary file, you must use the @code{temp_file()}
+function, unless you need to run monotone with the @option{--nostd}
+option.  @code{temp_file()} builds on @code{mkstemp()} and creates a
+file in the standard TMP/TEMP directories.
+For the definition of @code{temp_file()}, see @ref{Default hooks}.
+
+@item sleep(@var{seconds})
+
+Makes the calling process sleep for the specified number of seconds.
+
+@item spawn(@var{executable} [, @var{args ...}])
+
+Starts the named executable with the given arguments.  Returns the
+process pid on Posix systems, the process handle on Win32 or -1 if
+there was an error.
+Calls fork/execvp on Posix, CreateProcess on Win32.
+
+@strong{Important notice:}@*
+To spawn a process and wait for its completion, use the @code{execute()}
+function, unless you need to run monotone with the @option{--nostd}
+option.  @code{execute()} builds on @code{spawn()} and @code{wait()}
+in a standardized way.
+
+@item wait(@var{pid})
+
+Wait until the process with given pid (process handle on Win32) exits.
+Returns two values: a result value and the exit code of the waited-for
+process.
+The exit code is meaningful only if the result value is 0.
+
 @end ftable

+
 @node    Special Topics
 @chapter Special Topics

@@ -7240,6 +6965,16 @@ @section AUTHOR

 graydon hoare <graydon@@pobox.com>

+@node Default hooks
+@appendix Default hooks
+
+This section contains the entire source code of the standard hook file,
+that is built in to the monotone executable, and read before any user
+hooks files (unless @option{--nostd} is passed).  It contains the
+default values for all hooks.
+
+@verbatiminclude std_hooks.lua
+
 @node Index
 @unnumbered Index