This section documents the existing hook functions and their default definitions.
Some hooks take arguments which are more complex than a simple string or number. Where multiple hooks take the same kind of argument, we generally try to make them take that kind of argument in the same format.
key_identity
{ id = "key hash/fingerprint, in hex", given_name = "name given when creating the key", name = "local alias of the key" }
There are a number of hooks that are called when noteworthy events occur, such as commits or new revisions arriving over the network. These hooks can be used to feed the events into external notification systems, such as generating email.
By default, these hooks are undefined, so no special external actions are taken.
note_commit (
new_id,
revision,
certs)
Note that since the certs table does not contain cryptographic
or trust information, and only contains one entry per cert name, it is
an incomplete source of information about the committed version. This
hook is only intended as an aid for integrating monotone with informal
commit-notification systems such as mailing lists or news services. It
should not perform any security-critical operations.
note_netsync_start (
session_id,
my_role,
sync_type,
remote_host,
remote_key,
includes,
excludes)
The other arguments are:
note_netsync_revision_received (
new_id,
revision,
certs,
session_id)
note_netsync_start
and
note_netsync_end
. If you're not interested in that type of
tracking, you can ignore that variable entirely.
note_netsync_revision_sent (
rev_id,
revision,
certs,
session_id)
note_netsync_cert_received (
rev_id,
key_identity,
name,
value,
session_id)
note_netsync_start
and
note_netsync_end
. If you're not interested in that type of
tracking, you can ignore that variable entirely.
note_netsync_cert_sent (
rev_id,
key_identity,
name,
value,
session_id)
note_netsync_pubkey_received (
key_identity,
session_id)
note_netsync_start
and
note_netsync_end
. If you're not interested in that type of
tracking, you can ignore that variable entirely.
note_netsync_pubkey_sent (
key_identity,
session_id)
note_netsync_end (
session_id,
status,
bytes_in,
bytes_out,
certs_in,
certs_out,
revs_in,
revs_out,
keys_in,
keys_out)
status is a three digit integer that tells whether there was an error, and if so what kind of error it was:
In general, 2xx means there was no error, 4xx means there was a permissions
error, and 5xx means there was a protocol error. xx1 means some data may
have been transferred, xx2 means no data was transferred, and xx0 means all
data was transferred.
note_mtn_startup (...)
function note_mtn_startup(...) print("Beginning note_mtn_startup") for i = 1,arg.n do print(arg[i]) end print("Ending note_mtn_startup") end
These are hooks that can be used to provide smart, context-sensitive default values for a number of parameters the user might otherwise be prompted for.
get_branch_key (
branchname)
get_netsync_key(
server,
include,
exclude)
There is no default definition of this hook. The command-line option
--key=keyname overrides any value returned from this
hook function.
get_default_command_options(
command)
Note that there is no way to "override" these default options via a given command-line option once they've been set. This is especially true if you specify options with arguments in this hook such as --exclude=path - no subsequent command-line argument or --exclude option argument will be able to replace or remove the already excluded path.
Simple example which enables recursive directory scanning for mtn add by default:
function get_default_command_options(command) local default_options = {} if (command[1] == "add") then table.insert(default_options, "--recursive") end return default_options end
get_passphrase (
key_identity)
get_local_key_name (
key_identity)
get_author (
branchname,
key_identity)
author
certificates when you commit changes to
branchname with the keypair identity key_identity. Generally
this hook remains undefined, and monotone selects your signing key name
for the author certificate. You can use this hook to override that
choice, if you like.
This hook has no default definition, but a couple of possible definitions might be:
function get_author(branchname, key_identity) -- Key pair identity ignored. local user = os.getenv("USER") local host = os.getenv("HOSTNAME") if ((user == nil) or (host == nil)) then return nil end return string.format("%s@%s", user, host) end
function get_author(branchname, key_identity) -- Branch name ignored. if (key_identity.given_name == "joe@example.com") then return "Joe Random <joe@example.com>" end return key_identity end
edit_comment (
commentary,
user_log_message)
changelog
certificate, automatically generated when you commit
changes.
The contents of _MTN/log are read and passed as user_log_message. This allows you to document your changes as you proceed instead of waiting until you are ready to commit. Upon a successful commit, the contents of _MTN/log are erased setting the system up for another edit/commit cycle.
For the default definition of this hook, see Default hooks.
persist_phrase_ok ()
true
if you want monotone to remember the passphrase of
a private key for the duration of a single command, or false
if
you want monotone to prompt you for a passphrase for each certificate
it generates. Since monotone often generates several certificates in
quick succession, unless you are very concerned about security you
probably want this hook to return true
.
The default definition of this hook is:
function persist_phrase_ok() return true end
use_inodeprints ()
true
if you want monotone to automatically enable
Inodeprints support in all workspaces. Only affects working
copies created after you modify the hook.
The default definition of this hook is:
function use_inodeprints() return false end
ignore_file (
filename)
true
if filename should be ignored while adding,
dropping, or moving files. Otherwise returns false
. This is
most important when performing recursive actions on directories, which
may affect multiple files simultaneously.
The default definition of this hook recognises a number of common file
types and extensions for temporary and generated file types that users
typically don't want to track. If the file .mtn-ignore exists,
this hook will read a list of regular expressions from the file, one per
line, and ignore all files matching one of these expressions. For the
default definition of this hook, see Default hooks.
ignore_branch (
branchname)
true
if branchname should be ignored while listing
branches. Otherwise returns false
. This hook has no default
definition, therefore the default behavior is to list all branches.
get_date_format_spec (
wanted)
strftime
format specification, which mtn
log and similar commands will use to format dates, unless instructed
otherwise. The default definition returns ‘%x’ for long and short
date formats, ‘%X’ for long and short time formats and ‘%x %X’
for long and short date time formats, which is equivalent to ‘22/05/09’,
‘09:06:14’ and ‘22/05/09 09:06:14’ in an English locale.
wanted can be one of ‘date_long’, ‘date_short’, ‘time_long’, ‘time_short’, ‘date_time_long’ and ‘date_time_short’, though only ‘date_short’ and ‘date_time_short’ are currently used.
These hooks are used when running a netsync server, via mtn serve. They are evaluated by the server for each new connection, based on the certificate used for authentication by the client. Note that a long-running server will need to be restarted in order to reload the hook definitions if the montonerc file is changed.
get_netsync_read_permitted (
branch,
key_identity)
true
if a peer authenticated as key key_identity
should be allowed to read from your database certs, revisions,
manifests, and files associated with branch; otherwise false
.
The default definition of this hook reads a file read-permissions in
the configuration directory. This file looks like
pattern "net.example.project.{private,security}*" allow "joe@example.net" allow "f3f62f86eba204a3ce15174083a53349201993d6" comment "everyone can read these branches" pattern "net.example.{public,project}*" allow "*"
This example allows everyone access to branches net.example.project
and
net.example.public
and their sub-branches, except for the branches in
net.example.project.security
and net.example.project.private
,
which are only readable by Joe and Jim.
The file is divided into stanzas of one pattern
line followed by any
number of allow
and deny
lines, and possibly a continue
line. Anything from the unquoted word comment
until the next unquoted
word is ignored. A stanza is processed if the argument to
pattern
is a glob that matches branch. Any keys with a hash or
local_name that matches an
allow
line are given access, and any keys which match a deny
line
are denied access. If there is a continue "true"
line, then if the key
is not granted or denied access in this stanza the next matching stanza will be
processed. If there is not a continue "true"
line, then any key which
has not been given access will be denied access even if it doesn't match any
deny
lines. Thus, deny lines are redundant unless there is also a
continue "true"
line.
If a client connects anonymously, this hook will be called with a
key_identity of nil
.
get_netsync_write_permitted (
key_identity)
true
if a peer authenticated as key key_identity should
be allowed to write into your database certs, revisions, manifests, and
files; otherwise false
. The default definition of this hook reads a file
write-permissions in the configuration directory which contains a list
of key hashes or local key names, one per line, which are allowed write access.
The special value
*
means to allow access to anyone whose public key we already have.
If a client connects anonymously, it will be unconditionally denied
write access; this hook will not be called with a key_identity
of nil
.
Note also that, unlike the equivalent read permission hook, the write
permission hook does not take a branch name as an argument. There
is presently no way to selectively grant write access to different
branches via netsync, for a number of reasons. Contributions in the
database from different authors can be selectively trusted using the
Trust Evaluation Hooks instead.
get_remote_automate_permitted(
key_identity,
command,
options)
automate stdio
.
When a monotone client initiates a netsync connection, these hooks are called to attempt to parse the host argument provided on the command line. If the hooks fail or return nil, monotone will interpret the host argument as a network name (possibly with a port number) and open a TCP socket.
get_netsync_connect_command (
uri,
args)
uri["scheme"]
, such as "ssh"
or "file"
uri["user"]
, the name of a remote user
uri["host"]
, the name or address of a remote host
uri["port"]
, a network port number
uri["path"]
, a filesystem path
uri["query"]
, for additional parameters
uri["fragment"]
, to describe a sub-location within the remote resource
The args argument is a table containing between 0 and 3 components:
args["include"]
, the branch pattern to include
args["exclude"]
, the branch pattern to exclude
args["debug"]
, whether to run the connection in debug mode
The default definition of this hook follows:
function get_netsync_connect_command(uri, args) local argv = nil if uri["scheme"] == "ssh" and uri["host"] and uri["path"] then argv = { "ssh" } if uri["user"] then table.insert(argv, "-l") table.insert(argv, uri["user"]) end if uri["port"] then table.insert(argv, "-p") table.insert(argv, uri["port"]) end table.insert(argv, uri["host"]) end if uri["scheme"] == "file" and uri["path"] then argv = { } end if argv then table.insert(argv, get_mtn_command(uri["host"])) if args["debug"] then table.insert(argv, "--debug") else table.insert(argv, "--quiet") end table.insert(argv, "--db") table.insert(argv, uri["path"]) table.insert(argv, "serve") table.insert(argv, "--stdio") table.insert(argv, "--no-transport-auth") if args["include"] then table.insert(argv, args["include"]) end if args["exclude"] then table.insert(argv, "--exclude") table.insert(argv, args["exclude"]) end end return argv end
use_transport_auth (
uri)
true
. The form of
the uri argument is a table, identical to the table provided as
an argument to get_netsync_connect_command
.
Note that the return value of this hook must "match" the semantics of
the command returned by get_netsync_connect_command
. In
particular, if this hook returns false
, the serve
command line arguments passed to the remote end of the connection
should include the --no-transport-auth option. A mismatch
between this hook's return value and the command line returned by
get_netsync_connect_command
will cause a communication failure,
as the local and remote monotone processes will have mismatched
authentication assumptions.
function use_transport_auth(uri) if uri["scheme"] == "ssh" or uri["scheme"] == "file" then return false else return true end end
get_mtn_command(
host)
function get_mtn_command(host) return "mtn" end
Monotone makes heavy use of certs to provide descriptive information about revisions. In many projects, not all developers should have the same privileges, or be trusted for the same purposes (indeed, some signers might be automated robots, with very specific purposes).
These hooks allow the user to configure which signers will be trusted to make which kinds of assertions using certs. Monotone uses these certs when selecting available revisions for commands such as update.
Each user, or even each workspace, can have their own implementation of these hooks, and thus a different filtered view of valid revisions, according to their own preferences and purposes.
get_revision_cert_trust (
signers,
id,
name,
val)
The default definition of this hook simply returns true
, which
corresponds to a form of trust where every key which is defined in
your database is trusted. This is a weak trust setting; you
should change it to something stronger. A possible example of a
stronger trust function (along with a utility function for computing
the intersection of tables) is the following:
function intersection(a,b) local s={} local t={} for k,v in pairs(a) do s[v.name] = 1 end for k,v in pairs(b) do if s[v] ~= nil then table.insert(t,v) end end return t end function get_revision_cert_trust(signers, id, name, val) local trusted_signers = { "bob@happyplace.example.com", "friend@trustedplace.example.com", "myself@home.example.com" } local t = intersection(signers, trusted_signers) if t == nil then return false end if (name ~= "branch" and table.getn(t) >= 1) or (name == "branch" and table.getn(t) >= 2) then return true else return false end end
In this example, any revision certificate is trusted if it is signed
by at least one of three “trusted” keys, unless it is an
branch
certificate, in which case it must be signed by
two or more trusted keys. This is one way of requiring that
the revision has been approved by an extra “reviewer” who used the
approve command.
accept_testresult_change (
old_results,
new_results)
true
if you consider an update from the
version carrying the old_results to the version carrying the
new_results to be acceptable.
The default definition of this hook follows:
function accept_testresult_change(old_results, new_results) for test,res in pairs(old_results) do if res == true and new_results[test] ~= true then return false end end return true end
This definition accepts only those updates which preserve the set of
true
test results from update source to target. If no test
results exist, this hook has no affect; but once a true
test
result is present, future updates will require it. If you want a more
lenient behavior you must redefine this hook.
Differences between files can be shown in a number of ways, varying according to user preference and file type. These hooks allow customisation of the way file differences are shown.
get_encloser_pattern (
file_path)
^[[:alnum:]$_]
, which is correct for many programming
languages; a few text authoring packages, like Texinfo, have special
regular expressions that match their particular syntax. If you have a
better regular expression for some language, you can add it to this
hook; and if you send it to the monotone developers, we will likely
make it the default for that language. See Regexps, for the
regular expression syntax.
external_diff (
file_path,
old_data,
new_data,
is_binary,
diff_args,
old_rev,
new_rev)
If an extra arguments are given via --diff-args, the string will be passed in as diff_args. Otherwise diff_args will be nil.
The default implementation of this hook calls the program diff,
and if --diff-args were not passed, takes default arguments
from the Lua variable external_diff_default_args
. You can
override this variable in your configuration file, without overriding
the whole hook.
Monotone often needs to merge together the work of multiple distributed developers, and uses these hooks to help this process when the merge does not automatically succeed. Often these hooks will be used to invoke an external interactive merge tool.
The Default hooks include helper functions used by the hooks below to invoke a number of external merge tools known to monotone, and you can override or extend these hooks if you have a preferred tool, or if you have a tool specific to certain file types.
merge3 (
ancestor_path,
left_path,
right_path,
merged_path,
ancestor_text,
left_text,
right_text)
Returns a string, which should be the merger of the given texts. The
default definition of this hook delegates the actual merge to the
result of get_preferred_merge3_command. The default definition
of get_preferred_merge3_command checks to see if the
MTN_MERGE environment variable, or the Lua variable
merger
are set to the name of a merge tool that it recognizes,
and if not, then simply searches for whatever is installed on the
local system. For details, see the code in Default hooks.
get_preferred_merge3_command(
tbl)
Monotone's selectors are a powerful mechanism used to refer to revisions with symbolic names or groupings. Thanks to the hooks described in this section, it is possible to use various forms of shorthand in selection strings; these hooks are designed to recognise shorthand patterns and expand them to their full form.
For more detail on the use of selectors, see Selectors.
expand_selector (
str)
a:
for authors
or d:
for dates. This hook is called once for each element of a
combined selector string (between /
separators) prior to
evaluation of the selector. For the default definition of this hook, see
Default hooks.
expand_date (
str)
yesterday
or
6 months ago
and converting them into well formed date
expressions. For the default definition of this hook, see Default hooks.
Some files in a project are special; they may require different handling (such as binary or structured files that should always be manually merged – see Merging), or they may represent executable scripts or programs.
Monotone allows each file (or directory) in a repository to carry arbitrary File Attributes. Persistent attributes are stored in each revision's manifest. The hooks in this section allow files to be automatically recognised as having certain attributes at the time they're added, and for custom triggers to be invoked on each file according to its attributes when the workspace is changed.
attr_functions [
attribute] (
filename,
value)
attr_functions
, at table
entry attribute, is a function taking a file name filename
and an attribute value value. The function should “apply” the
attribute to the file, possibly in a platform-specific way. When
called to set an attribute the value this hook receives will be a
string representing the value of the attribute. When called to clear
an attribute the value this hook receives will be nil
.
Hook functions from this table are called for each existing attribute, after any command which modifies the workspace. These functions are also called during creation and modification of a workspace by the update, merge_into_workspace, pluck, clone and checkout commands to set or clear attributes as they change.
This facility can be used to extend monotone's understanding of files with platform-specific attributes, such as permission bits, access control lists, or special file types.
By default, there is only one entry in this table, for the mtn:execute
attribute. Its definition is:
attr_functions["mtn:execute"] = function(filename, value) if (value == "true") then set_executable(filename) else clear_executable(filename) end end
attr_init_functions [
attribute] (
filename)
attr_init_functions
, at
table entry attribute, is a function taking a file (or
directory) name filename. Each function defines the attributes
that should be set on the file named filename. This table of
hook functions is called once for each file during an add.
By default, there are only two entries in this table, for the
mtn:execute
and mtn:manual_merge
attributes. Their
definition is:
attr_init_functions["mtn:execute"] = function(filename) if (is_executable(filename)) then return "true" else return nil end end attr_init_functions["mtn:manual_merge"] = function(filename) if (binary_file(filename)) then return "true" -- binary files must be merged manually else return nil end end
The binary_file
function is also defined as a Lua hook. See
Default hooks.
Exporting monotone revisions in git-fast-import(1) format often requires translation of monotone author cert values and associated signing keys into corresponding git author and committer values. Translation of author and committer values and validation of the results is controlled by these hooks. See Default hooks.
unmapped_git_author(
author)
validate_git_author(
author)
unmapped_git_author
hook. This hook may return
true if the author is valid or false if it is not. The export will be
aborted if this hook returns false for any value.
If there is a policy decision to make, Monotone defines certain hooks to allow a client to validate or reject certain behaviors.
validate_commit_message (
message,
revision_text,
branchname)
true,
""
. If it finds fault, then it can return false, reason
where
reason is the reason the message was rejected. By default, this hook
rejects empty log messages.
Monotone allows the execution of arbitrary Lua hooks and functions through a special generalized "meta hook". See automate lua for more information.
hook_wrapper (
func_name,
...)