This is monotone.info, produced by makeinfo version 4.13 from
monotone.texi.

INFO-DIR-SECTION Programming
START-INFO-DIR-ENTRY
* monotone: (monotone).         Monotone version control system
END-INFO-DIR-ENTRY


File: monotone.info,  Node: Automation,  Next: RCS,  Prev: Database,  Up: Command Reference

5.9 Automation
==============

This section contains subcommands of the `mtn automate' command, used
for scripting monotone.  All give output on `stdout'; they may also
give useful chatter on `stderr', including warnings and error messages.

`mtn automate interface_version'

    *Arguments:*
          None.

    *Added in:*
          0.0

    *Purpose:*
          Prints version of the automation interface.  Major number
          increments whenever a backwards incompatible change is made
          to the `automate' command; minor number increments whenever
          any change is made (but is reset when major number
          increments).

    *Sample output:*
          1.2

    *Output format:*
          A decimal number, followed by "." (full stop/period),
          followed by a decimal number, followed by a newline, followed
          by end-of-file.  The first decimal number is the major
          version, the second is the minor version.

    *Error conditions:*
          None.


`mtn automate heads [BRANCH]'

    *Arguments:*
          One branch name,  BRANCH. If none is given, the current
          default branch is used.

    *Added in:*
          0.0

    *Purpose:*
          Prints the heads of branch BRANCH.

    *Sample output:*
          28ce076c69eadb9b1ca7bdf9d40ce95fe2f29b61
          75156724e0e2e3245838f356ec373c50fa469f1f

    *Output format:*
          Zero or more lines, each giving the ID of one head of the
          given branch.  Each line consists of a revision ID, in
          hexadecimal, followed by a newline.  The lines are printed in
          alphabetically sorted order.

    *Error conditions:*
          If the given branch contains no members or does not exist,
          then no lines are printed.


`mtn automate ancestors REV1 [REV2 [...]]'

    *Arguments:*
          One or more revision IDs, REV1, REV2, etc.

    *Added in:*
          0.2

    *Purpose:*
          Prints the ancestors of one or more revisions.

    *Sample output:*
          28ce076c69eadb9b1ca7bdf9d40ce95fe2f29b61
          75156724e0e2e3245838f356ec373c50fa469f1f

    *Output format:*
          Zero or more lines, each giving the ID of one ancestor of the
          given revisions.  Each line consists of a revision ID, in
          hexadecimal, followed by a newline.  The lines are printed in
          alphabetically sorted order.

          The output does not include REV1, REV2, etc., except if REV2
          is itself an ancestor of REV1, then REV2 will be included in
          the output.

    *Error conditions:*
          If any of the revisions do not exist, prints nothing to
          stdout, prints an error message to stderr, and exits with
          status 1.


`mtn automate common_ancestors REV1 [REV2 [...]]'

    *Arguments:*
          One or more revision IDs, REV1, REV2, etc.

    *Added in:*
          2.1

    *Purpose:*
          Prints all revisions which are ancestors of all of the
          revisions given as arguments.

    *Sample output:*
          28ce076c69eadb9b1ca7bdf9d40ce95fe2f29b61
          75156724e0e2e3245838f356ec373c50fa469f1f

    *Output format:*
          Zero or more lines, each giving the ID of one common ancestor
          of all the given revisions.  Each line consists of a revision
          ID, in hexadecimal, followed by a newline.  The lines are
          printed in alphabetically sorted order.

          The output will include one of the argument revisions only if
          that revision is an ancestor of all other revisions given as
          arguments.

    *Error conditions:*
          If any of the revisions do not exist, prints nothing to
          stdout, prints an error message to stderr, and exits with
          status 1.


`mtn automate parents REV'

    *Arguments:*
          One revision ID, REV.

    *Added in:*
          0.2

    *Purpose:*
          Prints the immediate parents of a revision.  This is like a
          non-recursive version of `automate ancestors'.

    *Sample output:*
          28ce076c69eadb9b1ca7bdf9d40ce95fe2f29b61
          75156724e0e2e3245838f356ec373c50fa469f1f

    *Output format:*
          Zero or more lines, each giving the ID of one parent of the
          given revision.  Each line consists of a revision ID, in
          hexadecimal, followed by a newline.  The lines are printed in
          alphabetically sorted order.

    *Error conditions:*
          If the given revision REV does not exist, prints nothing to
          stdout, prints an error message to stderr, and exits with
          status 1.


