New local pre-commit hook in monotone

There was only one hook in monotone until now which could be “reused” to interact with the commit process and validate the changeset that should be committed, the `validate_commit_message` hook. But this was a bit clumsy as it was actually designed to validate the commit message (as the name suggests) and not the changeset, thus the hook was called _after_ the commit message was entered in the editor (or was given with `–message` or `–message-file`).

Now monotone (from 0.99 onwards) gained a new commit hook which is called before the commit message processing takes place, but after the logic validated the changeset and branch to which it should be committed. Its named simply `validate_changes` and takes two parameters, the revision to be committed as full text (parsable in the hook via `parse_basic_io`) as the first and the name of the branch to which the revision should be committed as the second. Just as `validate_commit_message`, it is expected to return a tupel containing a boolean which denotes if the change is valid or not and an optional string which explains the reason if not and which is displayed to the committer afterwards.

With this new installment, it should feel natural e.g. to create a pre-commit hook which ensures that none of the patched or added sources contains Windows line endings:

function validate_changes(revdata, branchname)
  local parsed = parse_basic_io(revdata)
  for _,stanza in ipairs(parsed) do
    if stanza.name == "add_file" or
       stanza.name == "patch" then
      local file = stanza.values[1]
      if not guess_binary_file_contents(file) then
        local fp = assert(io.open(file, "r"))
        local contents = fp:read("*all")
        fp:close()
        if string.find(contents, "\r\n") then
          return false, "CRLF detected"
        end
      end
    end
  end
  return true, ""
end

Unfortunately its not yet possible to call `mtn_automate`, the lua interface to monotone’s automation commands, from hooks like this. Then we could have saved the `read(“*all”)` call and would only have to scan the output of `automate content_diff`, which should be a little faster than doing a full string search in lua for bigger files. We, i.e. the monotone devs, are aware of the problem though and will come up with a solution sooner or later.

I hope this new hook will still be useful for some of you until then.