convert: add filter.<driver>.process option
commitedcc85814c87ebd7f3b1b7d3979fac3dfb84d308
authorLars Schneider <larsxschneider@gmail.com>
Sun, 16 Oct 2016 23:20:37 +0000 (16 16:20 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 17 Oct 2016 18:45:52 +0000 (17 11:45 -0700)
tree92fcb94be20c944c989b91d6cc8b4a0f54af2a01
parent234fa07e066d6bc0728c3d9b92686c69a811e5ac
convert: add filter.<driver>.process option

Git's clean/smudge mechanism invokes an external filter process for
every single blob that is affected by a filter. If Git filters a lot of
blobs then the startup time of the external filter processes can become
a significant part of the overall Git execution time.

In a preliminary performance test this developer used a clean/smudge
filter written in golang to filter 12,000 files. This process took 364s
with the existing filter mechanism and 5s with the new mechanism. See
details here: https://github.com/github/git-lfs/pull/1382

This patch adds the `filter.<driver>.process` string option which, if
used, keeps the external filter process running and processes all blobs
with the packet format (pkt-line) based protocol over standard input and
standard output. The full protocol is explained in detail in
`Documentation/gitattributes.txt`.

A few key decisions:

* The long running filter process is referred to as filter protocol
  version 2 because the existing single shot filter invocation is
  considered version 1.
* Git sends a welcome message and expects a response right after the
  external filter process has started. This ensures that Git will not
  hang if a version 1 filter is incorrectly used with the
  filter.<driver>.process option for version 2 filters. In addition,
  Git can detect this kind of error and warn the user.
* The status of a filter operation (e.g. "success" or "error) is set
  before the actual response and (if necessary!) re-set after the
  response. The advantage of this two step status response is that if
  the filter detects an error early, then the filter can communicate
  this and Git does not even need to create structures to read the
  response.
* All status responses are pkt-line lists terminated with a flush
  packet. This allows us to send other status fields with the same
  protocol in the future.

Helped-by: Martin-Louis Bright <mlbright@gmail.com>
Reviewed-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Lars Schneider <larsxschneider@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/gitattributes.txt
convert.c
t/t0021-conversion.sh
t/t0021/rot13-filter.pl [new file with mode: 0755]