`mtn automate descendents REV1 [REV2 [...]]'

    *Arguments:*
          One or more revision IDs, REV1, REV2, etc.

    *Added in:*
          0.1

    *Purpose:*
          Prints the descendants of one or more revisions.

    *Sample output:*
          28ce076c69eadb9b1ca7bdf9d40ce95fe2f29b61
          75156724e0e2e3245838f356ec373c50fa469f1f

    *Output format:*
          Zero or more lines, each giving the ID of one descendant of
          the given revisions.  Each line consists of a revision ID, in
          hexadecimal, followed by a newline.  The lines are printed in
          alphabetically sorted order.

          The output does not include REV1, REV2, etc., except that if
          REV2 is itself a descendant of REV1, then REV2 will be
          included in the output.

    *Error conditions:*
          If any of the revisions do not exist, prints nothing to
          stdout, prints an error message to stderr, and exits with
          status 1.


`mtn automate children REV'

    *Arguments:*
          One revision ID, REV.

    *Added in:*
          0.2

    *Purpose:*
          Prints the immediate children of a revision.  This is like a
          non-recursive version of `automate descendents'.

    *Sample output:*
          28ce076c69eadb9b1ca7bdf9d40ce95fe2f29b61
          75156724e0e2e3245838f356ec373c50fa469f1f

    *Output format:*
          Zero or more lines, each giving the ID of one child of the
          given revision.  Each line consists of a revision ID, in
          hexadecimal, followed by a newline.  The lines are printed in
          alphabetically sorted order.

    *Error conditions:*
          If the given revision REV does not exist, prints nothing to
          stdout, prints an error message to stderr, and exits with
          status 1.


`mtn automate graph'

    *Arguments:*
          None.

    *Added in:*
          0.2

    *Purpose:*
          Prints out the complete ancestry graph of this database.

    *Sample output:*
          0c05e8ec9c6af4224672c7cc4c9ef05ae8bdb794
          27ebcae50e1814e35274cb89b5031a423c29f95a 5830984dec5c41d994bcadfeab4bf1bf67747b89
          4e284617c80bec7da03925062a84f715c1b042bd 27ebcae50e1814e35274cb89b5031a423c29f95a 657c756d24fb65213d59f4ae07e117d830dcc95b

    *Output format:*
          Zero or more lines, each giving ancestry information for one
          revision.  Each line begins with a revision ID.  Following
          this are zero or more space-prefixed revision IDs.  Each
          revision ID after the first is a parent (in the sense of
          `automate parents') of the first.  For instance, in the above
          sample output, 0c05e8ec9c6af4224672c7cc4c9ef05ae8bdb794 is a
          root node, 27ebcae50e1814e35274cb89b5031a423c29f95a has one
          parent, and 4e284617c80bec7da03925062a84f715c1b042bd has two
          parents, i.e., is a merge node.

          The output as a whole is alphabetically sorted by line;
          additionally, the parents within each line are alphabetically
          sorted.

    *Error conditions:*
          None.


`mtn automate erase_ancestors [REV1 [REV2 [...]]]'

    *Arguments:*
          One or more revision IDs, REV1, REV2, etc.

    *Added in:*
          0.1

    *Purpose:*
          Prints all arguments, except those that are an ancestor of
          some other argument.  One way to think about this is that it
          prints the minimal elements of the given set, under the
          ordering imposed by the "child of" relation.  Another way to
          think of it is if the arguments formed a branch, then we
          would print the heads of that branch.  If there are no
          arguments, prints nothing.

    *Sample output:*
          28ce076c69eadb9b1ca7bdf9d40ce95fe2f29b61
          75156724e0e2e3245838f356ec373c50fa469f1f

    *Output format:*
          Zero or more lines, each giving the ID of one descendant of
          the given revisions.  Each line consists of a revision ID, in
          hexadecimal, followed by a newline.  The lines are printed in
          alphabetically sorted order.

    *Error conditions:*
          If any of the revisions do not exist, prints nothing to
          stdout, prints an error message to stderr, and exits with
          status 1.


`mtn automate toposort [REV1 [REV2 [...]]]'

    *Arguments:*
          One or more revision IDs, REV1, REV2, etc.

    *Added in:*
          0.1

    *Purpose:*
          Prints all arguments, topologically sorted.  I.e., if REV1 is
          an ancestor of REV2, then REV1 will appear before REV2 in the
          output; if REV2 is an ancestor of REV1, then REV2 will appear
          before REV1 in the output; and if neither is an ancestor of
          the other, then they may appear in either order.  If there
          are no arguments, prints nothing.

    *Sample output:*
          28ce076c69eadb9b1ca7bdf9d40ce95fe2f29b61
          75156724e0e2e3245838f356ec373c50fa469f1f

    *Output format:*
          A list of revision IDs, in hexadecimal, each followed by a
          newline.  Revisions are printed in topologically sorted order.

    *Error conditions:*
          If any of the revisions do not exist, prints nothing to
          stdout, prints an error message to stderr, and exits with
          status 1.


`mtn automate ancestry_difference NEW [OLD1 [OLD2 [...]]]'

    *Arguments:*
          A "new" revision ID NEW, followed by zero or more "old"
          revision IDs OLD1, OLD2, etc.

    *Added in:*
          0.1

    *Purpose:*
          Prints all ancestors of the revision NEW, that are not also
          ancestors of one of the old revisions.  For purposes of this
          command, "ancestor" is an inclusive term; for example, if NEW
          is an ancestor of OLD1, it will not be printed; but if NEW is
          not an ancestor of any of the "old" revisions, then it will
          be.  Similarly, OLD1 will never be printed, because it is
          considered to be an ancestor of itself.  The reason for the
          names is that if NEW a new revision, and OLD1, OLD2, etc. are
          revisions that you have processed before, then this command
          tells you which revisions are new since then.

    *Sample output:*
          28ce076c69eadb9b1ca7bdf9d40ce95fe2f29b61
          75156724e0e2e3245838f356ec373c50fa469f1f

    *Output format:*
          A list of revision IDs, in hexadecimal, each followed by a
          newline.  Revisions are printed in topologically sorted order.

    *Error conditions:*
          If any of the revisions do not exist, prints nothing to
          stdout, prints an error message to stderr, and exits with
          status 1.


`mtn automate leaves'

    *Arguments:*
          None.

    *Added in:*
          0.1

    *Purpose:*
          Prints the leaves of the revision graph, i.e. all revision
          that have no children.  This is similar, but not identical to
          the functionality of `heads', which prints every revision in
          a branch, that has no descendants in that branch.  If every
          revision in the database was in the same branch, then they
          would be identical.  Generally, every leaf is the head of
          some branch, but not every branch head is a leaf.

    *Sample output:*
          28ce076c69eadb9b1ca7bdf9d40ce95fe2f29b61
          75156724e0e2e3245838f356ec373c50fa469f1f

    *Output format:*
          Zero or more lines, each a leaf of the revision graph.  Each
          line consists of a revision ID, in hexadecimal, followed by a
          newline.  The lines are printed in alphabetically sorted
          order.

    *Error conditions:*
          None.


`mtn automate roots'

    *Arguments:*
          None.

    *Added in:*
          4.3

    *Purpose:*
          Prints the roots of the revision graph, i.e. all revisions
          that have no parents.

    *Sample output:*
          276264b0b3f1e70fc1835a700e6e61bdbe4c3f2f

    *Output format:*
          Zero or more lines, each a root of the revision graph.  Each
          line consists of a revision ID, in hexadecimal, followed by a
          newline.  The lines are printed in alphabetically sorted
          order.

    *Error conditions:*
          None.


`mtn automate branches'

    *Arguments:*
          None.

    *Added in:*
          2.2

    *Purpose:*
          Prints all branch certs present in the revision graph, that
          are not excluded by the Lua hook `ignore_branch'.

    *Sample output:*
          net.venge.monotone
          net.venge.monotone.win32

    *Output format:*
          Zero or more lines, each the name of a branch. The lines are
          printed in alphabetically sorted order.

    *Error conditions:*
          None.


`mtn automate tags [BRANCH_PATTERN]'

    *Arguments:*
          A branch pattern (optional).

    *Changes:*
             * 11.0 - SIGNER now prints the hash of the signing key, no
               longer the name.          Also, the FORMAT_VERSION
               stanza has been removed in favour of the         global
               INTERFACE_VERSION.

             * 2.2 - added

    *Purpose:*
          If a branch pattern is given, prints all tags that are
          attached to revisions on branches matched by the pattern;
          otherwise prints all tags of the revision graph.

          If a branch name is ignored by means of the Lua hook
          `ignore_branch', it is neither printed, nor can it be matched
          by a pattern.

    *Sample output:*
               tag "monotree-0.1"
          revision [8a121346ce2920b6f85df68b3b620de96bd14a8d]
            signer [de84b575d5e47254393eba49dce9dc4db98ed42d]
          branches "net.venge.monotone.contrib" "net.venge.monotone.contrib.monotree"

               tag "monotree-0.2"
          revision [5d288b39b49613b0d9dca8ece6b9a42c3773f35b]
            signer [de84b575d5e47254393eba49dce9dc4db98ed42d]
          branches "net.venge.monotone.contrib.monotree"

               tag "monotree-0.3"
          revision [35cff8e8ba14155f5f7ddf7965073f514fd60f61]
            signer [de84b575d5e47254393eba49dce9dc4db98ed42d]
          branches "net.venge.monotone.contrib.monotree"

               tag "monotree-0.4"
          revision [f1afc520474f83c58262896ede027ef77226046e]
            signer [de84b575d5e47254393eba49dce9dc4db98ed42d]
          branches "net.venge.monotone.contrib.monotree"

    *Output format:*
          There is one basic_io stanza for each tag.

          All stanzas are formatted by basic_io. Stanzas are separated
          by a blank line. Values will be escaped, '\' to '\\' and '"'
          to '\"'.

          Each stanza has exactly the following four entries:

         `'tag''
               the value of the tag cert, i.e. the name of the tag

         `'revision''
               the hexadecimal id of the revision the tag is attached to

         `'signer''
               the name of the key used to sign the tag cert

         `'branches''
               a (possibly empty) list of all branches the tagged
               revision is on

          Stanzas are printed in arbitrary order.

    *Error conditions:*
          A run-time exception occurs if an illegal branch pattern is
          specified.


`mtn automate select SELECTOR'

    *Arguments:*
          One selector (or combined selector).

    *Added in:*
          0.2

    *Purpose:*
          Print all revisions that match the given selector.

    *Sample output:*
          28ce076c69eadb9b1ca7bdf9d40ce95fe2f29b61
          75156724e0e2e3245838f356ec373c50fa469f1f

    *Output format:*
          Zero or more lines, each giving the ID of one revision that
          matches the given selector.  Each line consists of a revision
          ID, in hexadecimal, followed by a newline.  Revision ids are
          printed in alphabetically sorted order.

    *Error conditions:*
          None.


`mtn automate identify PATH'

    *Arguments:*
          A file path.

    *Added in:*
          4.3

    *Purpose:*
          Prints the file ID (aka hash) of the given file.

    *Sample output:*
          6265ab1312fbe38bdc3aafa92441139cb2b779b0

    *Output format:*
          A single line with the file's ID, in hexadecimal, followed by
          a newline.

    *Error conditions:*
          If the file does not exists, is a special file or not
          readable, prints an error message to stderr and exists with
          status 1. A single file path only consisting of "-" is
          disallowed since it collides with the UNIX stdin marker.


`mtn automate inventory [`options...'] [FILES...]'

    *Arguments:*
          One or more file paths (optional). If present, only show an
          inventory for the given files or directories (and their
          sub-directories).

         `--depth=N'
               Maximum number of directories to descend.

         `--exclude=EXCLUDE-GLOB'
               File or directory to exclude.

         `--no-ignored'
               Don't output ignored files or directories.

         `--no-unknown'
               Don't output unknown directories.

         `--no-unchanged'
               Don't output files that are known but not changed in any
               way.

         `--no-corresponding-renames'
               If restricted to a renamed path, do not output the
               corresponding old / new paths for this restriction.


    *Changes:*
             * 8.0 - added the output of the `birth' key

             * 7.0 - added options `--no-ignored', `--no-unknown',
               `--no-unchanged' and `--no-corresponding-renames'

             * 6.0 - converted to basic_io format (restriction support,
               various fixes)

             * 1.0 - initial, line-based format

    *Purpose:*
          Prints the inventory of every file found in the workspace or
          its associated base and revision manifests. Each unique path
          is listed in a basic_io stanza. Stanzas are separated by
          blank lines.

    *Sample output:*
          All basic status cases:     path "added"
          new_type "file"
           fs_type "file"
            status "added" "known"
           changes "content"

              path "attributes_altered"
          old_type "file"
          new_type "file"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "known"
           changes "attrs"

              path "dropped"
          old_type "file"
           fs_type "none"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "dropped"

             path "ignored~"
          fs_type "file"
           status "ignored"

              path "missing"
          old_type "file"
          new_type "file"
           fs_type "none"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "missing"

              path "original"
          old_type "file"
          new_path "renamed"
           fs_type "none"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source"

              path "patched"
          old_type "file"
          new_type "file"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "known"
           changes "content"

              path "patched_and_attributes_altered"
          old_type "file"
          new_type "file"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "known"
           changes "content" "attrs"

              path "renamed"
          new_type "file"
          old_path "original"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_target" "known"

              path "unchanged"
          old_type "file"
          new_type "file"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "known"

             path "unknown"
          fs_type "file"
           status "unknown"

          Two files swapped in both the revision manifest and the
          workspace:     path "original"
          old_type "file"
          new_path "unchanged"
          new_type "file"
          old_path "unchanged"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source" "rename_target" "known"

              path "unchanged"
          old_type "file"
          new_path "original"
          new_type "file"
          old_path "original"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source" "rename_target" "known"

          Recorded in the revision manifest that two files were
          swapped, but they were not actually swapped in the workspace.
          Thus they both appear as patched:     path "original"
          old_type "file"
          new_path "unchanged"
          new_type "file"
          old_path "unchanged"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source" "rename_target" "known"
           changes "content"

              path "unchanged"
          old_type "file"
          new_path "original"
          new_type "file"
          old_path "original"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source" "rename_target" "known"
           changes "content"

          Rename (in the manifest and the workspace) `foo' to `bar';
          add (in the manifest and the workspace) new file `foo':     path "foo"
          old_type "file"
          new_path "bar"
          new_type "file"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source" "added" "known"

              path "bar"
          new_type "file"
          old_path "foo"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_target" "known"

          Rotated files `foo' -> `bar' -> `baz' -> `foo' (in the
          manifest and the workspace):     path "foo"
          old_type "file"
          new_path "bar"
          new_type "file"
          old_path "baz"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source" "rename_target" "known"

              path "bar"
          old_type "file"
          new_path "baz"
          new_type "file"
          old_path "foo"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source" "rename_target" "known"

              path "baz"
          old_type "file"
          new_path "foo"
          new_type "file"
          old_path "bar"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source" "rename_target" "known"

          Recorded in the revison manifest the rotation of files `foo'
          -> `bar' -> `baz' -> `foo', but the actual files in the
          workspace were not moved, so monotone interprets all files as
          having been patched:     path "foo"
          old_type "file"
          new_path "bar"
          new_type "file"
          old_path "baz"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source" "rename_target" "known"
           changes "content"

              path "bar"
          old_type "file"
          new_path "baz"
          new_type "file"
          old_path "foo"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source" "rename_target" "known"
           changes "content"

              path "baz"
          old_type "file"
          new_path "foo"
          new_type "file"
          old_path "bar"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source" "rename_target" "known"
           changes "content"

          Dropped from the manifest but not removed in the workspace
          and thus unknown:     path "dropped"
          old_type "file"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "dropped" "unknown"

          Added in the manifest but not in the workspace, and thus
          missing:     path "added"
          new_type "file"
           fs_type "none"
            status "added" "missing"

          Recorded a rename in the manifest, but not moved in the
          workspace, and thus unknown source and missing target:     path "original"
          old_type "file"
          new_path "renamed"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source" "unknown"

              path "renamed"
          new_type "file"
          old_path "original"
           fs_type "none"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_target" "missing"

          Moved in the workspace but no rename recorded in the
          manifest, and thus missing source and unknown target:     path "original"
          old_type "file"
          new_type "file"
           fs_type "none"
            status "missing"

             path "renamed"
          fs_type "file"
           status "unknown"

          Renamed in the manifest and the workspace and patched:     path "original"
          old_type "file"
          new_path "renamed"
           fs_type "none"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source"

              path "renamed"
          new_type "file"
          old_path "original"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_target" "known"
           changes "content"

          Renamed and restricted to `original' or `renamed':     path "original"
          old_type "file"
          new_path "renamed"
           fs_type "none"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source"

              path "renamed"
          new_type "file"
          old_path "original"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_target" "known"
           changes "content"

          Renamed and restricted to `original' with the
          `--no-corresponding-renames' option:     path "original"
          old_type "file"
          new_path "renamed"
           fs_type "none"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source"

          Renamed and restricted to `renamed' with the
          `--no-corresponding-renames' option:     path "renamed"
          new_type "file"
          old_path "original"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_target" "known"
           changes "content"

          File is missing, an unversioned directory is in the way:     path "missing_file"
          old_type "file"
          new_type "file"
           fs_type "directory"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "invalid"
           changes "content"

          Directory is missing, an unversioned file is in the way:     path "missing_directory"
          old_type "directory"
          new_type "directory"
           fs_type "file"
            status "invalid"

          Directory `source' renamed to `target', `target' is missing,
          an unversioned file is in the way:     path "source"
          old_type "directory"
          new_path "target"
           fs_type "none"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source"

              path "source/a"
          old_type "file"
          new_path "target/a"
           fs_type "none"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_source"

              path "target"
          new_type "directory"
          old_path "source"
           fs_type "file"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_target" "invalid"

              path "target/a"
          new_type "file"
          old_path "source/a"
           fs_type "none"
             birth [cb271687054afd3c2b873c8994f206f08fb240d3]
            status "rename_target" "missing"

    *Output format:*
          Each path is printed in one basic_io stanza. Stanzas are
          separated by a blank line. Each stanza starts with a `path'
          line, and contains up to seven lines. The order of the lines
          is not important, and may change in future revisions, except
          that the first line will always be `path'.

         `path'
               The file or directory path, relative to the workspace
               root. The file either exists in the workspace, or is
               listed in the base or revision manifest.  `path' is
               always output.

         `old_type'
               The type of the node in the base manifest.  "type" is
               either `file' or `directory'.  `old_type' is output for
               all old nodes (i.e. unchanged or dropped paths and
               rename sources).

         `new_type'
               The type of the node in the revision manifest.  "type"
               is either `file' or `directory'.  `new_type' is output
               for all new nodes (i.e. unchanged or added paths and
               rename targets).

         `fs_type'
               The type of the node in the workspace (also called the
               filesystem).  "type" is either `file', `directory' or
               `none' (if the path does not exist in the file system).
               `fs_type' is always output.

         `old_path'
               The old path for the node, if it has been renamed in the
               revision manifest.  `old_path' is only output for rename
               targets.

         `new_path'
               The new path for the node, if it has been renamed in the
               revision manifest.  `new_path' is only output for rename
               sources.

         `birth'
               The identify of the revision that the node was first
               added in.  `birth' is only output if it exists in a
               committed revision.

         `status'
               `status' is always output. Its value is one or more of:

              `rename_source'
                    PATH is part of a rename and denotes the old name
                    of a renamed node.

              `rename_target'
                    PATH is part of a rename and denotes the new name
                    of a renamed node.

              `added'
                    PATH has been added in the revision manifest, but
                    not existent in the base manifest.

              `dropped'
                    PATH has been deleted in the revision manifest and
                    the workspace.

              `missing'
                    PATH has been deleted in the workspace, but still
                    exists in the revision manifest.

                    A file will also be labeled `missing' if it is in a
                    directory that is ignored due to a regular
                    expression in `.mtn-ignore', but is also in the
                    revision manifest. A warning is issued in this case.

              `ignored'
                    PATH is ignored by monotone.

              `known'
                    PATH exists in the workspace, and in the revision
                    manifest.

              `unknown'
                    PATH exists in the workspace, but not in the
                    revision manifest, i.e.  is unversioned.

              `invalid'
                    PATH is versioned and exists in the workspace and
                    revision manifest, but with incompatible types (a
                    versioned missing file is replaced by an
                    unversioned directory and vice versa).

         `changes'

              `content'
                    The contents of a file have been changed.

              `attrs'
                    The attributes of a path (file or directory) have
                    been changed.


    *Error conditions:*
          When executed from outside of a workspace directory, prints
          an error message to stderr, and exits with status 1.


`mtn automate certs ID'

    *Arguments:*
          A revision ID ID, for which any certificates will be printed.

    *Changes:*
             * 11.0 - Keys are now listed by hash instead of name.

             * 1.0 - Added.

    *Purpose:*
          Prints all certificates associated with the given revision ID.
          Each certificate is contained in a basic IO stanza. For each
          certificate, the following values are provided: 'key'
                the hex-encoded hash of the key used to sign this certificate.
          'signature'
                a string indicating the status of the signature. Possible
                values of this string are:
                      'ok'        : the signature is correct
                      'bad'       : the signature is invalid
                      'unknown'   : signature was made with an unknown key
          'name'
                the name of this certificate
          'value'
                the value of this certificate
          'trust'
                is this certificate trusted by the defined trust metric?
                Possible values of this string are:
                      'trusted'   : this certificate is trusted
                      'untrusted' : this certificate is not trusted

    *Sample output:*
                key [5cd3b3a7ad2e8645e8887af193ee522dc59112e4]
          signature "ok"
               name "author"
              value "emile@alumni.reed.edu"
              trust "trusted"

                key [5cd3b3a7ad2e8645e8887af193ee522dc59112e4]
          signature "ok"
               name "branch"
              value "net.venge.monotone"
              trust "trusted"

                key [5cd3b3a7ad2e8645e8887af193ee522dc59112e4]
          signature "ok"
               name "changelog"
              value "propagate from branch 'net.venge.monotone.annotate' (head 76a886ef7c8ae12a4bba5fc2bd252557bf863aff)
                      to branch 'net.venge.monotone' (head 2490479a4e4e99243fead6d627d78291fde592f0)
          "
              trust "trusted"

                key [5cd3b3a7ad2e8645e8887af193ee522dc59112e4]
          signature "ok"
               name "date"
              value "2005-05-20T20:19:25"
              trust "trusted"

    *Output format:*
          All stanzas are formatted by basic_io. Stanzas are separated
          by a blank line. Values will be escaped, '\' to '\\' and '"'
          to '\"'.

    *Error conditions:*
          If a certificate is signed with an unknown public key, a
          warning message is printed to stderr. If the revision
          specified is unknown or invalid prints an error message to
          stderr and exits with status 1.


`mtn automate stdio'

    *Arguments:*
          none

    *Changes:*
             * 12.0 - Introduced out of band streams ('e', 'p', 't',
               'w'); the main output     of a command now only happens
               in the 'm' stream; the 'l' stream now marks     the end
               of all streams of a command; introduced the concept of
               "headers"     which are output before the first command
               is issued; specific error codes     to distinguish
               command from interface errors have also been introduced.

             * 3.1 - Added the 'o' item to the recognized input. This
               change should not break anything.

             * 1.0 - Initial version.

    *Purpose:*
          Allow multiple automate commands to be run from one instance
          of monotone.

    *Sample input:*
          l6:leavese
          l7:parents40:0e3171212f34839c2e3263e7282cdeea22fc5378e
          o3:key11:foo@bar.come l4:cert40:0e3171212f34839c2e3263e7282cdeea22fc53783:foo3:bare

    *Input format:*
          [ 'o' <string> <string> [ <string> <string> [ ... ] ] 'e' ]
          'l' <string> [ <string> [ ... ] ] 'e'

          The input is a series of commands. The command name plus
          arguments are provided as 'l' <string> [<string> ...] 'e',
          where <string> = <size> colon <data> . This may optionally be
          preceded by a set of key=value pairs (command options) as 'o'
          <string> <string> [<string> <string> ...] 'e', where strings
          come in pairs, key followed by value. For flag options that
          don't take values, specify the second string as zero length;
          `0:'.

          The space between the ending 'e' of one group of strings and
          the beginning 'l' or 'o' of the next is reserved. Any
          characters other than whitespace will cause an error.

    *Sample output:*
          format-version: 2

          0:m:41:7706a422ccad41621c958affa999b1a1dd644e79
          0:l:1:0
          ...
          1:e:38:misuse: key 'test@test' already exists
          1:l:1:2
          ...
          2:w:39:skipping file '\' with unsupported name
          2:m:144:    path ""
          old_type "directory"
          new_type "directory"
           fs_type "directory"
             birth [276264b0b3f1e70fc1835a700e6e61bdbe4c3f2f]
            status "known"
          ...
          3:t:34:c:certificates;k:keys;r:revisions;
          3:t:12:c=0;k=0;r=0;
          3:t:13:c#0;k#0;r#64;
          3:t:14:c#0;k#0;r#128;
          3:t:6:c;k;r;
          ...

    *Output format:*
          Right after a stdio session has been set up, header
          information is issued; to date the only header defined is
          `format-version', which denotes the version of the stdio
          format used throughout the session. The original format had
          no such version output, so our numbering starts with "2" here.

          Headers are separated from each other by single newline
          character `'\n'' and the last is separated from the following
          output by a pair of newline characters.

          After a command has been issued, one or more packets are
          returned for it.  A packet looks like:

          <command number>:<stream>:<size>:<output>

          `<command number>' is a decimal number specifying which
          command this output is from. It is 0 for the first command,
          and increases by one each time.

          `<stream>' is an identifier for which output stream this
          packet represents, allowing multiple streams to be
          multiplexed over the channel.  The following streams are
          presently defined; more streams may be added later.

             *  `m': this stream represents the normal ("main") stdout
               automate output of  the command, formatted as described
               in the description for that command.

             *  `e': this stream represents any (unstructured) error
               message data.

               Internally, this maps to calls to the `E()' print macros
               that would  normally be written by the command to the
               program's stderr stream, if the  automate sub-command
               had been called directly rather than via "'stdio"'.

             *  `w': this stream represents any (unstructured) warning
               message data.

               Internally, this maps to calls to the `W()' print macro
               that would  normally be written by the command to the
               program's stderr stream, if the  automate sub-command
               had been called directly rather than via "'stdio"'.

             *  `p': this stream represents any (unstructured) progress
               message data.

               Internally, this maps to calls to the `P()' print macro
               that would  normally be written by the command to the
               program's stderr stream, if the  automate sub-command
               had been called directly rather than via "'stdio"'.

             *  `t': this stream represents ticker updates, which may
               be used  by a user interface to display the progress of
               a command.

               The output for this channel can be described as follows:

                  *  `<output>       ::= <definition><payload><end>'

                  *  `<definition>   ::= <shortname> ':' <longname>
                    <eol>'

                  *  `<payload>      ::= <total_count><advance>+'

                  *  `<end>          ::= <shortname> <eol>'

                  *  `<total_count>  ::= <shortname> '=' <count> <eol>'

                  *  `<advance>      ::= <shortname> '#' <count> <eol>'

                  *  `<shortname>    ::= "\w+"'

                  *  `<longname>     ::= "[^;]+"'

                  *  `<count>        ::= ['0'-'9']+'

                  *  `<eol>          ::= ';''

               The definition tells the implementor the short name and
               long name of any upcoming ticker event. The names and
               meanings are command-specific and are therefore
               explained in the sections for the particular commands
               which support ticker output.

               The `total_count' might be 0 right at the start and can
               later be changed  to a different number if the command
               later on knows a more exact value. If  this is the case,
               this stanza is output again with this new value. A
               constant `total_count' of 0 means that the command may
               continue to run  for a undefined amount of time until
               the end stanza appears.

               The advance tells the implementor how much work has been
               done so far.

               Finally, the end stanza is printed just before the
               ticker ends  (i.e. the work has been done).

               All counts output absolute, raw values; no modulation
               takes place. It is usually the case that definition,
               `total_count', advance and end are output in separate
               stanzas. It is also possible that two or more parallel
               tickers output their stanzas at the same time, in this
               case it's ensured that the output does not get
               intermixed; first all definitions are output, afterwards
               all total_counts, and so on.

               _Note:_ The ticker format used for stdio is fixed and
               cannot be selected  explicitely via the global
               `--ticker' option. However, if you run an  automate
               command outside of stdio you can set a different ticker
               type, f.e.   COUNT, DOT or NONE.

             *  `l': this stream marks the termination of a command and
               all of  its streams and carries the return code of the
               command in the payload.

               A return code "0" stands for success, "1" for an error
               which occurred within  the stdio interface (f.e. syntax
               errors or missing privileges) before the  command is run
               and finally "2" for any other command-specific error.

          `<size>' is the number of bytes in the output.

          `<output>' is a piece of the output of the command.

    *Error conditions:*
          Errors in the commands run through this interface do not
          affect the exit status of this command. Instead, if a badly
          formatted or invalid command is received, or a command is
          given with invalid arguments or options, an error message to
          the error stream is printed and and the particular
          sub-command exits with return code "1". Other
          command-specific errors are returned as code "2".

          Trying to run the `automate stdio' or `automate remote_stdio'
          sub-commands will exit the particular command with return
          code "1".

    *Notes:*
          Keyboard interaction is disabled, just as if
          `--non-interactive' is specified. Actions which require
          operations on password-encrypted private keys will therefor
          fail unless the `get_passphrase' hook is set up locally.

    *Multiple streams*
          The multiple stream encoding allows the output of errors and
          warnings to be associated with the command that generated
          them, allows the communication path to always stay in sync,
          and offers the opportunity to add other stream types for
          other useful purposes in the future as needs arise.


`mtn automate remote_stdio [HOSTNAME]'

    *Arguments*
          HOSTNAME is the host (and optionally port) of the monotone
          server process to connect to. If not given, the default
          server is used.

    *Added in*
          12.0

    *Purpose*
          Permit `automate' commands to be run against a database that
          is being used to serve netsync connections.

    *Input/Output format*
          This command takes input and produces output in exactly the
          same format as `automate stdio'. Note that the commands run
          with `automate remote_stdio' may conform to a different
          INTERFACE_VERSION, because they are handled by a remote
          instance of monotone.

          There will be some extra chatter on stderr unless `--quiet'
          is given.

    *Error Conditions*
          If left idle for too long or there are network problems, the
          connection to the server may be dropped. This will not be
          detected while monotone is waiting for input. Instead, when a
          complete command has been entered and monotone tries to send
          it to the remote server it will print a message to stderr and
          exit with code 1.

    *Notes*
          On the server side the `get_remote_automate_permitted' hook
          has to be configured to include every command which should be
          executable over this interface.

          For both, the client and the server, keyboard interaction is
          disabled, just as if `--non-interactive' is specified.
          Actions which require operations on password-encrypted
          private keys will therefor fail unless the `get_passphrase'
          hook is set up locally and / or remotely.


`mtn automate remote `--remote-stdio-host=host' COMMAND ARGS-AND-OPTS'

    *Arguments*
          A command and its arguments, to execute on the remote server
          specified by the `--remote-stdio-host' option. If no host is
          given, the default server is used. If options are to be
          passed to the command, they must be preceded by `--' to
          prevent them from being interpreted as local options.

          Remote options *must* be given as a single token, ie
          `--branch=foo' or `-bfoo'. This is because the local and
          remote monotones may not understand exactly the same options
          (so the local monotone cannot know if an option given as
          `--branch' or `-b' should be followed by an argument), and
          because the server sees this as an `automate remote_stdio'
          connection (so it expects the options to already be parsed).

    *Added in*
          12.0

    *Purpose*
          Permit a single `automate' command to be run against a
          database that is being used to serve netsync connections,
          without having its input and output encoded as by `automate
          stdio'.

    *Input/Output Format*
          This command does not accept input.

          The output will be whatever output the remote command
          generates.

          Remote diagnostic messages are written to standard error,
          prefixed either with `mtn: remote error:', `mtn: remote
          warning:' or `mtn: remote message:' to make them
          distinguishable from local diagnostics. Tickers are not
          supported over this interface. If you need remote ticker
          support, please use `automate remote_stdio'.

    *Error Conditions*
          If the remote command returns a nonzero error code, will exit
          with code 1 and print "received remote error code N" to
          standard error, with "N" being the remote error code.

    *Notes*
          On the server side the `get_remote_automate_permitted' hook
          has to be configured to include every command which should be
          executable over this interface.

          Keyboard interaction is disabled on the server, just as if
          `--non-interactive' would have been specified on server
          startup.  Actions which require operations on
          password-encrypted private keys will therefor fail unless a
          `get_passphrase' hook is set up remotely.


`mtn automate pull [--set-default] [URI-OR-ADDRESS] [GLOB [...] [--exclude=EXCLUDE-GLOB]]]'
`mtn automate push [--set-default] [--keys-to-push=KEY] [URI-OR-ADDRESS] [GLOB [...] [--exclude=EXCLUDE-GLOB]]]'
`mtn automate sync [--set-default] [--keys-to-push=KEY] [URI-OR-ADDRESS] [GLOB [...] [--exclude=EXCLUDE-GLOB]]]'

    *Arguments:*
          The automate versions of pull, push and sync have the same
          set of arguments and options compared to the non-automate
          versions. Please check this manual in the appropriate section
          for a full explanation.

    *Added in:*
          12.0

    *Purpose:*
          Pushes, pulls or syncs (push & pull) revisions, certificates
          and keys of the given database to, from or with the given
          netsync server.

    *Sample output (stdio):*
          The following output shows an example of a pull which
          transferred two revisions and eight certs.

          _Note:_ The linebreaks are not part of the actual format, but
          have been added for better readability.

          0:p:62:doing anonymous pull; use -kKEYNAME if you need authentication
          0:p:25:connecting to monotone.ca0:0:p:29:finding items to synchronize:
          0:t:34:c:certificates;k:keys;r:revisions;
          0:t:12:c=0;k=0;r=0;
          0:t:13:c#0;k#0;r#64;
          0:t:14:c#0;k#0;r#128;
          [...]
          0:t:6:c;k;r;
          0:t:44:>:bytes in;<:bytes out;c:certs in;r:revs in;
          0:t:16:>=0;<=0;c=0;r=0;
          0:t:21:>#420;<#1344;c#0;r#0;
          0:t:22:>#1165;<#1741;c#0;r#0;
          [...]
          0:t:24:>#20839;<#14882;c#0;r#1;
          0:t:24:>#20839;<#14882;c#3;r#1;
          0:t:24:>#20839;<#14882;c#4;r#2;
          0:t:24:>#20839;<#14882;c#6;r#2;
          0:t:24:>#20863;<#14930;c#8;r#2;
          0:t:8:<;>;c;r;
          0:p:36:successful exchange with monotone.ca
          0:l:1:0

    *Output format:*
          If ran outside of `automate stdio', the output of these
          commands is equal to the normal netsync command output.

          If these commands are run over stdio, the stdio ticker format
          is used (for a description of this format, check `automate
          stdio').

          The following ticker types are printed out during the
          refinement phase:

             * `c': The number of certs found for an upcoming
               synchronization

             * `k': The number of keys found for an upcoming
               synchronization

             * `r': The number of revisions found for an upcoming
               synchronization

          After refinement the actual synchronization between the two
          nodes start. The ticker stanzas in this phase are the
          following:

             * `>': The number of incoming bytes

             * `<': The number of outgoing bytes

             * `c': The number of incoming certs  (only pull and sync)

             * `C': The number of outgoing certs  (only push and sync)

             * `r': The number of incoming revisions  (only pull and
               sync)

             * `R': The number of outgoing revisions  (only push and
               sync)

    *Error conditions:*
          If a netsync error occurs, the command outputs an error and
          exits with status 1.


`mtn automate genkey NAME PASSPHRASE'

    *Aguments*
          NAME is the name to associate with the new key, and
          PASSPHRASE is the passphrase that will be used to encrypt the
          private half.

    *Changes:*
             * 10.0 - The separate hashes for the private half of a key
               really didn't make much sense; have one `hash [...]'
               line instead of separate `public_hash [...]' and
               `private_hash [...]' lines.

             * 3.1 - initial

    *Purpose:*
          Generate a key with the given name and passphrase.

    *Sample output:*
                      name "tbrownaw@gmail.com"
                      hash [475055ec71ad48f5dfaf875b0fea597b5cbbee64]
           public_location "database" "keystore"
          private_location "keystore"

    *Output format:*
          A basic_io stanza. The public_location and private_location
          items may have multiple values as shown above for
          public_location, one value for each place that the key is
          stored.

    *Error conditions:*
          Error conditions: If the passphrase is empty or the key
          already exists, prints an error message to stderr and exits
          with status 1.


`mtn automate get_revision ID'

    *Arguments:*
          The argument ID specifies the revision id for which the
          changeset information should be printed.

    *Changes:*
             * 7.0 - ID is now mandatory

             * 1.0 - initial

    *Purpose:*
          Prints change information for the specified revision id.

    *Sample output:*
          format_version "1"

          new_manifest [bfe2df785c07bebeb369e537116ab9bb7a4b5e19]

          old_revision [429fea55e9e819a046843f618d90674486695745]

          patch "ChangeLog"
           from [7dc21d3a46c6ecd94685ab21e67b131b32002f12]
             to [234513e3838d423b24d5d6c98f70ce995c8bab6e]

          patch "std_hooks.lua"
           from [0408707bb6b97eae7f8da61af7b35364dbd5a189]
             to [d7bd0756c48ace573926197709e53eb24dae5f5f]

    *Output format:*
          There are several changes that are described; each of these
          is described by a different basic_io stanza. The first string
          pair of each stanza indicates the type of change represented.

          All stanzas are formatted by basic_io. Stanzas are separated
          by a blank line. Values will be escaped, '\' to '\\' and '"'
          to '\"'.

          Possible values of this first value are along with an ordered
          list of basic_io formatted stanzas that will be provided are:

          'format_version'
                used in case this format ever needs to change.
                format: ('format_version', the string "1")
                occurs: exactly once
          'new_manifest'
                represents the new manifest associated with the revision.
                format: ('new_manifest', manifest id)
                occurs: exactly one
          'old_revision'
                represents a parent revision.
                format: ('old_revision', revision id)
                occurs: either one or two times
          'delete
                represents a file or directory that was deleted.
                format: ('delete', path)
                occurs: zero or more times
          'rename'
                represents a file or directory that was renamed.
                format: ('rename, old filename), ('to', new filename)
                occurs: zero or more times
          'add_dir'
                represents a directory that was added.
                format: ('add_dir, path)
                occurs: zero or more times
          'add_file'
                represents a file that was added.
                format: ('add_file', path), ('content', file id)
                occurs: zero or more times
          'patch'
                represents a file that was modified.
                format: ('patch', filename), ('from', file id), ('to', file id)
                occurs: zero or more times
          'clear'
                represents an attr that was removed.
                format: ('clear', filename), ('attr', attr name)
                occurs: zero or more times
          'set'
                represents an attr whose value was changed.
                format: ('set', filename), ('attr', attr name), ('value', attr value)
                occurs: zero or more times

          These stanzas will always occur in the order listed here;
          stanzas of the same type will be sorted by the filename they
          refer to. The 'delete' and following stanzas will be grouped
          under the corresponding 'old_revision' one.

    *Error conditions:*
          If the revision specified is unknown or invalid prints an
          error message to stderr and exits with status 1.


`mtn automate get_current_revision [--exclude EXCL] [--depth=DEPTH] [PATH ...]'

    *Arguments:*
          One or more PATH arguments restrict the revision to these
          paths, otherwise all changes in workspace are taken into
          account.

          Options EXCL and DEPTH work just like in MTN COMMIT.

    *Added in:*
          7.0

    *Purpose:*
          Prints change information for the current workspace,
          optionally restricted by one or more paths.

    *Sample output:*
          See AUTOMATE GET_REVISION

    *Output format:*
          See AUTOMATE GET_REVISION

    *Error conditions:*
          If the command is executed outside of a workspace, or the
          restriction is invalid, prints an error message to stderr and
          exits with status 1.


`mtn automate get_base_revision_id'

    *Arguments:*
          None.

    *Added in:*
          2.0

    *Purpose:*
          Prints the revision id the current workspace is based on.
          This is the "old_revision" value stored in `_MTN/revision'.

    *Sample output:*
          28ce076c69eadb9b1ca7bdf9d40ce95fe2f29b61

    *Output format:*
          One line containing the base revision ID of the current
          workspace.

    *Error conditions:*
          If no workspace book keeping _MTN directory is found, prints
          an error message to stderr, and exits with status 1.


`mtn automate get_current_revision_id'

    *Arguments:*
          None.

    *Added in:*
          2.0

    *Purpose:*
          Prints the revision id of the current workspace. This is the
          id of the revision that would be committed by an unrestricted
          commit in the workspace.

    *Sample output:*
          28ce076c69eadb9b1ca7bdf9d40ce95fe2f29b61

    *Output format:*
          One line containing the current revision id ID of the current
          workspace.

    *Error conditions:*
          If no workspace book keeping _MTN directory is found, prints
          an error message to stderr, and exits with status 1.


`mtn automate get_manifest_of'

`mtn automate get_manifest_of REVID'

    *Arguments:*
          Specifying the optional REVID argument outputs the manifest
          for the revision with the specified ID. Otherwise, outputs
          the manifest for the current workspace.  (You can think of
          leaving the argument blank as meaning "give me the manifest
          of THIS".)

    *Added in:*
          2.0

    *Purpose:*
          Prints the contents of the manifest associated with the given
          roster.

    *Sample output:*
          format_version "1"

          dir ""

             file ".htaccess"
          content [e3915658cb464d05f21332e03d30dca5d94fe776]

             file "AUTHORS"
          content [80d8f3f75c9b517ec462233e155f7dfb93379f67]

             file "ChangeLog"
          content [fc74a48c7f73eedcbe1ea709755fbe819b29736c]

             file "LICENSE"
          content [dfac199a7539a404407098a2541b9482279f690d]

             file "README"
          content [440eec971e7bb61ccbb61634deb2729bb25931cd]

             file "TODO"
          content [e0ea26c666b37c5f98ccf80cb933d021ee55c593]

             file "branch.psp"
          content [b28ece354969314ce996f3030569215d685973d6]

             file "common.py"
          content [1fdb62e05fb2a9338d2c72ddc58de3ab2b3976fe]

             file "config.py.example"
          content [64cb5898e3a026b4782c343ca4386585e0c3c275]

             file "error.psp"
          content [7152c3ff110418aca5d23c374ea9fb92a0e98379]

             file "fileinbranch.psp"
          content [5d8536100fdf51d505b6f20bc9c16aa78d4e86a8]

             file "headofbranch.psp"
          content [981df124a0b5655a9f78c42504cfa8c6f02b267a]

             file "help.psp"
          content [a43d0588a69e622b2afc681678c2a5c3b3b1f342]

             file "html.py"
          content [18a8bffc8729d7bfd71d2e0cb35a1aed1854fa74]

             file "index.psp"
          content [c621827db187839e1a7c6e51d5f1a7f6e0aa560c]

             file "monotone.py"
          content [708b61436dce59f47bd07397ce96a1cfabe81970]

             file "revision.psp"
          content [a02b1c161006840ea8685e461fd07f0e9bb145a3]

             file "rss_feed.gif"
          content [027515fd4558abf317d54c437b83ec6bc76e3dd8]

             file "tags.psp"
          content [638140d6823eee5844de37d985773be75707fa25]

             file "tarofbranch.psp"
          content [be83f459a152ffd49d89d69555f870291bc85311]

             file "test.py"
          content [e65aace9237833ec775253cfde97f59a0af5bc3d]
             attr "mtn:execute" "true"

             file "utility.py"
          content [fb51955563d64e628e0e67e4acca1a1abc4cd989]

             file "viewmtn.css"
          content [8d04b3fc352a860b0e3240dcb539c1193705398f]

             file "viewmtn.py"
          content [7cb5c6b1b1710bf2c0fa41e9631ae43b03424a35]

             file "wrapper.py"
          content [530290467a99ca65f87b74f653bf462b28c6cda9]

    *Output format:*
          There is one basic_io stanza for each file or directory in the
          manifest.

          All stanzas are formatted by basic_io. Stanzas are separated
          by a blank line. Values will be escaped, '\' to '\\' and '"'
          to '\"'.

          Possible values of this first value are along with an ordered
          list of basic_io formatted stanzas that will be provided are:

          'format_version'
                used in case this format ever needs to change.
                format: ('format_version', the string "1")
                occurs: exactly once
          'dir':
                represents a directory.  The path "" (the empty string) is used
                to represent the root of the tree.
                format: ('dir', pathname)
                occurs: one or more times
          'file':
                represents a file.
                format: ('file', pathname), ('content', file id)
                occurs: zero or more times

          In addition, 'dir' and 'file' stanzas may have attr
          information included.  These are appended to the stanza below
          the basic dir/file information, with one line describing each
          attr.  These lines take the form ('attr', attr name, attr
          value).

          Stanzas are sorted by the path string.

    *Error conditions:*
          If the revision ID specified is unknown or invalid prints an
          error message to stderr and exits with status 1.


`mtn automate get_attributes PATH'

    *Arguments:*
          The argument PATH determines which path's attributes should
          be printed.

    *Added in:*
             * 11.0 - removed the `format_version' stanza

             * 5.0 - renamed from `attributes' to `get_attributes'

             * 3.0 - initial

    *Purpose:*
          Prints all attributes of the given file and the attribute
          states.

    *Sample output:*
           attr "foo" "bar"
          state "added"

           attr "baz" "bat"
          state "dropped"

           attr "foobar" "foobat"
          state "unchanged"

    *Output format:*
          There is one basic_io stanza for each attribute of the given
          file.

          All stanzas are formatted by basic_io. Stanzas are separated
          by a blank line and ordered by attribute name. Values will be
          escaped, '\' to '\\' and '"' to '\"'.

          Each attribute stanza also contains another entry which tells
          the status of attribute. This entry can have one of the
          following four values:

             * 'added': the attribute has just been added to the file

             * 'dropped': the attribute has just been dropped from the
               file

             * 'unchanged': the attribute has not been changed since
               the last revision

             * 'changed': the attribute has been changed since the last
               revision

          The status 'changed' can come up if an attribute foo has been
          dropped and added afterwards with another value, like

          $ mtn attr drop file.txt foo ; mtn attr set file.txt foo baz

          If an attribute has been dropped, the output will still
          return the previously set value of the dropped attribute for
          convenience (obviously this is no longer recorded in the
          current workspace).

          The complete format:

          'attr':
                represents an attribute.
                format: ('attr', key, value), ('state', [unchanged|changed|added|dropped])
                occurs: zero or more times

    *Error conditions:*
          If the path specified is unknown in the new workspace
          revision, prints an error message to stderr and exits with
          status 1.


`mtn automate set_attribute PATH KEY VALUE'

    *Arguments:*
          A path, an attribute key and an attribute value.

    *Added in:*
          5.0

    *Purpose:*
          Edits the current workspace revision and inserts the given
          attribute key and value for the specified path. Note that
          this change is not committed and therefor behaves exactly
          like `mtn attr set KEY VALUE'.

    *Output format:*
          This command does not print out anything if successful.

    *Error conditions:*
          If the path specified is unknown in the new workspace
          revision, prints an error message to stderr and exits with
          status 1.


`mtn automate drop_attribute PATH [KEY]'

    *Arguments:*
          A path and an attribute key (optional).

    *Added in:*
          5.0

    *Purpose:*
          Removes an attribute from the current workspace revision for
          the specified path.  If no attribute key is given, all
          attributes of this path are removed. Note that this change is
          not committed and therefor behaves exactly like `mtn attr
          drop PATH [KEY]'.

    *Output format:*
          This command does not print out anything if successful.

    *Error conditions:*
          If the path specified is unknown in the new workspace
          revision or the attribute key is not found for this path,
          prints an error message to stderr and exits with status 1.


`mtn automate content_diff [--revision=ID1 [--revision=ID2]] [--reverse] [FILES ...]'

    *Arguments:*
          One or more FILE arguments restrict the diff output to these
          files, otherwise all changed files in the given revision(s)
          and/or current workspace are considered.

          If zero or more revisions are given, the command behaves as
          follows:

             * no revision: the diff is done from the parent (base)
               revision of this workspace to the workspace revision.

             * one revision: the diff is done from the given revision
               `id1' to the workspace revision. If `--reverse' is
               given, the order is reversed.

             * two revisions: the diff is done from `id1' to `id2'; no
               workspace is needed in this case.

    *Changes:*
             * 9.0 - added `--with-header' option

             * 4.0 - initial

    *Purpose:*
          Prints the content changes between two revisions or a
          revision and the current workspace. This command differs from
          `mtn diff' in that way that it only outputs content changes
          and keeps quiet on renames or drops by default, as the header
          of `mtn diff' is omitted unless `--with-header' is given and
          is omitted regardless if there are no changes.

    *Sample output:*
          ============================================================
          --- guitone/res/i18n/guitone_de.ts      9857927823e1d6a0339b531c120dcaadd22d25e9
          +++ guitone/res/i18n/guitone_de.ts      0b4715dc296b1955b0707923d45d79ca7769dd3f
          @@ -1,6 +1,14 @@
           <?xml version="1.0" encoding="utf-8"?>
           <!DOCTYPE TS><TS version="1.1">
           <context>
          +    <name>AncestryGraph</name>
          +    <message>
          [...]

    *Output format:*
          The GNU unified diff format. If there have been no content
          changes, the output is empty.

    *Error conditions:*
          If more than two revisions are given or a workspace is
          required, but not found, prints to stderr and exits with
          status 1. If one or more file restrictions can't be applied,
          the command prints to stderr and exits as well.


`mtn automate get_file ID'

    *Arguments:*
          The  ID argument specifies the file hash of the file to be
          output.

    *Added in:*
          1.0

    *Purpose:*
          Prints the contents of the specified file.

    *Sample output:*
          If you've downloaded a release, see INSTALL for installation
          instructions.  If you've checked this out, the generated files are not
          included, and you must use "autoreconf --install" to create them.

          "make html" for docs, or read the .info file and / or man page.

    *Output format:*
          The file contents are output without modification.

    *Error conditions:*
          If the file id specified is unknown or invalid prints an
          error message to stderr and exits with status 1.


`mtn automate get_file_of FILENAME [--revision=ID]'

    *Arguments:*
          The  FILENAME argument specifies the filename of the file to
          be output.

          If a revision ID is given, the file's contents in that
          specific revision are printed. If no revision is given, the
          workspace's revision is used.

    *Added in:*
          4.0

    *Purpose:*
          Prints the contents of the specified file.

    *Sample output:*
          If you've downloaded a release, see INSTALL for installation
          instructions.  If you've checked this out, the generated files are not
          included, and you must use "autoreconf --install" to create them.

          "make html" for docs, or read the .info file and / or man page.

    *Output format:*
          The file contents are output without modification.

    *Error conditions:*
          If the filename specified is unknown in the given revision or
          invalid, or if the given revision is unknown, prints an error
          message to stderr and exits with status 1.


`mtn automate file_merge LEFT-RID LEFT-PATH RIGHT-RID RIGHT-PATH'

    *Arguments:*
          LEFT-RID, LEFT-FID, RIGHT-RID, RIGHT-FID specify two files to
          merge, by revision and file path.

    *Added in:*
          9.0

    *Purpose:*
          Prints the result of the internal line merge on the contents
          of the specified files.

          This command does not just take two file ids, because the
          revision ids and paths are needed to check for manual merge
          and file encoding attributes.

    *Sample output:*
          If you've downloaded a release, see INSTALL for installation
          instructions.  If you've checked this out, the generated files are not
          included, and you must use "autoreconf --install" to create them.

          "make html" for docs, or read the .info file and / or man page.

    *Output format:*
          The file merge results are output without modification.

    *Error conditions:*
          If either file id is unknown or invalid, or if the internal
          line merger fails, prints an error message to stderr and
          exits with status 1.


`mtn automate get_option OPTION'

    *Arguments:*
          The OPTION argument specifies the option name of the option
          to be output.

    *Added in:*
          3.1

    *Purpose:*
          Prints an option from _MTN/option of the current workspace.

    *Sample output:*
          net.venge.monotone

    *Output format:*
          The option value is written out without modification.

    *Error conditions:*
          If the option is unknown, prints an error message to stderr
          and exits with status 1.


`mtn automate keys'

    *Arguments:*
          None.

    *Changes:*
             * 11.0 - Instead of having a "name" item, there are
               "given_name" and "local_name" items.

             * 10.0 - The separate hashes for the private half of a key
               really didn't make much sense; have one `hash [...]'
               line instead of separate `public_hash [...]' and
               `private_hash [...]' lines.

             * 1.1 - initial


    *Purpose:*
          Print all keys in basic_io format.

    *Sample output:*
                      hash [475055ec71ad48f5dfaf875b0fea597b5cbbee64]
                given_name "tbrownaw@gmail.com"
                local_name "tbrownaw@gmail.com"
           public_location "database" "keystore"
          private_location "keystore"

                     hash [3ac4afcd86af28413b0a23b7d22b9401e15027fc]
                given_name "tomfa@debian.org"
                local_name "tomfa@debian.org"
          public_location "database"

                      hash [115fdc73d87a5e9901d018462b21a1f53eca33a1]
                given_name "underwater@fishtank.net"
                local_name "underwater@fishtank.net"
           public_location "keystore"
          private_location "keystore"

    *Output format:*
          For each key, a basic_io stanza is printed. The
          public_location and private_location items may have multiple
          values as shown above for public_location, one value for each
          place that the key is stored. If the private key does not
          exist, then the private_hash and private_location items will
          be absent. given_name is the name provided when the key was
          created, and local_name is the name returned by the
          `get_local_key_name' hook.

          The keys are ordered by hash value.

    *Error conditions:*
          None.


`mtn automate packet_for_rdata ID'

    *Arguments:*
          The ID specifies the revision to output an rdata packet for.

    *Added in:*
          2.0

    *Purpose:*
          Prints the revision data in packet format

    *Sample output:*
          [rdata bdf3b10b5df0f17cc6c1b4b3351d84701bda59ed]
          H4sIAAAAAAAA/0XQS27DMAwE0L1PIfgArb4kte62NzACg5SoJEBsF7aRurev0UVzgJl5mLas
          E+/jU9ftvsymd33Xzfo9Tjzfm267GSgGwVarz6Valx0KtFYwii9VqUFCqJQ5X7puedRx1ef9
          r2rwHlSbi+BUSrF4xn1p0RInkmxTbmwREp/BL97LzfQfN56v+rlc+860dZnMED01jhILkURJ
          Ul0KPpGN1ueUwDHyiXF66Ywx+2IGD+0Uqg8aCzikAEzZNRXPmJKlkhMxSHuNzrofx/uq2/J4
          6njV/bZsu/zMPOlbOY4XJSD5KOrwXGdwpDGdfotZayQHKTAi5fRPqUWKcAMMIQfAjOK0nkfm
          6tFacjYgBPV46X4BtlpiNYUBAAA=
          [end]

    *Output format:*
          Revision data in `monotone read' compatible packet format.

    *Error conditions:*
          If ID is unknown or invalid prints an error message to stderr
          and exits with status 1.


`mtn automate packet_for_certs ID'

    *Arguments:*
          The ID specifies the revision to output cert packets for.

    *Added in:*
          2.0

    *Purpose:*
          Prints the certs associated with a revision in packet format

    *Sample output:*
          [rcert bdf3b10b5df0f17cc6c1b4b3351d84701bda59ed
                 branch
                 njs@pobox.com
                 bmV0LnZlbmdlLm1vbm90b25l]
          K90i1XHHmaMEMuwbPifFweLThJl0m7jigh2Qq6Z7TBwNJ6IMOjXWCizv73cacZ1CtzxFDVwQ
          SlqhNWiPQWxdcMp+Uuo+V8IFMKmvxVSTuVDukLMuNAQqpGL5S+a+tEj68NMq+KLKuL8kAAPc
          RoFD7GQlTS35S3RHWA4cnvqn+8U=
          [end]
          [rcert bdf3b10b5df0f17cc6c1b4b3351d84701bda59ed
                 date
                 njs@pobox.com
                 MjAwNi0wNC0wOFQxMTo1MDowMA==]
          araz9A8x6AlK6m6UhwnhUhk7cdyxeE2nvzj2gwaDvkaBxOq4SN23/wnaPqUXx1Ddn8smzyRY
          HN08xloYc0yNChp3wjbqx20REcsTg3XE4rN/sgCbqqw5hVT22a5ZhqkfkDeoeJvan0R0UBax
          ngKYo9eLuABNlmFX2onca75JW1E=
          [end]
          [rcert bdf3b10b5df0f17cc6c1b4b3351d84701bda59ed
                 author
                 njs@pobox.com
                 bmpzQHBvYm94LmNvbQ==]
          BLPOYhgLsAN+w7CwOsv9GfXnG3u7RNF1DTrWdn0AnYE1e+ptgTeMVWUI18H4OGL0B7wm08rv
          Pxk/hvsb8fBn1Kf5HDDO2pbjJ0xVzI9+p+TR0y5jJNZlVSTj+nvtPgvK9NzsdooYWnwlWmJv
          bOkAzQcZb8NMh8pbQkdHbR5uzMo=
          [end]
          [rcert bdf3b10b5df0f17cc6c1b4b3351d84701bda59ed
                 changelog
                 njs@pobox.com
                 MjAwNi0wNC0wOCAgTmF0aGFuaWVsIFNtaXRoICA8bmpzQHBvYm94LmNvbT4KCgkqIG5ldHh4
          L3Jlc29sdmVfZ2V0aG9zdGJ5bmFtZS5jeHggKHJlc29sdmVfaG9zdG5hbWUpOiAjaWZkZWYg
          b3V0CglXaW4zMi1pbmNvbXBhdGlibGUgZXJyb3IgcmVwb3J0aW5nIGNhbGwuCg==]
          Ncl4L/oEPctzVQixTKA6FrLceeHnLiXfeyeFDNmtUFYg9BMUcjWkeyKmaWknLvOcHortxjto
          K6pQ9E8S7zI+TpzFAhssg5a///rFL0+2GJU3t6pcHs6LC0Q4tbqzwKd/5+8GwT1gphbM1wm7
          KuzKthwqD3pp49GbgTrp8iWMTr0=
          [end]

    *Output format:*
          Cert data in `monotone read' compatible packet format.

    *Error conditions:*
          If ID is unknown or invalid prints an error message to stderr
          and exits with status 1.


`mtn automate packet_for_fdata ID'

    *Arguments:*
          The ID specifies the file to output an fdata packet for.

    *Added in:*
          2.0

    *Purpose:*
          Prints the file data in packet format

    *Sample output:*
          [fdata 229c7f621b65f7e4970ae5aaec993812b9daa1d4]
          H4sIAAAAAAAA/z2OO27DMBBEe51ioMaNrJzBpQAjTXKBBTW0CJPcgFw6yO1DCkG62Q/em83j
          R9vlRez6naPKzh2CwkipXFBJbO8fn7f7HV4LQq4mMYoFzdMYSnMj1xXY/lnuoHt2kB2hQpst
          PREPZhaxvvchskIKkdU6xsXWvQsk76MOUquGVolZmmmh0+xxvf7JZ5jCFXbU4KZ1muYkT+Kw
          FOez5q6uLuh9+9eoQawhez3Fp+VtHJNkfMmDHfALzWYfcAgBAAA=
          [end]

    *Output format:*
          File data in `monotone read' compatible packet format.

    *Error conditions:*
          If ID is unknown or invalid prints an error message to stderr
          and exits with status 1.


`mtn automate packet_for_fdelta FROM-ID TO-ID'

    *Arguments:*
          The FROM-ID specifies the file to use as the base of the
          delta, and TO-ID specifies the file to use as the target of
          the delta.

    *Added in:*
          2.0

    *Purpose:*
          Prints the file delta in packet format

    *Sample output:*
          [fdelta 597049a62d0a2e6af7df0b19f4945ec7d6458727
                  229c7f621b65f7e4970ae5aaec993812b9daa1d4]
          H4sIAAAAAAAA/0WOy0oEMRBF9/mKS2/c9LQg4t5lw+BGf6BIKtNhkpSkKop/b9II7m49OOfu
          eHp5dnvEj/SHL0aQ75qFAgcQGmcm5RXKjP3t/eP1ekWUhlTVKGeyJNXNoXU/s27AP8sf7O8D
          ZEdSSLd1JMaNKzeysY8ps4Iao4oNjM99eFdQDbMOSldDV8ZC3aSxlxpxufzJF5jANx6oyS2b
          c0uhO+OwkpezZhCvK0bf8TVrMLZUo5zi0/I4j4UqPunGA+B+AfHvKEIPAQAA
          [end]

    *Output format:*
          File delta data in `monotone read' compatible packet format.

    *Error conditions:*
          If FROM-ID or TO-ID is unknown or invalid prints an error
          message to stderr and exits with status 1.


`mtn automate get_content_changed ID FILE'

    *Arguments:*
          The ID specifies a revision ID, from which content change
          calculations will be based.  and FILE specifies the file for
          which to calculate revisions in which it was last changed.

    *Added in:*
          4.0

    *Purpose:*
          Returns a list of revision IDs in which the content  was most
          recently changed, relative to the revision ID specified as
          ID. This equates to a content mark following the *-merge
          algorithm.

    *Sample output:*
            content_mark [276264b0b3f1e70fc1835a700e6e61bdbe4c3f2f]

    *Output format:*
          Zero or more basic_io stanzas, each specifying a revision ID
          in which a content mark is set:

             * No content mark is returned if FILE is a directory.

             * One content mark is returned if FILE is a file and has
               recently been changed exclusively in one revision (be it
               by a commit or merge).

             * Multiple content marks are returned if FILE is a file
               and has recently been part of a clean merge case.  A
               clean merge happens when the same change to FILE is made
               on both sides of the particular merge, together with
               other unrelated changes, which make the resulting
               revisions not collapse into one revision.

          The complete format: 'content_mark'
                   the hexadecimal id of the revision the content mark is attached to

    *Error conditions:*
          If ID or FILE is unknown or invalid prints an error message
          to stderr and exits with status 1.


`mtn automate get_corresponding_path SOURCE_ID FILE TARGET_ID'

    *Arguments:*
          The SOURCE_ID specifies a revision ID in which FILE is
          current extant.  and FILE specifies the file whose name in
          TARGET_ID is to be determined; TARGET_ID specifies a revision
          ID.

    *Added in:*
          4.0

    *Purpose:*
          Given a the file name FILE in the source revision SOURCE_ID,
          a filename will if possible be returned naming the file in
          the target revision TARGET_ID.  This allows the same file to
          be matched between revisions, accounting for renames and
          other changes.

    *Sample output:*
          file "foo"

    *Output format:*
          Zero or one basic_io stanzas. Zero stanzas will be output if
          the file does not exist within the target revision; this is
          not considered an error. If the file does exist in the target
          revision, a single stanza with the  following details is
          output.

          The complete format:    'file'
                   the file name corresponding to "file name" (arg 2) in the target revision

    *Error conditions:*
          If the revision IDs SOURCE_ID or TARGET_ID are unknown or
          invalid prints an error message to stderr and exits with
          status 1. If the file path FILE does not exist in the
          revision SOURCE_ID or is invalid, prints an error message to
          stderr and exits with status 1. Note that FILE not existing
          in the revision TARGET_ID is not an error.


`mtn automate get_db_variables [DOMAIN]'

    *Arguments:*
          The optional DOMAIN restricts the output to variables only
          within this domain.

    *Changes:*
             * 7.0 - converted output to basic_io, renamed to
               'get_db_variables'

             * 4.1 - added as 'db_get'

    *Purpose:*
          Reads and outputs database variables. For more information
          about variables, see *note Vars::.

    *Sample output:*
          domain "database"
           entry "default-exclude-pattern" ""
           entry "default-include-pattern" "net.venge.monotone*"
           entry "default-server" "monotone.ca"

          domain "known-servers"
           entry "monotone.ca" "3e6f5225bc2fffacbc20c9de37ff2dae1e20892e"
           entry "monotone.mtn-host.prjek.net" "a52f85615cb2445989f525bf17a603250381a751"
           entry "venge.net" "70a0f283898a18815a83df37c902e5f1492e9aa2"

    *Output format:*
          basic_io-formatted stanzas. Each stanza starts with a
          'domain', followed by one or more 'entry' lines. Each 'entry'
          contains the NAME and the VALUE of the respective database
          variable.

    *Error conditions:*
          If the domain is unknown or no variables where found, prints
          an error message to stderr and exits with status 1.


`mtn automate set_db_variable DOMAIN NAME VALUE'

    *Arguments:*
          The DOMAIN and NAME specify the database variable which is
          changed to VALUE.

    *Changes:*
             * 7.0 - renamed to 'set_db_variable'

             * 4.1 - added as 'db_set'

    *Purpose:*
          Change a database variable, see also *note Vars::.

    *Sample usage:*
          mtn automate set_db_variable database default-server off.net

    *Output format:*
          No output.

    *Error conditions:*
          None.


`mtn automate drop_db_variables DOMAIN [NAME]'

    *Arguments:*
          The DOMAIN and NAME specify the database variable which
          should be dropped. If NAME is ommitted, all database
          variables in the DOMAIN are dropped.

    *Added in:*
          7.0

    *Purpose:*
          Drops one or more database variables, see also *note Vars::.

    *Sample usage:*
          mtn automate drop_db_variables known-servers

    *Output format:*
          No output.

    *Error conditions:*
          If the specific variable or any variables in the given domain
          are not found, prints to stderr and exits with status 1.


`mtn automate put_file [BASE-ID] CONTENTS'

    *Arguments:*
          The optional BASE-ID specifies a file-id on which the
          contents are based on. This is used for delta encoding.
          CONTENTS are the contents of the new file.

    *Added in:*
          4.1

    *Purpose:*
          Preparation of a workspace-less commit.  See also `automate
          put_revision'. Normally used via `automate stdio'.

    *Sample output:*
          70a0f283898a18815a83df37c902e5f1492e9aa2

    *Output format:*
          The sha1 sum of the contents, hex encoded.

    *Error conditions:*
          If the optional base id is unknown prints an error message to
          stderr and exits with status 1.


`mtn automate put_revision REVISION-DATA'

    *Arguments:*
          REVISION-DATA is the new revision. See example below.  Note
          that the new_manifest entry is ignored - `put_revision' will
          ignore whatever you put here and calculate the correct
          manifest id itself.  (However, for now, you must put 40 hex
          digits here - it's just that which particular digits you put
          are entirely irrelevant.  All zeros is a good choice.)
          Monotone will also canonicalize your whitespace
          automatically.  You do not need to worry about getting just
          the right amount of indentation in front of each line.
          However, everything else about your revision must be valid.

    *Added in:*
          4.1

    *Purpose:*
          Workspace-less commit. Normally used via `automate stdio'.

    *Sample argument:*
               format_version "1"

               new_manifest [0000000000000000000000000000000000000004]

               old_revision []

               add_dir ""

               add_file "foo"
               content [5bf1fd927dfb8679496a2e6cf00cbe50c1c87145]

    *Sample output:*
          4c2c1d846fa561601254200918fba1fd71e6795d

    *Output format:*
          The new revision id, hex encoded.

    *Error conditions:*
          If the changeset is invalid prints an error message to stderr
          and exits with status 1. May abort on invalid formats.  If
          the revision is already present in the database, prints a
          message to stderr noting this fact, but otherwise works as
          normal.


`mtn automate cert REVISION NAME VALUE'

    *Arguments:*
          REVISION is an existing revision, NAME is the certificate name
          and VALUE its value.

    *Added in:*
          4.1

    *Purpose:*
          `automate stdio' capable variant of `mtn cert'. To sign the
          cert with a specific private key, use `--key'.

    *Sample usage:*
          mtn automate cert 4c2c1d846fa561601254200918fba1fd71e6795d author tester@test.net

    *Output format:*
          No output.

    *Error conditions:*
          If the revision is invalid prints an error message to stderr
          and exits with status 1.


`mtn automate show_conflicts [-BRANCH BRANCH] [LEFT_REV RIGHT_REV]'

    *Arguments:*
          Optional left and right revision ids.

          If no revs are given, they default to the first two heads
          that would be chosen by the `merge' command for the current
          branch. If no workspace is present, the branch may be given
          by the -BRANCH option.

    *Changes:*
             * 11.0 - Add resolution for orphaned node conflicts.
               Deleted `resolved_user' conflict resolution; use
               `resolved_*_left' for single file conflicts. Add
               `resolved_keep_left, resolved_keep_right' resolutions.

             * 9.0 - Added default resolution for file content
               conflicts, user resolutions for others.
               `directory_loop_created' changed to `directory_loop'.

             * 8.0 - initial

    *Purpose:*
          Show all conflicts between two revisions.

          This is intended to be used before a `merge'; an external tool
          can guide the user thru resolving each conflict in turn, then
          do the merge.

          The same file format is output by the `conflicts store'
          command, which also allows specifying user conflict
          resolutions. The file syntax for the resolutions is given
          here, so an external tool can set them directly.

          For more information on conflicts, *note Merge Conflicts::.

          Note that this cannot be used to show conflicts that would
          occur in an `update', since in that case one revision is the
          workspace.

    *Sample output:*
          The output starts by listing the revisions and their common
          ancestor:     left [532ab5011ea9e64aa212d4ea52363b1b8133d5ba]
             right [b94a03a922c2c281a88d8988db64e76a32edb6a1]
          ancestor [ead03530f5fefe50c9010157c42c0ebe18086559]

          If there are no conflicts, the ancestor revision is not
          output, and no conflict stanzas are output.

          Attribute changed in both branches, or dropped in one:         conflict attribute
                 node_type "file"
                 attr_name "attr1"
             ancestor_name "foo"
          ancestor_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
                 left_name "foo"
              left_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
           left_attr_value "valueX"
                right_name "foo"
             right_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
          right_attr_value "valueZ"

                  conflict attribute
                 node_type "file"
                 attr_name "attr2"
             ancestor_name "foo"
          ancestor_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
                 left_name "foo"
              left_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
           left_attr_value "valueY"
                right_name "foo"
             right_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
          right_attr_state "dropped"

          Missing root directory:      conflict missing_root
              left_type "pivoted root"
          ancestor_name "foo"
             right_type "deleted directory"
          ancestor_name "foo"

          Directory deleted and/or renamed:      conflict orphaned_directory
             right_type "deleted directory"
          ancestor_name ""
              left_type "renamed directory"
          ancestor_name ""
              left_name "bar"

               conflict orphaned_file
             right_type "deleted directory"
          ancestor_name "foo"
              left_type "added file"
              left_name "foo/baz"
           left_file_id [f5122a7f896cb2dd7ecaa84be89c94ab09c15101]

                  conflict orphaned_file
                right_type "deleted directory"
             ancestor_name "foo"
                 left_type "renamed file"
             ancestor_name "bar"
          ancestor_file_id [ac4c6d06436632e017bb7d3ea241734e8899f8ce]
                 left_name "foo/baz"
              left_file_id [ac4c6d06436632e017bb7d3ea241734e8899f8ce]

               conflict multiple_names
              left_type "renamed directory"
          ancestor_name ""
              left_name "aaa"
             right_type "renamed directory"
          ancestor_name ""
             right_name "bbb"

               conflict duplicate_name
              left_type "renamed directory"
          ancestor_name "foo"
              left_name ""
             right_type "renamed directory"
          ancestor_name "bar"
             right_name ""

               conflict multiple_names
              left_type "renamed directory"
          ancestor_name "foo"
              left_name "a/foo"
             right_type "renamed directory"
          ancestor_name "foo"
             right_name "b/foo"

          Directory loop created:      conflict directory_loop
              left_type "renamed directory"
          ancestor_name "foo"
              left_name "bar/foo"
             right_type "renamed directory"
          ancestor_name "bar"
             right_name "foo/bar"

          File content changed (this may be resolvable by the internal
          line merger), file also renamed:          conflict content
                  node_type "file"
              ancestor_name "bar"
           ancestor_file_id [f0ef49fe92167fe2a086588019ffcff7ea561786]
                  left_name "bar"
               left_file_id [08cd878106a93ce2ef036a32499c1432adb3ee0d]
                 right_name "bar"
              right_file_id [0cf419dd93d38b2daaaf1f5e0f3ec647745b9690]
          resolved_internal

                  conflict content
                 node_type "file"
             ancestor_name "foo"
          ancestor_file_id [50bf338804db2685a575124c8c8371d06b65c523]
                 left_name "bar"
              left_file_id [f1bb6fff2ad16d67143d89fc374ede7abec5d437]
                right_name "baz"
             right_file_id [b966b2d35b99e456cb0c55e4573ef0b1b155b4a9]
           `resolved_internal' is a conflict resolution. If the file
          contents in the two revs can be successfully merged by the
          internal line merger, `resolved_internal' is output.

          File added and/or renamed:      conflict duplicate_name
              left_type "added file"
              left_name "bar"
           left_file_id [ba4637112ee3e55a6106d647d6c4e04a6643f8eb]
             right_type "added file"
             right_name "bar"
          right_file_id [fe6d523f607e2f2fc0f0defad3bda0351a95a337]

                  conflict duplicate_name
                 left_type "renamed file"
             ancestor_name "foo"
          ancestor_file_id [c6864a8456855c48afe83488a47501fe8b94bd57]
                 left_name "bar"
              left_file_id [c6864a8456855c48afe83488a47501fe8b94bd57]
                right_type "added file"
                right_name "bar"
             right_file_id [c809d71002ec57a2f1d10221f05993012a491436]

                  conflict duplicate_name
                 left_type "renamed file"
             ancestor_name "foo"
          ancestor_file_id [918f3642b57a5e2dd13ee874e3dc2518a53ab4b4]
                 left_name "abc"
              left_file_id [918f3642b57a5e2dd13ee874e3dc2518a53ab4b4]
                right_type "renamed file"
             ancestor_name "bar"
          ancestor_file_id [bdf46a521d5f1dd54c31dda15e99ff6b0c80394a]
                right_name "abc"
             right_file_id [bdf46a521d5f1dd54c31dda15e99ff6b0c80394a]

          File renamed to different names:         conflict multiple_names
                 left_type "renamed file"
             ancestor_name "foo"
          ancestor_file_id [e80910e54d0bdea1b6d295ada320b87aaf9fdc23]
                 left_name "bar"
              left_file_id [e80910e54d0bdea1b6d295ada320b87aaf9fdc23]
                right_type "renamed file"
             ancestor_name "foo"
          ancestor_file_id [e80910e54d0bdea1b6d295ada320b87aaf9fdc23]
                right_name "baz"
             right_file_id [e80910e54d0bdea1b6d295ada320b87aaf9fdc23]

          Invalid file name (`_MTN' in root directory):      conflict invalid_name
              left_type "pivoted root"
          ancestor_name "foo"
             right_type "added directory"
             right_name "foo/_MTN"

                  conflict invalid_name
                 left_type "pivoted root"
             ancestor_name "foo"
                right_type "renamed file"
             ancestor_name "bad/_MTN"
          ancestor_file_id [629d9e5d254241abf4b46f108fb53189e314e41d]
                right_name "foo/_MTN"
             right_file_id [629d9e5d254241abf4b46f108fb53189e314e41d]

          Revisions that don't share a common ancestor:     left [161e426c3b0c3f98d0be225f69d6f893ce8e0442]
             right [0e3260f51acd1e98c40666557eb6c0eefeae5f02]
          ancestor []

          conflict missing_root

            conflict duplicate_name
           left_type "added directory"
           left_name ""
          right_type "added directory"
          right_name ""

          All possible conflict resolutions:    resolved_drop_left
            resolved_drop_right
             resolved_keep_left
            resolved_keep_right
              resolved_internal
           resolved_rename_left file
          resolved_rename_right file
             resolved_user_left file
            resolved_user_right file
           For single file conflicts, the `resolved_*_left' resolution
          name is used.

          *Note Conflicts::, for more information on conflict
          resolutions.

    *Output format:*
          First the revision ids of the left and right revisions, and
          their common ancestor, are printed in one basic_io stanza.

          Then each conflict is listed in a basic_io stanza. Stanzas are
          separated by blank lines.

          Each conflict stanza starts with a `conflict' line, and
          contains up to eleven lines. The order of the lines is not
          important, and may change in future revisions, except that
          the first line will always be `conflict'.

          When the conflicts involve files, the file ids are output, so
          the file contents can be retrieved efficiently via `automate
          get_file', to aid in conflict resolution.

          Only the `resolved_internal' conflict resolution is output by
          this command; the other conflict resolutions are inserted in a
          conflicts file by `conflicts resolve_first' or an external
          tool, and read by `merge'.

    *Error conditions:*
          If the revision IDs are given, but either is unknown or
          invalid, prints an error message to stderr and exits with
          status 1.


`mtn automate get_workspace_root'

    *Arguments:*
          None.

    *Added in:*
          8.0

    *Purpose:*
          To show the path of the workspace root for the current
          directory.

    *Sample output:*
          /home/jim/juice

    *Output format:*
          A path.

    *Error conditions:*
          If the current directory isn't part of a workspace, prints an
          error to stderr and exits with status 1.


`mtn automate update'

    *Arguments:*
          Same as `mtn update'; no arguments, options
          -MOVE-CONFLICTING-PATHS, -REVISION=REVISION

    *Added in:*
          12.1

    *Purpose:*
          Update the current workspace to the latest or given revision;
          see `update' in *note Workspace::.

    *Sample output:*
          Nothing on stdout. stderr gives progress messages of the form: mtn: updating along branch 'mms.work_stephe'
          mtn: selected update target 233afb8c4832bf33d5f5734225164de5f5a6278c
          mtn: [left]  4a368a6b217c40b2ff3b12bb7cfa00987e0f191c
          mtn: [right] 233afb8c4832bf33d5f5734225164de5f5a6278c
          mtn: renaming build/windows_common.make to build/utf_common.make
          mtn: adding build/x86_gnu_linux_release

          These messages are in the 'p' stream in automate stdio.

    *Output format:*
          Free form, prefixed by "mtn:".

    *Error conditions:*
          see `update' in *note Workspace::.


`mtn automate read_packets PACKET-DATA'

    *Arguments:*
          A data packet, PACKET-DATA, as produced by `mtn pubkey
          KEYNAME'.

    *Added in:*
          9.0

    *Purpose:*
          Store public keys (and incidentally anything else that can be
          represented as a packet) into the database.

    *Output format:*
          No output.

    *Error conditions:*
          An error will be produced if the argument is not a valid
          packet.


`mtn automate lua FUNCTION_NAME [FUNCTION_ARGS...]'

    *Arguments:*
          A valid Lua function name and zero or more function
          arguments. Note that string arguments need to be wrapped in
          another pair of quotes, i.e. `"foo"' or `'foo'' will not
          work, but `"'foo'"' or `'"foo"'' will.

          Complex types are also supported, anything which can be
          evaluated as valid Lua expression can be given as input,
          including nested tables and functions, like f.e.
          `{1,true,{['func'] = function(...) return ... end }}'

    *Added in:*
          9.0

    *Purpose:*
          Call Lua functions, like monotone hooks, in the monotone
          context, f.e. to retrieve user defaults like keys, passwords,
          ignorable files and more.

    *Output format:*
          A string dump of the return value of the function, in Lua
          code. The Lua types `function', `thread', `userdata' and
          `lightuserdata' are not serialized, but set to `nil' in the
          dump.

          Please note that `nil' values in tables are not printed since
          Lua does not distinguish between unset and not existing
          entries in a table like other programming languages do.

    *Sample output:*
          A single string return value:

          [1] = "Output";

          Two numeric return values:

          [1] = 3;
          [2] = 4.4;

          A nested table:

          [1] = {
              ["bar"] = {
                  [1] = 1;
                  [2] = 2;
                  [3] = 3;
              };
          };

          A callback function:

          [1] = nil --[[function]];

    *Error conditions:*
          This command prints an error message and exists with status 1
          if the function does not exist, one or more function
          arguments could not be evaluated or the function could not be
          called for another reason.




File: monotone.info,  Node: RCS,  Next: GIT,  Prev: Automation,  Up: Command Reference

5.10 RCS
========

`mtn rcs_import FILENAME...'
     This command imports all the file versions in each RCS file listed
     in FILENAME....  These files should be raw RCS files, ending in
     `,v'. Monotone parses them directly and inserts them into your
     database.  Note that this does not do any revision reconstruction,
     and is only useful for debugging.

`mtn cvs_import PATHNAME'
     This command imports all the file versions in each RCS file found
     in the tree of files starting at PATHNAME, then reconstructs the
     tree-wide history of logical changes by comparing RCS time stamps
     and change log entries. For each logical tree-wide change, monotone
     synthesizes a manifest and revision, and commits them (along with
     all associated file deltas) to your database. It also copies all
     change log entries, author identifiers, and date stamps to
     manifest certificates.

     In normal use, PATHNAME will be a CVS module, though it is
     possible to point it at a directory within a module as well.
     Whatever directory you point it at will become the root of
     monotone's version of the tree.



File: monotone.info,  Node: GIT,  Prev: RCS,  Up: Command Reference

5.11 GIT
========

`mtn git_export [--authors-file=AUTHORS-FILE] [--branches-file=BRANCHES-FILE]'
`mtn git_export [--import-marks=MARKS-FILE] [--export-marks=MARKS-FILE]'
`mtn git_export [--log-revids] [--log-certs] [--use-one-changelog]'
`mtn git_export [--refs=TYPE]'
     This command exports all revisions from the current monotone
     database to `stdout' in a format that can be piped directly to git
     fast-import.

     The `--authors-file' option may be used to map monotone author and
     committer names to different values in a manner similar to that
     documented in git-svn(1). Mappings are specified in the
     AUTHORS-FILE as: loginname = Joe User <user@example.com>

     The list of authors that might need to be mapped can be extracted
     from a monotone database with the following sql query:

     $ mtn db execute 'select distinct value from revision_certs where name = "author"'

     The list of committers that might need to be mapped can be
     extracted from a monotone database with the following sql query:

     $ mtn db execute 'select distinct public_keys.name
                       from public_keys
                       left join revision_certs on revision_certs.keypair_id = public_keys.id
                       where revision_certs.name = "author"'

     The `--branches-file' option may be used to map monotone branch
     names to different values. This may be required as monotone allows
     branch names that are not valid according to git. Branch mappings
     are specified in the BRANCHES-FILE as:

     monotone-branch-name = git-branch-name

     Revisions with no author cert will use "Unknown <unknown>" for both
     the author and the committer. These can be mapped to other values
     using the AUTHORS-FILE option.

     The list of branches that might need to be mapped can be extracted
     from a monotone database with using the `ls branches' command:

     $ mtn ls branches --ignore-suspend-certs

     The `--import-marks' and `--export-marks' options are similar to
     those documented in git-fast-export(1) and git-fast-import(1).
     These may be used for incremental exports and may also be useful
     for repository verification. The MARKS-FILE is read on startup if
     `--import-marks' is specified and all marked revs are excluded
     from the export. The MARKS-FILE is written on completion if
     `--export-marks' is specified and will contain marks for all revs
     that were exported in addition to any marks that were read on
     startup. It is safe to use the same file for both `--import-marks'
     and `--export-marks' but different files may also be used.

     The original monotone revision ids may be included in the exported
     git commit messages using the `--log-revids' option. These will
     appear as:

     Monotone-Parent: ...
     Monotone-Revision: ...

     in the git commit messages and may be useful for repository
     verification. Merge revisions with two parents will include two
     `Monotone-Parent' lines.

     The original monotone values for `author', `date', `branch' and
     `tag' certificates may be included in the exported git commit
     messages using the `--log-certs' option. These will appear as:

     Monotone-Author: ...
     Monotone-Date: ...
     Monotone-Branch: ...
     Monotone-Tag: ...

     in the git commit messages and may be useful for repository
     verification or maintaining information that is otherwise not
     maintained by git. In particular monotone may have several values
     for each of these certs and git only represents a single `author'
     and `date' value.

     By default, the values of all changelog and comment certs on a
     revision are concatenated to form the git commit message for that
     revision. The `--use-one-changelog' option will prevent this
     behaviour and use the value from the first changelog cert
     encountered. _WARNING:_ this will explicitly lose information in
     the exported data. Changelog certs have no implicit ordering, one
     will be selected arbitrarily to be used as the git commit message
     and all others will be excluded from the exported data.
     Additionally, all comment certs will be excluded from the exported
     data.

     References to the original monotone branches and tags are exported
     as `refs/tags/<tag-name>' and `refs/heads/<branch-name>'. In
     addition, references to the original monotone revision ids, the
     root revisions and the leaf revisions may be exported using
     `--refs=revs', `--refs=roots' and `--refs=leaves' respectively.
     These references are exported as `refs/mtn/revs/<id>',
     `refs/mtn/roots/<id>' and `refs/mtn/leaves/<id>' and may be useful
     for repository verification. These additional references should
     probably not be maintained after the exported repository has been
     verified as they cause considerable clutter in tools like gitk.



File: monotone.info,  Node: Lua Reference,  Next: Special Topics,  Prev: Command Reference,  Up: Top

6 Lua Reference
***************

Monotone makes use of the Lua (http://www.lua.org) programming language
to customize and extend its behaviour.  By writing "functions" which
are loaded and evaluated at runtime, you can help monotone to make a
particular decision, set a suitable default or preference or perform a
certain action.

   You can put Lua functions in a file `$HOME/.monotone/monotonerc', or
in your workspace in `_MTN/monotonerc', both of which will be read
every time monotone runs. Definitions in `_MTN/monotonerc' shadow
(override) definitions made in your `$HOME/.monotone/monotonerc'. You
can also tell monotone to interpret extra hook functions from any other
FILE using the `--rcfile=FILE' option; hooks defined in files specified
on the command-line will shadow hooks from the other predefined
locations.  By specifying `--rcfile=DIRECTORY' you can automatically
load all the files contained in DIRECTORY.

   There are two uses for Lua functions; hooks and user-defined
commands. This section documents hooks; see `register_command' in *note
Additional Lua Functions:: for user-defined commands. The source
distribution contains some example user commands in the
`contrib/command' directory.

   Hooks are Lua functions that are called from monotone code in many
places. Monotone provides default definitions for some hooks; see *note
Default hooks:: for their complete source. For other hooks, if no
definition is provided a default return value is used. When writing new
hooks, it may be helpful to reuse some code from the default ones.
Since Lua is a lexically scoped language with closures, this can be
achieved with the following code:

     do
         local old_hook = default_hook
         function default_hook(arg)
             if not old_hook(arg) then
                 -- do other stuff
             end
         end
     end

   Now the default hook is trapped in a variable local to this block,
and can only be seen by the new hook. Since in Lua variables default to
the global scope, the new hook is seen from inside monotone.

   Monotone also provides a number of helper functions to hook writers
exposing functionality not available with standard Lua.

* Menu:

* Hooks::                       All hooks called by monotone.
* Additional Lua Functions::    Extra functionality available to hook writers.
* Implementation Differences::  Functional differences from standard Lua


File: monotone.info,  Node: Hooks,  Next: Additional Lua Functions,  Prev: Lua Reference,  Up: Lua Reference

6.1 Hooks
=========

This section documents the existing hook functions and their default
definitions.

6.1.1 Common Data Types
-----------------------

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'
     When a key is created, it is given a meaningful name. Because this
     is chosen by the key creator and may be unreliable, trust hooks
     need to be able to look at the key hash as well. This may be
     inconvenient, so a local alias is also provided.  This alias is
     obtained from an other hook, which can provide reliable easy-to-use
     names based on the key hash (or however else you want).

          {
             id = "key hash/fingerprint, in hex",
             given_name = "name given when creating the key",
             name = "local alias of the key"
          }


6.1.2 Event Notifications and Triggers
--------------------------------------

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)'
     Called by monotone after the version NEW_ID is committed. The
     second parameter, REVISION is the text of the revision, what would
     be given by `mtn automate get_revision NEW_ID'. The third
     parameter, CERTS, is a Lua table containing the set of certificate
     names and values committed along with this version. There is no
     default definition for this hook.

     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)'
     Called by monotone before any other of the netsync notification
     hooks are called.  The SESSION_ID helps keep track of the current
     netsync session in case several are happening at the same time,
     and is used throughout all netsync notification hooks.

     The other arguments are:

    *MY_ROLE*
          This will be either "client" or "server".

    *SYNC_TYPE*
          This will be one of "sync", "push", or "pull".

    *REMOTE_HOST*
          The network address of the remote host. At the client, this
          will be the name it was told to connect to; at the server,
          this will use the numerical IP address the connection was
          received from.

    *REMOTE_KEY*
          The identity of the key being used by the other end of the
          connection. The fields may be empty at the server if the key
          used by the client is not present at the server.

    *INCLUDES and EXCLUDES*
          The include and exclude patterns used by the client.


`note_netsync_revision_received (NEW_ID, REVISION, CERTS, SESSION_ID)'
     Called by monotone after the revision NEW_ID is received through
     netsync. REVISION is the text of the revision, what would be given
     by `mtn automate get_revision NEW_ID'. CERTS is a Lua table
     containing one subtable for each cert attached to the revision
     NEW_ID. These subtables have fields named "key", "name", and
     "value", containing the identity of the signing key for the cert,
     the name of the cert, and the value of the cert. There is no
     default definition for this hook.  SESSION_ID is used together
     with `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)'
     Called by monotone after the revision REV_ID is sent through
     netsync. The arguments are the same as for
     NOTE_NETSYNC_REVISION_RECEIVED.

`note_netsync_cert_received (REV_ID, KEY_IDENTITY, NAME, VALUE, SESSION_ID)'
     Called by monotone after a cert is received through netsync, if
     the revision that the cert is attached to was not also received in
     the same netsync operation. REV_ID is the revision id that the
     cert is attached to, KEY_IDENTITY is the key that the cert is
     signed with, NAME is the name of the cert, and VALUE is the cert
     value. There is no default definition for this hook.  SESSION_ID
     is used together with `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)'
     Called by monotone after a cert is sent through netsync, if the
     revision that the cert is attached to was not also sent in the
     same netsync operation. The arguments are the same as for
     NOTE_NETSYNC_CERT_RECEIVED.

`note_netsync_pubkey_received (KEY_IDENTITY, SESSION_ID)'
     Called by monotone after a pubkey is received through netsync.
     KEY_IDENTITY is the identity of the key received. There is no
     default definition for this hook.  SESSION_ID is used together
     with `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)'
     Called by monotone after a pubkey is sent through netsync. The
     arguments are the same as for NOTE_NETSYNC_PUBKEY_RECEIVED.

`note_netsync_end (SESSION_ID, STATUS, BYTES_IN, BYTES_OUT, CERTS_IN, CERTS_OUT, REVS_IN, REVS_OUT, KEYS_IN, KEYS_OUT)'
     Called by monotone after all other the netsync notification hooks
     have been called.  This hook would usually be used for
     post-netsync purposes, like collecting all the data from all other
     netsync notification hooks, make some nice output from them and
     finally send the result somewhere.  It could also be used to
     prepare parallel databases with all the data to be displayed
     through something like viewmtn.

     STATUS is a three digit integer that tells whether there was an
     error, and if so what kind of error it was:

    *200*
          No error, connection successful.

    *211*
          The connection was interrupted after some data may have been
          transferred.

    *212*
          The connection was interrupted before any data could be
          transferred.

    *412*
          The request is not permitted.

    *422*
          The client tried to use a key that the server doesn't know
          about.

    *432*
          The client and server have different epochs for a branch.

    *512*
          Protocol error (source/sink confusion).

    *521*
          Protocol error (packet received at a time when it doesn't
          make sense).

    *532*
          The client did not identify itself correctly. (Possible
          replay attack?)


     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 (...)'
     Called by monotone when it is first started, this hook was added
     so that usage of monotone could be monitored for user interface
     testing.  Note that by default, no monitoring occurs.  The
     arguments to the hook function are the arguments to monotone,
     without the initial `mtn' command.  They can be accessed through
     the lua ARG variable as in this example:

          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


6.1.3 User Defaults
-------------------

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)'
     Returns a string which is the name or hash of an RSA private key
     used to sign certificates in a particular branch BRANCHNAME. There
     is no default definition for this hook. The command-line option
     `--key=KEYNAME' overrides any value returned from this hook
     function. If you have only one private key in your database, you
     do not need to define this function or provide a `--key=KEYNAME'
     option; monotone will guess that you want to use the unique
     private key.

`get_netsync_key(SERVER, INCLUDE, EXCLUDE)'
     Returns a string which is the name or hash of the key to use to
     authenticate the given netsync connection. When called by the
     `serve' command, SERVER is the address monotone is listening on,
     INCLUDE is `"*"', and EXCLUDE is `""'.

     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)'
     Returns a table of program options, either valid for the given
     command or valid global options. The COMMAND argument is given as
     a table of command parts, i.e. for commands with subcommands like
     `automate' or `db' this argument contains at least two elements.

     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)'
     Returns a string which is the passphrase used to encrypt the
     private half of KEY_IDENTITY in your key store, using the
     TRIPLEDES symmetric cipher.  This hook has no default definition.
     If this hook is not defined or returns false, monotone will prompt
     you for a passphrase each time it needs to use a private key.

`get_local_key_name (KEY_IDENTITY)'
     Return the local alias for the given key. The ID and GIVEN_NAME
     fields of KEY_IDENTITY will be populated, and the NAME field will
     not be. The return value indicates what the NAME field should
     contain. The default implementation make this the same as
     GIVEN_NAME.

`get_author (BRANCHNAME, KEY_IDENTITY)'
     Returns a string which is used as a value for automatically
     generated `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

`get_default_database_locations ()'
     Returns a table of paths where monotone should look for managable
     databases.  The command `list databases' searches all these paths
     for valid monotone databases and outputs details on each one.

     The default implementation returns a table with a single entry,
     `$HOME/.monotone/databases' on Unix and
     `%APPDATA%\monotone\databases' on Windows.

`get_default_database_alias ()'
     Returns the alias of the managed database which should be used as
     default for commands like `clone' or `setup' if these are missing
     an explicit database option.  This alias and the first path found
     in the `get_default_database_locations' hook form the complete path
     of this default database.

     The default implementation returns `:default.mtn'.

`edit_comment (USER_LOG_MESSAGE)'
     Returns a log entry for a given set of changes, described in
     USER_LOG_MESSAGE.  The user_log_message is identical to the output
     of `mtn status'. This hook is intended to interface with some sort
     of editor, so that you can interactively document each change you
     make. Values for `author', `date', `branch' and the `changelog'
     are extracted from the result and used to generate these
     certificates when you commit changes.

     The contents of `_MTN/log' are read and passed as as the
     `changelog' value in 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 *note Default hooks::.

`persist_phrase_ok ()'
     Returns `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 ()'
     Returns `true' if you want monotone to automatically enable *note
     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)'
     Returns `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 *note Default hooks::.

`ignore_branch (BRANCHNAME)'
     Returns `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)'
     Returns a `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.

     The `date_time_long' format is used by the `status', `commit' and
     `log' commands to format revision dates for printing. This format
     must preserve a date passed through a formatting and parsing
     cycle. Otherwise the `status' command will issue warnings that the
     format is unsuitable and the `commit' command will abort.


6.1.4 Netsync Permission Hooks
------------------------------

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)'
     Returns `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)'
     Returns `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 *note Trust Evaluation Hooks::
     instead.

`get_remote_automate_permitted(KEY_IDENTITY, COMMAND, OPTIONS)'
     Returns true if a peer authenticated as key KEY_IDENTITY should be
     allowed to execute the given COMMAND with the given OPTIONS, as if
     through `automate stdio'.


6.1.5 Netsync Transport Hooks
-----------------------------

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)'
     Returns a table describing a command to run to connect to the
     specified host. The URI argument is a table containing between 0
     and 7 components:

        * `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)'
     Returns a boolean indicating whether monotone should use transport
     authentication mechanisms when communicating with URI. If this
     hook fails, the return value is assumed to be `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)'
     Returns a string containing the monotone command to be executed on
     HOST when communicating over `ssh'.  The HOST argument is a string
     containing the name of the host to which `ssh' is connecting, from
     the server URI.  This is useful when there are multiple monotone
     binaries on the remote host, or the monotone binary is not in the
     default path.

          function get_mtn_command(host)
              return "mtn"
          end


6.1.6 Trust Evaluation Hooks
----------------------------

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)'
     Returns whether or not you _trust_ the assertion NAME=VALUE on a
     given revision ID, given a valid signature from all the keys in
     SIGNERS. The SIGNERS parameter is a table containing all the key
     identities which signed this cert, the other three parameters are
     strings.

     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)'
     This hook is used by the update algorithm to determine whether a
     change in test results between update source and update target is
     acceptable. The hook is called with two tables, each of which maps
     a signing key - representing a particular testsuite - to a boolean
     value indicating whether or not the test run was successful. The
     function should return `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.


6.1.7 External Diff Tools
-------------------------

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)'
     Called for each file unless `diff' is given the
     `--no-show-encloser' option (or the `--external' option).
     FILE_PATH is the pathname of the file that is being diffed.  The
     hook should return a string constant containing a regular
     expression; this regular expression will be used to find lines
     that, in that file, name the "top-level" constructs enclosing each
     "hunk" of changes.  The default is `^[[: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.  *Note Regexps::, for the regular
     expression syntax.

`external_diff (FILE_PATH, OLD_DATA, NEW_DATA, IS_BINARY, DIFF_ARGS, OLD_REV, NEW_REV)'
     Called for each file when `diff' is given the `--external' option.
     FILE_PATH is the pathname of the file that is being diffed.
     OLD_DATA and NEW_DATA are the data contents of the old and the new
     file.  If the data is binary, IS_BINARY will be true, otherwise
     false.  OLD_REV and NEW_REV are the revision IDs of the old and
     new data.

     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.


6.1.8 External Merge Tools
--------------------------

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 *note 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)'
     This hook is called to resolve merges that monotone could not
     resolve automatically.  The actual ancestor, left, and right
     contents of the file are passed in the ANCESTOR_TEXT, LEFT_TEXT,
     and RIGHT_TEXT strings.  In addition, the hook is given the names
     that this file had in the ancestor (ANCESTOR_PATH), left
     (LEFT_PATH), and right (RIGHT_PATH) trees, and the name it will
     end up having in the merged tree (MERGED_PATH).  These paths are
     useful for merge tools that can display the names of files in
     their GUI, since the actual path names are likely more meaningful
     than the temporary file names the merge tool will actually be
     working on.

     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 *note get_preferred_merge3_command::.  The default
     definition of *note 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 *note Default hooks::.

`get_preferred_merge3_command(TBL)'
     Returns the results of running an external merge on three strings.
     TBL wraps up the various arguments for each merge command and is
     always provided by *note merge3::. If there is a particular editor
     that you would like to use to perform merge3 operations, override
     this hook to specify it.


6.1.9 Selector Expansion
------------------------

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 *note Selectors::.

`expand_selector (STR)'
     Attempts to expand STR as a selector. Expansion generally means
     providing a type prefix for the selector, such as `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 *note Default hooks::.

`expand_date (STR)'
     Attempts to expand STR as a date expression. Expansion means
     recognizing and interpreting special words such as `yesterday' or
     `6 months ago' and converting them into well formed date
     expressions. For the default definition of this hook, see *note
     Default hooks::.


6.1.10 Attribute Handling
-------------------------

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 *note Merging::), or they may represent executable scripts
or programs.

   Monotone allows each file (or directory) in a repository to carry
arbitrary *note 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)'
     This is not a hook function, but a _table_ of hook functions. Each
     entry in the table `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)'
     This is not a hook function, but a _table_ of hook functions. Each
     entry in the table `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
     *note Default hooks::.


6.1.11 GIT Export 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 *note Default hooks::.

`unmapped_git_author(AUTHOR)'
     This hook is called for any git author or committer value that does
     not come from the current _author map_ file. If no _author map_
     file is specified this hook will be called for _every_ unique git
     author and committer value.  It may return the value unchanged or
     modify it in some way in an effort to ensure that it is valid. The
     default implementation attempts several common pattern
     replacements to produce valid authors from monotone authors.

`validate_git_author(AUTHOR)'
     This hook is called before the git author or committer value is
     written to the export output stream. The AUTHOR value is either
     the mapped value from the current _author map_ file or the value
     produced by the `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.


6.1.12 Validation Hooks
-----------------------

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)'
     This hook is called after the user has entered his/her commit
     message.  MESSAGE is the commit message that the user has entered
     and REVISION_TEXT is the full text of the changes for this
     revision, which can be parsed with the parse_basic_io function.
     The BRANCHNAME on which the new revision will be committed if all
     goes well is passed in as the third parameter.  If the hook finds
     the commit message satisfactory, it can return `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.


6.1.13 Meta Hooks
-----------------

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, ...)'
     This hook is explicitely called on every execution of `automate
     lua'.  It takes a function name and zero or more string function
     arguments which are internally evaluated into Lua code. It returns
     a dump of the return value of the called function in Lua code on
     success.



File: monotone.info,  Node: Additional Lua Functions,  Next: Implementation Differences,  Prev: Hooks,  Up: Lua Reference

6.2 Additional Lua Functions
============================

This section documents the additional Lua functions made available to
hook writers.

`alias_command(ORIGINAL, ALIAS)'
     This function adds a new alias for a monotone command.  A call to
     this function would normally be placed directly in the
     `monotonerc' file, rather than in a hook function.

`change_workspace(DIRECTORY)'
     Change to workspace DIRECTORY, which may be absolute or relative
     to the directory that was current when mtn was started.

     Throws an error if DIRECTORY does not exist or is not a workspace
     (does not contain `_MTN').

     After calling change_workspace, the next operation should read the
     workspace options. `mtn_automate' does this; other Lua extensions
     do not. In addition, `automate stio' reads the workspace options
     before executing each command.

`existonpath(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, `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, `existonpath' would search for "xxdiff.exe".

`get_confdir()'
     Returns the path to the configuration directory, either implied or
     given with `--confdir'.

`get_ostype()'
     Returns the operating system flavor as a string.

`guess_binary_file_contents(FILESPEC)'
     Returns true if the file appears to be binary, i.e. contains one or
     more of the following characters:
          0x00 thru 0x06
          0x0E thru 0x1a
          0x1c thru 0x1f

`include(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.

`includedir(SCRIPTPATH)'
     This function loads and executes in alphabetical order all the
     scripts contained in the directory scriptpath.

     If one of the scripts has an error, the function doesn't process
     the remaining scripts and immediately returns false.

`includedirpattern(SCRIPTPATH, PATTERN)'
     This function loads and executes in alphabetical order all the
     scripts contained into the directory scriptpath that match the
     given pattern.  If one of the scripts has an error, the functions
     doesn't process the remaining scripts and immediately returns
     false.

`is_executable(FILESPEC)'
     This function returns true if the file is executable, false
     otherwise.  On Windows this function returns always false.

`kill(PID [, SIGNAL])'
     This function calls the kill() C library function on POSIX systems
     and TerminateProcess on Win32 (in that case PID is the process
     handle).  If the optional SIGNAL parameter is missing, SIGTERM
     will be used.  Returns 0 on success, -1 on error.

`make_executable(FILESPEC)'
     This function marks the named file as executable.  On Windows has
     no effect.

`match(GLOB, STRING)'
     Returns true if GLOB matches STR, return false otherwise.

`mkstemp(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.

     *Important notice:*
     To create a temporary file, you must use the `temp_file()'
     function, unless you need to run monotone with the `--nostd'
     option.  `temp_file()' builds on `mkstemp()' and creates a file in
     the standard TMP/TEMP directories.  For the definition of
     `temp_file()', see *note Default hooks::.

`mtn_automate( ... )'
     The `mtn_automate' Lua function calls the Monotone `automate'
     command passed in its arguments. The result of the call is a pair
     consisting of a boolean return code, indicating whether the call
     was successful or not, and a string being the `stdout' output from
     the `automate' command. This function is not for use in ordinary
     Lua hooks, but rather for Lua based commands as defined by the Lua
     function `register_command'.

     Note that keyboard interaction is disabled, just as if
     `--non-interactive' is specified. Actions which require operations
     on password-encrypted private keys will therefor fail unless the
     `get_passphrase' hook is set up locally.

`parse_basic_io(DATA)'
     Parse the string DATA, which should be in basic_io format. It
     returns nil if it can't parse the string; otherwise it returns a
     table. This will be a list of all statements, with each entry
     being a table having a "name" element that is the symbol beginning
     the statement and a "values" element that is a list of all the
     arguments.

     For example, given this as input:

          thingy "foo" "bar"
          thingy "baz"
          spork
          frob "oops"

     The output table will be:
          {
             1 = { name = "thingy", values = { 1 = "foo", 2 = "bar" } },
             2 = { name = "thingy", values = { 1 = "baz" } },
             3 = { name = "spork", values = { } },
             4 = { name = "frob", values = { 1 = "oops" } }
          }

`regex.search(REGEXP, STRING)'
     Returns true if a match for REGEXP is found in STR, return false
     otherwise.  *Note Regexps::, for the syntax of REGEXP.

`register_command(NAME, PARAMS, ABSTRACT, DESCRIPTION, FUNCTION)'
     Add a command named NAME to the USER command group in monotone.
     This function is normally called directly from a `monotonerc' file
     rather than a hook.  When the user issues the registered command,
     monotone will call the lua FUNCTION name supplied.  That function
     would then normally use mtn_automate() calls to service the
     request.

`server_request_sync(WHAT, ADDRESS, INCLUDE, EXCLUDE)'
     Initiate a netsync connection to the server at ADDRESS, with the
     given include and exclude patterns, of type `sync', `push', or
     `pull', as given by the WHAT argument.

     When called by a monotone instance which is not running the `serve'
     command, this function has no effect.

`server_set_listening(BOOLEAN)'
     If the argument is FALSE, make the server not listen for incoming
     connections, and exit when all existing connections have closed.

     If the argument is TRUE, cancel an earlier call with FALSE given.

`sleep(SECONDS)'
     Makes the calling process sleep for the specified number of
     seconds.

`spawn(EXECUTABLE [, 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.

     *Important notice:*
     To spawn a process and wait for its completion, use the `execute()'
     function, unless you need to run monotone with the `--nostd'
     option.  `execute()' builds on `spawn()' and `wait()' in a
     standardized way.

`spawn_pipe(EXECUTABLE [, ARGS ...])'
     Like spawn(), but returns three values, where the first two are the
     subprocess' standard input and standard output, and the last is the
     process PID on POSIX systems, the process handle on Win32 or -1 if
     there was an error.

`spawn_redirected(INFILE, OUTFILE, ERRFILE, EXECUTABLE [, ARGS ...])'
     Like spawn(), but with standard input, standard output and standard
     error redirected to the given files.

`wait(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.



File: monotone.info,  Node: Implementation Differences,  Prev: Additional Lua Functions,  Up: Lua Reference

6.3 Implementation Differences
==============================

This section documents disabled and overwritten functions from the
standard Lua libraries.

`print, io.write'
     Both functions are overwritten to print to standard error (instead
     of standard output), formatted as monotone progress message with
     the prefix "lua:" in front of every line.

     The rationale behind this is to catch most of the informational
     messages from hooks which use these functions and present them via
     monotone's user interface. This allows them to be logged just as
     other progress messages, and prevents unexpected out-of-band
     output in the *note Automation:: interface.

     If you explicitely need to write to either stdout or stderr,
     please use `io.stdout:write' and `io.stderr.write'.

`os.execute, io.popen'
     Both functions have been disabled for security reasons. You should
     use their replacements `spawn' and `spawn_pipe'.

     The original versions do not apply any kind of shell character
     escaping, which might lead to serious problems f.e. when a merger
     is automatically invoked by such a function.



File: monotone.info,  Node: Special Topics,  Next: Default hooks,  Prev: Lua Reference,  Up: Top

7 Special Topics
****************

This chapter describes some "special" issues which are not directly
related to monotone's _use_, but which are occasionally of interest to
people researching monotone or trying to learn the specifics of how it
works. Most users can ignore these sections.

* Menu:

* Internationalization::        Using monotone in non-English locales.
* Hash Integrity::              Notes on probability and failure.
* Rebuilding ancestry::         In case of corruption.
* Mark-Merge::                  The merging algorithm used by Monotone.
* Regexps::                     The syntax of regular expressions
                                  used by Monotone.


File: monotone.info,  Node: Internationalization,  Next: Hash Integrity,  Prev: Special Topics,  Up: Special Topics

7.1 Internationalization
========================

Monotone initially dealt with only ASCII characters, in file path
names, certificate names, key names, and packets. Some conservative
extensions are provided to permit internationalized use. These
extensions can be summarized as follows:

   * Monotone uses GNU gettext to provide localized progress and error
     messages. Translations may or may not exist for your locale, but
     the infrastructure is present to add them.

   * All command-line arguments are mapped from your local character
     set to UTF-8 before processing. This means that monotone can _only_
     handle key names, file names and certificate names which map
     cleanly into UTF-8.

   * Monotone's control files are stored in UTF-8. This includes:
     revisions and manifests, both inside the database and when written
     to the `_MTN/' directory of the workspace; the `_MTN/options' and
     `_MTN/revision' files. Converting these files to any other
     character set will cause monotone to break; do not do so.

   * File path names in the workspace are converted to the locale's
     character set (determined via the LANG or CHARSET environment
     variables) before monotone interacts with the file system. If you
     are accustomed to being able to use file names in your locale's
     character set, this should "just work" with monotone.

   * Key and cert names, and similar "name-like" entities are subject to
     some cleaning and normalization, and conversion into network-safe
     subsets of ASCII (typically ACE). Generally, you should be able to
     use "sensible" strings in your locale's character set as names,
     but they may appear mangled or escaped in certain contexts such as
     network transmission.

   * Monotone's transmission and storage forms are otherwise unchanged.
     Packets and database contents are 7-bit clean ASCII.


   The remainder of this section is a precise specification of
monotone's internationalization behavior.

General Terms
=============

Character set conversion
     The process of mapping a string of bytes representing wide
     characters from one encoding to another. Per-file character set
     conversions are specified by a Lua hook `get_charset_conv' which
     takes a filename and returns a table of two strings: the first
     represents the "internal" (database) charset, the second
     represents the "external" (file system) charset.

LDH
     Letters, digits, and hyphen: the set of ASCII bytes `0x2D',
     `0x30..0x39', `0x41..0x5A', and `0x61..0x7A'.

stringprep
     RFC 3454, a general framework for mapping, normalizing, prohibiting
     and bidirectionality checking for international names prior to use
     in public network protocols.

nameprep
     RFC 3491, a specific profile of stringprep, used for preparing
     international domain names (IDNs)

punycode
     RFC 3492, a "bootstring" encoding of Unicode into ASCII.

IDNA
     RFC 3490, international domain names for applications, a
     combination of the above technologies (nameprep, punycoding,
     limiting to LDH characters) to form a specific "ASCII compatible
     encoding" (ACE) of Unicode, signified by the presence of an
     "unlikely" ACE prefix string "xn-". IDNA is intended to make it
     possible to use Unicode relatively "safely" over legacy
     ASCII-based applications. the general picture of an IDNA string is
     this:

                {ACE-prefix}{LDH-sanitized(punycode(nameprep(UTF-8-string)))}

     It is important to understand that IDNA encoding does _not_
     preserve the input string: it both prohibits a wide variety of
     possible strings and normalizes non-equal strings to supposedly
     "equivalent" forms.

     By default, monotone does _not_ decode IDNA when printing to the
     console (IDNA names are ASCII, which is a subset of UTF-8, so this
     normal form conversion can still apply, albeit oddly). this
     behavior is to protect users against security problems associated
     with malicious use of "similar-looking" characters. If the hook
     `display_decoded_idna' returns true, IDNA names are decoded for
     display.


Filenames
=========

   * Filenames are subject to normal form conversion.

   * Filenames are subject to an additional normal form stage which
     adjusts for platform name semantics, for example changing the
     Windows `0x5C' '\' path separator to `0x2F' '/'. This extra
     processing is performed by boost::filesystem.

   * FIXME: Monotone does not properly handle case insensitivity on
     Windows.

   * A filename (in normal form) is constrained to be a nonempty
     sequence of path components, separated by byte `0x2F' (ASCII / ),
     and without a leading or trailing `0x2F'.

   * A path component is a nonempty sequence of any UTF-8 character
     codes except the path separator byte `0x2F' and any ASCII "control
     codes" (`0x00..0x1F' and `0x7F').

   * The path components "." and ".." are prohibited.

   * Manifests and revisions are constructed from the normal form
     (UTF-8). The LC_COLLATE locale category is _not_ used to sort
     manifest or revision entries.


File contents
=============

   * Files are subject to character set conversion and line ending
     conversion.

   * File SHA1 values are calculated from the internal form of the
     conversions. If the external form of a file differs from the
     internal form, running a 3rd party program such as `sha1sum' will
     produce different results than those entries shown in a
     corresponding manifest.


UI messages
===========

UI messages are displayed via calls to `gettext()'.

Host names
==========

Host names are read on the command-line and subject to normal form
conversion. Host names are then split at `0x2E' (ASCII '.'), each
component is subject to IDNA encoding, and the components are rejoined.

   After processing, host names are stored internally as ASCII. The
invariant is that a host name inside monotone contains only sequences
of LDH separated by `0x2E'.

Cert names
==========

Read on the command line and subject to normal form conversion and IDNA
encoding as a single component. The invariant is that a cert name
inside monotone is a single LDH ASCII string.

Cert values
===========

Cert values may be either text or binary, depending on the return value
of the hook `cert_is_binary'. If binary, the cert value is never
printed to the screen (the literal string "<binary>" is displayed,
instead), and is never subjected to line ending or character
conversion. If text, the cert value is subject to normal form
conversion, as well as having all UTF-8 codes corresponding to ASCII
control codes (`0x0..0x1F' and `0x7F') prohibited in the normal form,
except `0x0A' (ASCII LF).

Var domains
===========

Read on the command line and subject to normal form conversion and IDNA
encoding as a single component. The invariant is that a var domain
inside monotone is a single LDH ASCII string.

Var names and values
====================

Var names and values are assumed to be text, and subject to normal form
conversion.

Key names
=========

Read on the command line and subject to normal form conversion and IDNA
encoding as an email address (split and joined at '.' and '@'
characters). The invariant is that a key name inside monotone contains
only LDH, `0x2E' (ASCII '.') and `0x40' (ASCII '@') characters.

Packets
=======

Packets are 7-bit ASCII. The characters permitted in packets are the
union of these character sets:

   * The 65 characters of base64 encoding (64 coding + "=" pad).

   * The 16 characters of hex encoding.

   * LDH, '@' and '.' characters, as required for key and cert names.

   * '[' and ']', the packet delimiters.

   * ASCII codes 0x0D (CR), 0x0A (LF), 0x09 (HT), and 0x20 (SP).


File: monotone.info,  Node: Hash Integrity,  Next: Rebuilding ancestry,  Prev: Internationalization,  Up: Special Topics

7.2 Hash Integrity
==================

Some proponents of a competing, proprietary version control system have
suggested, in a usenix paper
(http://www.usenix.org/events/hotos03/tech/full_papers/henson/henson_html/),
that the use of a cryptographic hash function such as SHA1 as an
identifier for a version is unacceptably unsafe. This section addresses
the argument presented in that paper and describes monotone's
additional precautions.

   To summarize our position:
   * the analysis in the paper is wrong,

   * even if it were right, monotone is sufficiently safe.

The analysis is wrong
=====================

The paper displays a fundamental lack of understanding about what a
_cryptographic_ hash function is, and how it differs from a normal hash
function. Furthermore it confuses accidental collision with attack
scenarios, and mixes up its analysis of the risk involved in each. We
will try to untangle these issues here.

   A cryptographic hash function such as SHA1 is more than just a
uniform spread of inputs to an output range. Rather, it must be
designed to withstand attempts at:

   * reversal: deriving an input value from the output

   * collision: finding two different inputs which hash to the same
     output

   Collision is the problem the paper is concerned with. Formally, an
n-bit cryptographic hash should cost 2^n work units to collide against
a given value, and sqrt(2^n) tries to find a random pair of colliding
values. This latter probability is sometimes called the hash's
"birthday paradox probability".

Accidental collision
--------------------

One way of measuring these bounds is by measuring how single-bit
changes in the input affect bits in the hash output. The SHA1 hash has
a strong _avalanche property_, which means that flipping _any one bit_
in the input will cause on average half the 160 bits in the output code
to change. The fanciful VAL1 hash presented in the paper does not have
such a property -- flipping its first bit when all the rest are zero
causes _no change_ to any of the 160 output bits -- and is completely
unsuited for use as a _cryptographic hash_, regardless of the general
shape of its probability distribution.

   The paper also suggests that birthday paradox probability cannot be
used to measure the chance of accidental SHA1 collision on "real
inputs", because birthday paradox probability assumes a uniformly
random sample and "real inputs" are not uniformly random. The paper is
wrong: the inputs to SHA1 are not what is being measured (and in any
case can be arbitrarily long); the collision probability being measured
is of _output space_. On output space, the hash is designed to produce
uniformly random spread, even given nearly identical inputs. In other
words, it is _a primary design criterion_ of such a hash that a
birthday paradox probability is a valid approximation of its collision
probability.

   The paper's characterization of risk when hashing "non-random
inputs" is similarly deceptive. It presents a fanciful case of a
program which is _storing_ every possible 2kb block in a file system
addressed by SHA1 (the program is trying to find a SHA1 collision).
While this scenario _will_ very likely encounter a collision
_somewhere_ in the course of storing all such blocks, the paper
neglects to mention that we only expect it to collide after storing
about 2^80 of the 2^16384 possible such blocks (not to mention the
requirements for compute time to search, or disk space to store 2^80
2kb blocks).

   Noting that monotone can only store 2^41 bytes in a database, and
thus probably some lower number (say 2^32 or so) active rows, we
consider such birthday paradox probability well out of practical sight.
Perhaps it will be a serious concern when multi-yottabyte hard disks
are common.

Collision attacks
-----------------

Setting aside accidental collisions, then, the paper's underlying theme
of vulnerability rests on the assertion that someone will break SHA1.
Breaking a cryptographic hash usually means finding a way to collide it
trivially. While we note that SHA1 has in fact resisted attempts at
breaking for 8 years already, we cannot say that it will last forever.
Someone might break it. We can say, however, that finding a way to
trivially collide it only changes the resistance to _active attack_,
rather than the behavior of the hash on benign inputs.

   Therefore the vulnerability is not that the hash might suddenly cease
to address benign blocks well, but merely that additional security
precautions might become a requirement to ensure that blocks are
benign, rather than malicious. The paper fails to make this
distinction, suggesting that a hash becomes "unusable" when it is
broken. This is plainly not true, as a number of systems continue to
get useful low collision hashing behavior -- just not good security
behavior -- out of "broken" cryptographic hashes such as MD4.

Monotone is probably safe anyways
=================================

Perhaps our arguments above are unconvincing, or perhaps you are the
sort of person who thinks that practice never lines up with theory.
Fair enough. Below we present _practical_ procedures you can follow to
compensate for the supposed threats presented in the paper.

Collision attacks
-----------------

A successful collision attack on SHA1, as mentioned, does not disrupt
the _probability_ features of SHA1 on benign blocks. So if, at any
time, you believe SHA1 is "broken", it does _not_ mean that you cannot
use it for your work with monotone. It means, rather, that you cannot
base your _trust_ on SHA1 values anymore. You must trust who you
communicate with.

   The way around this is reasonably simple: if you do not trust SHA1
to prevent malicious blocks from slipping into your communications, you
can always augment it by enclosing your communications in more
security, such as tunnels or additional signatures on your email posts.
If you choose to do this, you will still have the benefit of
self-identifying blocks, you will simply cease to trust such blocks
unless they come with additional authentication information.

   If in the future SHA1 (or, indeed, RSA) becomes accepted as broken
we will naturally upgrade monotone to a newer hash or public key
scheme, and provide migration commands to recalculate existing
databases based on the new algorithm.

   Similarly, if you do not trust our vigilance in keeping up to date
with cryptography literature, you can modify monotone to use any
stronger hash you like, at the cost of isolating your own
communications to a group using the modified version. Monotone is free
software, and runs atop `botan', so it is both legal and relatively
simple to change it to use some other algorithm.


File: monotone.info,  Node: Rebuilding ancestry,  Next: Mark-Merge,  Prev: Hash Integrity,  Up: Special Topics

7.3 Rebuilding ancestry
=======================

As described in *note Historical records::, monotone revisions contain
the SHA1 hashes of their predecessors, which in turn contain the SHA1
hashes of _their_ predecessors, and so on until the beginning of
history.  This means that it is _mathematically impossible_ to modify
the history of a revision, without some way to defeat SHA1.  This is
generally a good thing; having immutable history is the point of a
version control system, after all, and it turns out to be very
important to building a _distributed_ version control system like
monotone.

   It does have one unfortunate consequence, though.  It means that in
the rare occasion where one _needs_ to change a historical revision, it
will change the SHA1 of that revision, which will change the text of
its children, which will change their SHA1s, and so on; basically the
entire history graph will diverge from that point (invalidating all
certs in the process).

   In practice there are two situations where this might be necessary:
   * bugs: monotone has occasionally allowed nonsense, uninterpretable
     changesets to be generated and stored in the database, and this
     was not detected until further work had been based off of them.

   * advances in crypto: if or when SHA1 is broken, we will need to
     migrate to a different secure hash.

   Obviously, we hope neither of these things will happen, and we've
taken lots of precautions against the first recurring; but it is better
to be prepared.

   If either of these events occur, we will provide migration commands
and explain how to use them for the situation in question; this much is
necessarily somewhat unpredictable.  In the past we've used the (now
defunct) `db rebuild' command, and more recently the `db rosterify'
command, for such changes as monotone developed.  These commands were
used to recreate revisions with new formats.  Because the revision id's
changed, all the existing certs that you trust also must be reissued,
signed with your key.(1)

   While such commands can reconstruct the ancestry graph in _your_
database, there are practical problems which arise when working in a
distributed work group.  For example, suppose our group consists of the
fictional developers Jim and Beth, and they need to rebuild their
ancestry graph. Jim performs a rebuild, and sends Beth an email telling
her that he has done so, but the email gets caught by Beth's spam
filter, she doesn't see it, and she blithely syncs her database with
Jim's. This creates a problem: Jim and Beth have combined the
pre-rebuild and post-rebuild databases.  Their databases now contain two
complete, parallel (but possibly overlapping) copies of their project's
ancestry.  The "bad" old revisions that they were trying to get rid of
are still there, mixed up with the "good" new revisions.

   To prevent such messy situations, monotone keeps a table of branch
"epochs" in each database. An epoch is just a large bit string
associated with a branch. Initially each branch's epoch is zero. Most
monotone commands ignore epochs; they are relevant in only two
circumstances:

   * When monotone rebuilds ancestry, it generates a new _random_ epoch
     for each branch in the database.

   * When monotone runs netsync between databases, it checks to make
     sure that all branches involved in the synchronization have the
     same epochs. If any epochs differ, the netsync is aborted with no
     changes made to either database. If either side is seeing a branch
     for the first time, it adopts the epoch of the other side.


   Thus, when a user rebuilds their ancestry graph, they select a new
epoch and thus effectively disassociate with the group of colleagues
they had previously been communicating with. Other members of that
group can then decide whether to follow the rebuild user into a new
group -- by pulling the newly rebuilt ancestry -- or to remain behind
in the old group.

   In our example, if Jim and Beth have epochs, Jim's rebuild creates a
new epoch for their branch, in his database.  This causes monotone to
reject netsync operations between Jim and Beth; it doesn't matter if
Beth loses Jim's email. When she tries to synchronize with him, she
receives an error message indicating that the epoch does not match. She
must then discuss the matter with Jim and settle on a new course of
action -- probably pulling Jim's database into a fresh database on
Beth's end - before future synchronizations will succeed.

Best practices
==============

The previous section described the theory and rationale behind rebuilds
and epochs.  Here we discuss the practical consequences of that
discussion.

   If you decide you must rebuild your ancestry graph -- generally by
announcement of a bug from the monotone developers -- the first thing
to do is get everyone to sync their changes with the central server; if
people have unshared changes when the database is rebuilt, they will
have trouble sharing them afterwards.

   Next, the project should pick a designated person to take down the
netsync server, rebuild their database, and put the server back up with
the rebuilt ancestry in it.  Everybody else should then pull this
history into a fresh database, check out again from this database, and
continue working as normal.

   In complicated situations, where people have private branches, or
ancestries cross organizational boundaries, matters are more complex.
The basic approach is to do a local rebuild, then after carefully
examining the new revision IDs to convince yourself that the rebuilt
graph is the same as the upstream subgraph, use the special `db epoch'
commands to force your local epochs to match the upstream ones.  (You
may also want to do some fiddling with certs, to avoid getting
duplicate copies of all of them; if this situation ever arises in real
life we'll figure out how exactly that should work.)  Be very careful
when doing this; you're explicitly telling monotone to let you shoot
yourself in the foot, and it will let you.

   Fortunately, this process should be extremely rare; with luck, it
will never happen at all.  But this way we're prepared.

   ---------- Footnotes ----------

   (1) Regardless of who originally signed the certs, after the rebuild
they will be signed by you.  This means you should be somewhat careful
when rebuilding, but it is unavoidable -- if you could sign with other
people's keys, that would be a rather serious security problem!


File: monotone.info,  Node: Mark-Merge,  Next: Regexps,  Prev: Rebuilding ancestry,  Up: Special Topics

7.4 Mark-Merge
==============

Monotone makes use of the Mark-Merge (also known as *-merge) algorithm.
The emails reproduced below document the algorithm. Further information
can be found at revctrl.org (http://revctrl.org/MarkMerge).

Initial mark-merge proposal
---------------------------

From: Nathaniel Smith <njs <at> pobox.com>
Subject: [cdv-devel] more merging stuff (bit long...)
Newsgroups: gmane.comp.version-control.codeville.devel, gmane.comp.version-control.monotone.devel
Date: 2005-08-06 09:08:09 GMT

I set myself a toy problem a few days ago: is there a really, truly,
right way to merge two heads of an arbitrary DAG, when the object
being merged is as simple as possible: a single scalar value?

I assume that I'm given a graph, and each node in the graph has a
value, and no other annotation; I can add annotations, but they have
to be derived from the values and topology.  Oh, and I assume that no
revision has more than 2 parents; probably things can be generalized
to the case of indegree 3 or higher, but it seems like a reasonable
restriction...

So, anyway, here's what I came up with.  Perhaps you all can tell me
if it makes sense.

User model
----------

Since the goal was to be "really, truly, right", I had to figure out
what exactly that meant... basically, what I'm calling a "user model"
-- a formal definition of how the user thinks about merging, to give
an operational definition of "should conflict" and "should clean
merge".  My rules are these:
  1) whenever a user explicitly sets the value, they express a claim
     that their setting is superior to the old setting
  2) whenever a user chooses to commit a new revision, they implicitly
     affirm the validity of the decisions that led to that revision's
     parents
    Corollary of (1) and (2): whenever a user explicitly sets the
     value, they express that they consider their new setting to be
     superior to _all_ old settings
  3) A "conflict" should occur if, and only if, the settings on each
     side of the merge express parallel claims.
This in itself is not an algorithm, or anything close to it; the hope
is that it's a good description of what people actually want out of a
merge algorithm, expressed clearly enough that we can create an
algorithm that fits these desiderata.

Algorithm
---------

I'll use slightly novel notation.  Lower case letters represent values
that scalar the scalar takes.  Upper case letters represent nodes in
the graph.

Now, here's an algorithm, that is supposed to just be a transcription
of the above rules, one step more formal:
  First, we need to know where users actively expressed an intention.
  Intention is defined by (1), above.  We use * to mark where this
  occurred:

    i)      a*     graph roots are always marked

            a
    ii)     |      no mark, value was not set
            a

            a
    iii)    |      b != a, so b node marked
            b*

          a   b
    iv)    \ /
            c*
                   c is totally new, so marked
          a   a
           \ /
            c*

          a   b    we're marking places where users expressed
    v)     \ /     intention; so b should be marked iff this
            b?     was a conflict (!)

          a   a    for now I'm not special-casing the coincidental
    vi)    \ /     clean merge case, so let's consider this to be
            a?     a subclass of (v).

  That's all the cases possible.  So, suppose we go through and
  annotate our graph with *s, using the above rules; we have a graph
  with some *s peppered through it, each * representing one point that
  a user took action.

  Now, a merge algorithm per se: Let's use *(A) to mean the unique
  nearest marked ancestor of node A.  Suppose we want to merge A and
  B.  There are exactly 3 cases:
    - *(A) is an ancestor of B, but not vice versa: B wins.
    - *(B) is an ancestor of A, but not vice versa: A wins.
    - *(A) is _not_ an ancestor of B, and vice versa: conflict,
      escalate to user
  Very intuitive, right?  If B supercedes the intention that led to A,
  then B should win, and vice-versa; if not, the user has expressed
  two conflicting intentions, and that, by definition, is a conflict.

  This lets us clarify what we mean by "was a conflict" in case (v)
  above.  When we have a merge of a and b that gives b, we simple
  calculate *(a); if it is an ancestor of 'b', then we're done, but if
  it isn't, then we mark the merge node.  (Subtle point: this is
  actually not _quite_ the same as detecting whether merging 'a' and
  'b' would have given a conflict; if we somehow managed to get a
  point in the graph that would have clean merged to 'a', but in fact
  was merged to 'b', then this algorithm will still mark the merge
  node.)  For cases where the two parents differ, you have to do this
  using the losing one; for cases where the two parents are the same,
  you should check both, because it could have been a clean merge two
  different ways.  If *(a1) = *(a2), i.e., both sides have the same
  nearest marked ancestor, consider that a clean merge.

  That's all.

Examples
--------

Of course, I haven't shown you this is well-defined or anything, but
to draw out the suspense a little, have some worked examples (like
most places in this document, I draw graphs with two leaves and assume
that those are being merged):

  graph:
       a*
      / \
     a   b*
  result: *(a) is an ancestor of b, but *(b) is not an ancestor of a;
    clean merge with result 'b'.

  graph:
       a*
      / \
     b*  c*
  result: *(b) = b is not an ancestor of c, and *(c) = c is not an
    ancestor of c; conflict.

  graph:
       a*
      / \
     b*  c*  <--- these are both marked, by (iii)
     |\ /|
     | X |
     |/ \|
     b*  c*  <--- which means these were conflicts, and thus marked
  result: the two leaves are both marked, and thus generate a conflict,
    as above.

Right, enough of that.  Math time.

Math
----

Theorem: In a graph marked following the above rules, every node N
  will have a unique least marked ancestor M, and the values of M and N
  will be the same.
Proof: By downwards induction on the graph structure.  The base case
  are graph roots, which by (i) are always marked, so the statement is
  trivially true.  Proceeding by cases, (iii) and (iv) are trivially
  true, since they produce nodes that are themselves marked.  (ii) is
  almost as simple; in a graph 'a' -> 'a', the child obviously
  inherits the parent's unique least marked ancestor, which by
  inductive hypothesis exists.  The interesting case is (v) and (vi):
     a   b
      \ /
       b
  If the child is marked, then again the statement is trivial; so
  suppose it is not.  By definition, this only occurs when *(a) is an
  ancestor of 'b'.  But, by assumption, 'b' has a unique nearest
  ancestor, whose value is 'b'.  Therefore, *(a) is also an ancestor
  of *(b).  If we're in the weird edge case (vi) where a = b, then
  these may be the same ancestor, which is fine.  Otherwise, the fact
  that a != b, and that *(a)'s value = a's value, *(b)'s value = b's
  value, implies that *(a) is a strict ancestor of *(b).  Either way,
  the child has a unique least marked ancestor, and it is the same
  ULMA as its same-valued parent, so the ULMA also has the right
  value.  QED.

Corollary: *(N) is a well-defined function.

Corollary: The three cases mentioned in the merge algorithm are the
  only possible cases.  In particular, it cannot be that *(A) is an
  ancestor of B and *(B) is an ancestor of A simultaneously, unless
  the two values being merged are identical (and why are you running
  your merge algorithm then?).  Or in other words: ambiguous clean
  merge does not exist.
Proof: Suppose *(A) is an ancestor of B, and *(B) is an ancestor of A.
  *(B) is unique, so *(A) must also be an ancestor of *(B).
  Similarly, *(B) must be an ancestor of *(A).  Therefore:
    *(A) = *(B)
  We also have:
    value(*(A)) = value(A)
    value(*(B)) = value(B)
  which implies
    value(A) = value(B).  QED.

Therefore, the above algorithm is well-defined in all possible cases.

We can prove another somewhat interesting fact:
Theorem: If A and B would merge cleanly with A winning, then any
  descendent D of A will also merge cleanly with B, with D winning.
Proof: *(B) is an ancestor of A, and A is an ancestor of D, so *(B) is
  an ancestor of D.

I suspect that this is enough to show that clean merges are order
invariant, but I don't have a proof together ATM.

Not sure what other properties would be interesting to prove; any
suggestions?  It'd be nice to have some sort of proof about "once a
conflict is resolved, you don't have to resolve it again" -- which is
the problem that makes ambiguous clean merge so bad -- but I'm not
sure how to state such a property formally.  Something about it being
possible to fully converge a graph by resolving a finite number of
conflicts or something, perhaps?

Funky cases
-----------

There are two funky cases I know of.

Coincidental clean merge:
    |
    a
   / \
  b*  b*

Two people independently made the same change.  When we're talking
about textual changes, some people argue this should give a conflict
(reasoning that perhaps the same line _should_ be inserted twice).  In
our context that argument doesn't even apply, because these are just
scalars; so obviously this should be a clean merge.  Currently, the
only way this algorithm has to handle this is to treat it as an
"automatically resolved conflict" -- there's a real conflict here, but
the VCS, acting as an agent for the user, may decide to just go ahead
and resolve it, because it knows perfectly well what the user will do.
In this interpretation, everything works fine, all the above stuff
applies; it's somewhat dissatisfying, though, because it's a violation
of the user model -- the user has not necessarily looked at this
merge, but we put the * of user-assertion on the result anyway.  Not a
show-stopper, I guess...

It's quite possible that the above stuff could be generalized to allow
non-unique least marked ancestors, that could only arise in exactly
this case.

I'm not actually sure what the right semantics would be, though.  If
we're merging:
    |
    a
   / \
  b   b
   \ / \
    b   c
Should that be a clean merge?  'b' was set twice, and only one of
these settings was overridden; is that good enough?

Do you still have the same opinion if the graph is:
    |
    a
    |
    b
   / \
  c   b
  |  / \
  b  b  c
  \ /
   b
?  Here the reason for the second setting of 'b' was that a change
away from it was reverted; to make it extra cringe-inducing, I threw
in that change being reverted was another change to 'c'... (this may
just be an example of how any merge algorithm has some particular case
you can construct where it will get something wrong, because it
doesn't _actually_ know how to read the users's minds).

Supporting these cases may irresistably lead back to ambiguous clean,
as well:
     |
     a
    / \
   b*  c*
  / \ / \
 c*  X   b*
  \ / \ /
   c   b

The other funky case is this thing (any clever name suggestions?):
    a
   / \
  b*  c*
   \ / \
    c*  d*
Merging here will give a conflict, with my algorithm; 3-way merge
would resolve it cleanly.  Polling people on #monotone and #revctrl,
the consensus seems to be that they agree with 3-way merge, but giving
a conflict is really not _that_ bad.  (It also seems to cause some
funky effects with darcs-merge; see zooko's comments on #revctrl and
darcs-users.)

This is really a problem with the user model, rather than the
algorithm.  Apparently people do not interpret the act of resolving
the b/c merge to be "setting" the result; They seem to interpret it as
"selecting" the result of 'c'; the 'c' in the result is in some sense
the "same" 'c' as in the parent.  The difference between "setting" and
"selecting" is the universe of possible options; if you see
   a   b
    \ /
     c
then you figure that the person doing the merge was picking from all
possible resolution values; when you see
   a   b
    \ /
     b
you figure that the user was just picking between the two options
given by the parents.  My user model is too simple to take this into
account.  It's not a huge extension to the model to do so; it's quite
possible that an algorithm could be devised that gave a clean merge
here, perhaps by separately tracking each node's nearest marked
ancestor and the original source of its value as two separate things.

Relation to other work
----------------------

This algorithm is very close to the traditional codeville-merge
approach to this problem; the primary algorithmic difference is the
marking of conflict resolutions as being "changes".  The more
important new stuff here, I think, are the user model and the proofs.

Traditionally, merge algorithms are evaluated by coming up with some
set of examples, eyeballing them to make some guess as to what the
"correct" answer was, comparing that to the algorithm's output, and
then arguing with people whose intuitions were different.
Fundamentally, merging is about deterministically guessing the user's
intent in situations where the user has not expressed any intent.
Humans are very good at guessing intent; we have big chunks of squishy
hardware designed to form sophisticated models of others intents, and
it's completely impossible for a VCS to try and duplicate that in
full.  My suggestion here, with my "user model", is to seriously and
explicitly study this part of the problem.  There are complicated
trade-offs between accuracy (correctly modeling intention),
conservatism (avoiding incorrectly modeling intention), and
implementability (describing the user's thought processes exactly
isn't so useful if you can't apply it in practice).  It's hard to make
an informed judgement when we don't have a name for the thing we're
trying to optimize, and hard to evaluate an algorithm when we can't
even say what it's supposed to be doing.

I suspect the benefit of the proofs is obvious to anyone who has spent
much time banging their head against this problem; until a few days
ago I was skeptical there _was_ a way to design a merge algorithm that
didn't run into problems like ambiguous clean merge.

I'm still skeptical, of course, until people read this; merging is
like crypto, you can't trust anything until everyone's tried to break
it... so let's say I'm cautiously optimistic .  If this holds up,
I'm quite happy; between the user model and the proofs, I'm far more
confident that this does something sensible in all cases and has no
lurking edge cases than I have been in any previous algorithm.  The
few problem cases I know of display a pleasing conservatism -- perhaps
more cautious than they need to be, but even if they do cause an
occasional unnecessary conflict, once the conflict is resolved it
should stay resolved.

So... do your worst!

-- Nathaniel

--
So let us espouse a less contested notion of truth and falsehood, even
if it is philosophically debatable (if we listen to philosophers, we
must debate everything, and there would be no end to the discussion).
  -- Serendipities, Umberto Eco

Replies and further discussion concerning this email can be found in
the  monotone-devel archives
(http://thread.gmane.org/gmane.comp.version-control.monotone.devel/4297).

Improvements to *-merge
-----------------------

From: Nathaniel Smith <njs@...>
Subject: improvements to *-merge
Newsgroups: gmane.comp.version-control.revctrl, gmane.comp.version-control.monotone.devel
Date: 2005-08-30 09:21:18 GMT

This is a revised version of *-merge:
  http://thread.gmane.org/gmane.comp.version-control.monotone.devel/4297
that properly handles accidental clean merges.  It does not improve
any of the other parts, just the handling of accidental clean merges.
It shows a way to relax the uniqueness of the *() operator, while
still preserving the basic results from the above email.  For clarity,
I'll say 'unique-*-merge' to refer to the algorithm given above, and
'multi-*-merge' to refer to this one.

This work is totally due to Timothy Brownawell <tbrownaw@...>.
All I did was polish up the proofs and write it up.  He has a more
complex version at:
  http://article.gmane.org/gmane.comp.version-control.monotone.devel/4496
that also attempts to avoid the conflict with:
     a
    / \
   b*  c*
    \ / \
     c*  d*
and has some convergence in it, but the analysis for that is not done.

So:

User model
----------

We keep exactly the same user model as unique-*-merge:

  1) whenever a user explicitly sets the value, they express a claim
     that their setting is superior to the old setting
  2) whenever a user chooses to commit a new revision, they implicitly
     affirm the validity of the decisions that led to that revision's
     parents
    Corollary of (1) and (2): whenever a user explicitly sets the
     value, they express that they consider their new setting to be
     superior to _all_ old settings
  3) A "conflict" should occur if, and only if, the settings on each
     side of the merge express parallel claims.

The difference is that unique-*-merge does not _quite_ fulfill this
model, because in real life your algorithm will automatically resolve
coincidental clean merge cases without asking for user input; but
unique-* is not smart enough to take this into account when inferring
user intentions.

Algorithm
---------

We start by marking the graph of previous revisions.  For each node in
the graph, we either mark it (denoted by a *), or do not.  A mark
indicates our inference that a human expressed an intention at this
node.

    i)      a*     graph roots are always marked

            a1
    ii)     |      no mark, value was not set
            a2

            a
    iii)    |      b != a, so 'b' node marked
            b*

          a   b
    iv)    \ /
            c*
                   'c' is totally new, so marked
          a1  a2
           \ /
            c*

          a   b1   we're marking places where users expressed
    v)     \ /     intention; so 'b' should be marked iff this
            b2?    was a conflict

          a1  a2   'a' matches parents, and so is not marked
    vi)    \ /     (alternatively, we can say this is a special
            a3     case of (v), that is never a conflict)

Case (vi) is the only one that differs from unique-* merge.  However,
because of it, we must use a new definition of *():

Definition: By *(A), we mean we set of minimal marked ancestors of A.
"Minimal" here is used in the mathematical sense of a node in a graph
that has no descendents in that graph.

Algorithm: Given two nodes to merge, A and B, we consider four cases:
   a) value(A) = value(B): return the shared value
   b) *(A) > B: return value(B)
   c) *(B) > A: return value(A)
   d) else: conflict; escalate to user
Where "*(A) > B" means "all elements of the set *(A) are non-strict
ancestors of the revision B".  The right way to read this is as "try
(a) first, and then if that fails try (b), (c), (d) simultaneously".

Note that except for the addition of rule (a), this is a strict
generalization of the unique-* algorithm; if *(A) and *(B) are
single-element sets, then this performs _exactly_ the same
computations as the unique-* algorithm.

Now we can say what we mean by "was a conflict" in case (v) above:
given a -> b2, b1 -> b2, we leave b2 unmarked if and only if
*(a) > b1.

Examples
--------

1.
    a1*
   / \
  a2  b*

result: *(a2) = {a1}, a1 > b, so b wins.

2.
    a*
   / \
  b*  c*

result: *(b) = {b}, *(c) = {c}, neither *(b) > c nor *(c) > b, so
 conflict.

3.
    a*
   / \
  b1* b2*
   \ / \
    b3  c1*

result: *(b3) = {b1, b2}; b2 > c1, but b1 is not > c, so c does not
 win.  *(c1) = {c1}, which is not > b3.  conflict.
note: this demonstrates that this algorithm does _not_ do convergence.
Instead, it takes the conservative position that for one node to
silently beat another, the winning node must pre-empt _all_ the
intentions that created the losing node.  While it's easy to come up
with just-so stories where this is the correct thing to do (e.g., b1
and b2 each contain some other changes that independently require 'a'
to become 'b'; c1 will have fixed up b2's changes, but not b1's), this
doesn't actually mean much.  Whether this is good or bad behavior a
somewhat unresolved question, that may ultimately be answered by which
merge algorithms turn out to be more tractable...

4.
    a*
   / \
  b1* b2*
  |\ /|
  | X |
  |/ \|
  b3  c*

result: *(b3) = {b1, b2} > c.  *(c) = {c}, which is not > b3.  c wins
 cleanly.

5.
     a*
    / \
   b1* c1*
  / \ / \
 c2* X   b2*
  \ / \ /
   c3  b3

result: *(c3) = {c1, c2}; c1 > b3 but c2 is not > b3, so b3 does not
 win.  likewise, *(b3) = {b1, b2}; b1 > c3 but b2 is not > c3, so c3
 does not win either.  conflict.

6.
     a*
    / \
   b1* c1*
  / \ / \
 c2* X   b2*
  \ / \ /
   c3  b3
   |\ /|
   | X |
   |/ \|
   c4* b4*

(this was my best effort to trigger an ambiguous clean merge with this
algorithm; it fails pitifully:)
result: *(c4) = {c4}, *(b4) = {b4}, obvious conflict.

Math
----

The interesting thing about this algorithm is that all the unique-*
proofs still go through, in a generalized form.  The key one that
makes *-merge tractable is:

Theorem: In a graph marked by the above rules, given a node N, all
 nodes in *(N) will have the same value as N.
Proof: By induction.  We consider the cases (i)-(vi) above.  (i)
 through (iv) are trivially true.  (v) is interesting.  b2 is marked
 when *(a) not > b1.  b2 being marked makes that case trivial, so
 suppose *(a) > b1.  All elements of *(a) are marked, and are
 ancestors of b1; therefore, by the definition of *() and "minimal",
 they are also all ancestors of things in *(b1).  Thus no element of
 *(a) can be a minimal marked ancestor of b2.
 (vi) is also trivial, because *(a3) = *(a1) union *(a2).  QED.

We also have to do a bit of extra work because of the sets:

Corollary 1: If *(A) > B, and any element R of *(B) is R > A, then
 value(A) = value(B).
Proof: Let such an R be given.  R > A, and R marked, imply that there
 is some element S of *(A) such that R > S.
 On the other hand, *(A) > B implies that S > B.  By similar reasoning
 to the above, this means that there is some element T of *(B) such
 that S > T.  So, recapping, we have:
  nodes:   R  >  S  >  T
   from: *(B)  *(A)  *(B)
 *(B) is a set of minimal nodes, yet we have R > T and R and T both in
 *(B).  This implies that R = T.  R > S > R implies that S = R,
 because we are in a DAG.  Thus
   value(A) = value(S) = value(R) = value(B)
 QED.

Corollary 2: If *(A) > B and *(B) > A, then not only does value(A) =
 value(B), but *(A) = *(B).
Proof: By above, each element of *(B) is equal to some element of
 *(A), and vice-versa.

This is good, because it means our algorithm is well-defined.  The
only time when options (b) and (c) (in the algorithm) can
simultaneously be true, is when the two values being merged are
identical to start with.  I.e., no somewhat anomalous "4th case" of
ambiguous clean merge.

Actually, this deserves some more discussion.  With *() returning a
set, there are some more subtle "partial ambiguous clean" cases to
think about -- should we be worrying about cases where some, but not
all, of the marked ancestors are pre-empted?  This is possible, as in
example 5 above:
     a*
    / \
   b1* c1*
  / \ / \
 c2* X   b2*
  \ / \ /
   c3  b3
A hypothetical (convergence supporting?) algorithm that said A beats B
if _any_ elements of *(A) are > B would give an ambiguous clean merge
on this case.  (Maybe that wouldn't be so bad, so long as we marked
the result, but I'm in no way prepared to do any sort of sufficient
analysis right now...)

The nastiest case of this is where *(A) > B, but some elements of *(B)
are > A -- so we silently make B win, but it's really not _quite_
clear that's a good idea, since A also beat B sometimes -- and we're
ignoring those user's intentions.

This is the nice thing about Corollary 1 (and why I didn't just
collapse it into Corollary 2) -- it assures us that the only time this
_weak_ form of ambiguous clean can happen is when A and B are already
identical.  This _can_ happen, for what it's worth:
       a*
      /|\
     / | \
    /  |  \
   /   |   \
  b1*  b2*  d*
  |\   /\  /
  | \ /  \/
  |  X   b3*
  | / \ /
  |/   b4
  b5
Here *(b5) = {b3, b2}, *(b6) = {b2, b4}.  If we ignore for a moment
that b4 and b5 have the same value, this is a merge that b4 would win
and b5 would lose, even though one of b4's ancestors, i.e. b1, is
pre-empted by b5.  However, it can _only_ happen if we ignore that
they have the same value...

The one other thing we proved about unique-* merge also still applies;
the proof goes through word-for-word:
Theorem: If A and B would merge cleanly with A winning, then any
  descendent D of A will also merge cleanly with B, with D winning.
Proof: *(B) > A, and A > D, so *(B) > D.

Discussion
----------

This algorithm resolves one of the two basic problems I observed for
unique-* merge -- coincidental clean merges are now handled, well,
cleanly, and the user model is fully implemented.  However, we still
do not handle the unnamed case (you guys totally let me down when I
requested names for this case last time):
    a
   / \
  b*  c*
   \ / \
    c*  d*
which still gives a conflict.  We also, of course, continue to not
support more exotic features like convergence or implicit rollback.

Not the most exciting thing in the world.  OTOH, it does strictly
increase the complexity of algorithms that are tractable to formal
analysis.

Comments and feedback appreciated.

-- Nathaniel

--
"The problem...is that sets have a very limited range of
activities -- they can't carry pianos, for example, nor drink
beer."

Replies and further discussion concerning this email can be found in
the  monotone-devel archives
(http://thread.gmane.org/gmane.comp.version-control.revctrl/93).

More on "mark-merge"
--------------------

From: Timothy Brownawell <tbrownaw@...>
Subject: more on "mark-merge"
Newsgroups: gmane.comp.version-control.revctrl, gmane.comp.version-control.monotone.devel

Prerequisite:
http://thread.gmane.org/gmane.comp.version-control.monotone.devel/4297

A user can make 2 types of merge decisions:
(1): One parent is better than the other (represented by *)
(2): Both parents are wrong (represented by ^)

Since there are 2 types of merge decisions, it would be bad to treat all
merge decisions the same. Also, in the case of merge(a, a) = a, it is
possible for there to be multiple least decision ancestors.

=====

Define: ^(A) is the set of ancestors of A that it gets its value from
(found by setting N=A and iterating N = *(N) until there is no change)
        *(A) is the set of least ancestors of A in which the user made a
decision

note that erase_ancestors(^(A)) = ^(A),
and erase_ancestors(*(A)) = *(A)

=====

& is intersection, | is union

*(A) has the same properties as before, except that it is not a single
ancestor, but a set. This set can acquire more than one member only in
the case of
   Aa    Ba
     \  /
      Ca
, where *(A) and *(B) are different; *(C) will be
erase_ancestors(*(A) | *(B))

The ancestory corollary becomes:
any ancestor C of A with value(C) != value(A) will be an ancestor of at
least one member of *(A)

When merging A and B:

# if one side knows of _all_ places that the other side was chosen, it
wins
(1)
set X = erase_ancestors(*(A) | *(B))
    if X & *(B) = {}, A wins
    if X & *(A) = {}, B wins
else, X contains members of both *(A) and *(B)

# if one side knows of _all_ places that the other side originated, it
wins
(2)
set Y = erase_ancestors(*(A) | ^(B))
set Z = erase_ancestors(*(B) | ^(A))
    if Y & ^(B) = {} and Z & ^(A) = {}, conflict
    if Y & ^(B) = {}, A wins
    if Z & ^(A) = {}, B wins

# if one side knows of _any_ places that the other side originated, it
wins
(3)
    if Y & ^(B) != ^(B) and Z & ^(A) != ^(A), conflict
    if Y & ^(B) != ^(B), A wins
    if Z & ^(A) != ^(A), B wins

# else, nobody knows anything
(4) conflict

(3) is convergence, and can be safely left out if unwanted

====

"Funky cases"

Coincidental clean does not exist; a mark is only needed when there is
user intervention.

    |
    a
   / \
  b   b
   \ / \
    b   c
and the example after it will resolve cleanly iff (3) is included.

     |
     a
    / \
   b*  c*
  / \ / \
 c*  X   b*
  \ / \ /
   c   b
will be a conflict.

    a
   / \
  b*  c*
   \ / \
    c*  d*
This ("the other funky case") is handled by (2), and resolves cleanly.

Tim

Replies and further discussion concerning this email can be found in
the  monotone-devel archives
(http://thread.gmane.org/gmane.comp.version-control.revctrl/92).


File: monotone.info,  Node: Regexps,  Prev: Mark-Merge,  Up: Special Topics

7.5 Regular Expression Syntax
=============================

Monotone expects user-provided regular expressions in `.mtn-ignore'
files and as the result of the `get_encloser_pattern' Lua hook (for the
`diff' command).  User-written Lua hooks may also use the function
`regex.search' as they see fit.  All these regular expressions should
be written with the same syntax, which is that expected by the
Perl-Compatible Regular Expression library (PCRE).

* Menu:

* Regexp Summary::  Quick reference to regular expression syntax.
* Regexp Details::  Details of regular expression syntax and semantics.


File: monotone.info,  Node: Regexp Summary,  Next: Regexp Details,  Up: Regexps

7.5.1 Regexp Syntax Summary
---------------------------

This is a quick-reference summary of the regular expression syntax used
in Monotone.

Quoting
.......

`\X'
     where X is non-alphanumeric is a literal X

`\Q...\E'
     treat enclosed characters as literal

Characters
..........

`\a'
     alarm, that is, the BEL character (hex 07)

`\cX'
     "control-X", where X is any character

`\e'
     escape (hex 1B)

`\f'
     formfeed (hex 0C)

`\n'
     newline (hex 0A)

`\r'
     carriage return (hex 0D)

`\t'
     tab (hex 09)

`\DDD'
     character with octal code DDD, or backreference

`\xHH'
     character with hex code HH

`\x{HHH...}'
     character with hex code HHH...

Character Types
...............

`.'
     any character except newline;                in dotall mode, any
     character whatsoever

`\C'
     one byte, even in UTF-8 mode (best avoided)

`\d'
     a decimal digit

`\D'
     a character that is not a decimal digit

`\h'
     a horizontal whitespace character

`\H'
     a character that is not a horizontal whitespace character

`\p{XX}'
     a character with the XX property

`\P{XX}'
     a character without the XX property

`\R'
     a newline sequence

`\s'
     a whitespace character

`\S'
     a character that is not a whitespace character

`\v'
     a vertical whitespace character

`\V'
     a character that is not a vertical whitespace character

`\w'
     a "word" character

`\W'
     a "non-word" character

`\X'
     an extended Unicode sequence

`\d', `\D', `\s', `\S', `\w', and `\W' recognize only ASCII characters.

General category property codes for `\p' and `\P'
.................................................

`C'
     Other

`Cc'
     Control

`Cf'
     Format

`Cn'
     Unassigned

`Co'
     Private use

`Cs'
     Surrogate

`L'
     Letter

`Ll'
     Lower case letter

`Lm'
     Modifier letter

`Lo'
     Other letter

`Lt'
     Title case letter

`Lu'
     Upper case letter

`L&'
     Ll, Lu, or Lt

`M'
     Mark

`Mc'
     Spacing mark

`Me'
     Enclosing mark

`Mn'
     Non-spacing mark

`N'
     Number

`Nd'
     Decimal number

`Nl'
     Letter number

`No'
     Other number

`P'
     Punctuation

`Pc'
     Connector punctuation

`Pd'
     Dash punctuation

`Pe'
     Close punctuation

`Pf'
     Final punctuation

`Pi'
     Initial punctuation

`Po'
     Other punctuation

`Ps'
     Open punctuation

`S'
     Symbol

`Sc'
     Currency symbol

`Sk'
     Modifier symbol

`Sm'
     Mathematical symbol

`So'
     Other symbol

`Z'
     Separator

`Zl'
     Line separator

`Zp'
     Paragraph separator

`Zs'
     Space separator

Script names for `\p' and `\P'
..............................

Arabic, Armenian, Balinese, Bengali, Bopomofo, Braille, Buginese, Buhid,
Canadian_Aboriginal, Cherokee, Common, Coptic, Cuneiform, Cypriot,
Cyrillic, Deseret, Devanagari, Ethiopic, Georgian, Glagolitic, Gothic,
Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana,
Inherited, Kannada, Katakana, Kharoshthi, Khmer, Lao, Latin, Limbu,
Linear_B, Malayalam, Mongolian, Myanmar, New_Tai_Lue, Nko, Ogham,
Old_Italic, Old_Persian, Oriya, Osmanya, Phags_Pa, Phoenician, Runic,
Shavian, Sinhala, Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le,
Tamil, Telugu, Thaana, Thai, Tibetan, Tifinagh, Ugaritic, Yi.

Character Classes
.................

`[...]'
     positive character class

`[^...]'
     negative character class

`[X-Y]'
     range (can be used for hex characters)

`[[:XXX:]]'
     positive POSIX named set

`[[:^XXX:]]'
     negative POSIX named set

`alnum'
     alphanumeric

`alpha'
     alphabetic

`ascii'
     0-127

`blank'
     space or tab

`cntrl'
     control character

`digit'
     decimal digit

`graph'
     printing, excluding space

`lower'
     lower case letter

`print'
     printing, including space

`punct'
     printing, excluding alphanumeric

`space'
     whitespace

`upper'
     upper case letter

`word'
     same as `\w'

`xdigit'
     hexadecimal digit

   In PCRE, POSIX character set names recognize only ASCII characters.
You can use `\Q...\E' inside a character class.

Quantifiers
...........

`?'
     0 or 1, greedy

`?+'
     0 or 1, possessive

`??'
     0 or 1, lazy

`*'
     0 or more, greedy

`*+'
     0 or more, possessive

`*?'
     0 or more, lazy

`+'
     1 or more, greedy

`++'
     1 or more, possessive

`+?'
     1 or more, lazy

`{N}'
     exactly N

`{N,M}'
     at least N, no more than M, greedy

`{N,M}+'
     at least N, no more than M, possessive

`{N,M}?'
     at least N, no more than M, lazy

`{N,}'
     N or more, greedy

`{N,}+'
     N or more, possessive

`{N,}?'
     N or more, lazy

Anchors and Simple Assertions
.............................

`\b'
     word boundary

`\B'
     not a word boundary

`^'
     start of subject                also after internal newline in
     multiline mode

`\A'
     start of subject

`$'
     end of subject                also before newline at end of subject
                   also before internal newline in multiline mode

`\Z'
     end of subject                also before newline at end of subject

`\z'
     end of subject

`\G'
     first matching position in subject

Match Point Reset
.................

`\K'
     reset start of match

Alternation
...........

`EXPR|EXPR|EXPR...'

Capturing
.........

`(...)'
     capturing group

`(?<NAME>...)'
     named capturing group (like Perl)

`(?'NAME'...)'
     named capturing group (like Perl)

`(?P<NAME>...)'
     named capturing group (like Python)

`(?:...)'
     non-capturing group

`(?|...)'
     non-capturing group; reset group numbers for   capturing groups in
     each alternative

Atomic Groups
.............

`(?>...)'
     atomic, non-capturing group

Comment
.......

`(?#....)'
     comment (not nestable)

Option Setting
..............

`(?i)'
     caseless

`(?J)'
     allow duplicate names

`(?m)'
     multiline

`(?s)'
     single line (dotall)

`(?U)'
     default ungreedy (lazy)

`(?x)'
     extended (ignore white space)

`(?-...)'
     unset option(s)

Lookahead and Lookbehind Assertions
...................................

`(?=...)'
     positive look ahead

`(?!...)'
     negative look ahead

`(?<=...)'
     positive look behind

`(?<!...)'
     negative look behind

   Each top-level branch of a look behind must be of a fixed length.

Backreferences
..............

`\N'
     reference by number (can be ambiguous)

`\gN'
     reference by number

`\g{N}'
     reference by number

`\g{-N}'
     relative reference by number

`\k<NAME>'
     reference by name (like Perl)

`\k'NAME''
     reference by name (like Perl)

`\g{NAME}'
     reference by name (like Perl)

`\k{NAME}'
     reference by name (like .NET)

`(?P=NAME)'
     reference by name (like Python)

Subroutine References (possibly recursive)
..........................................

`(?R)'
     recurse whole pattern

`(?N)'
     call subpattern by absolute number

`(?+N)'
     call subpattern by relative number

`(?-N)'
     call subpattern by relative number

`(?&NAME)'
     call subpattern by name (like Perl)

`(?P>NAME)'
     call subpattern by name (like Python)

Conditional Patterns
....................

`(?(CONDITION)YES-PATTERN)'

`(?(CONDITION)YES-PATTERN|NO-PATTERN)'

`(?(N)...'
     absolute reference condition

`(?(+N)...'
     relative reference condition

`(?(-N)...'
     relative reference condition

`(?(<NAME>)...'
     named reference condition (like Perl)

`(?('NAME')...'
     named reference condition (like Perl)

`(?(NAME)...'
     named reference condition (PCRE only)

`(?(R)...'
     overall recursion condition

`(?(RN)...'
     specific group recursion condition

`(?(R&NAME)...'
     specific recursion condition

`(?(DEFINE)...'
     define subpattern for reference

`(?(assert)...'
     assertion condition

Backtracking Control
....................

The following act immediately they are reached:

`(*ACCEPT)'
     force successful match

`(*FAIL)'
     force backtrack; synonym `(*F)'

   The following act only when a subsequent match failure causes a
backtrack to reach them. They all force a match failure, but they
differ in what happens afterwards. Those that advance the
start-of-match point do so only if the pattern is not anchored.

`(*COMMIT)'
     overall failure, no advance of starting point

`(*PRUNE)'
     advance to next starting character

`(*SKIP)'
     advance start to current matching position

`(*THEN)'
     local failure, backtrack to next alternation

Newline Conventions
...................

These are recognized only at the very start of the pattern or after a
`(*BSR_...)' option.

`(*CR)'

`(*LF)'

`(*CRLF)'

`(*ANYCRLF)'

`(*ANY)'

What `\R' Matches
.................

These are recognized only at the very start of the pattern or after a
`(*...)' option that sets the newline convention.

`(*BSR_ANYCRLF)'

`(*BSR_UNICODE)'

