{"thread":{"id":"47695","subject":"[PATCH] Docs: split out long-running subprocess handshake","startedAt":"2018-01-25T18:53:39Z","lastAt":"2018-01-25T18:53:39Z","messageCount":1,"participants":["Jonathan Tan"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"337393","messageId":"20180125185324.115317-1-jonathantanmy@google.com","threadId":"47695","inReplyTo":null,"subject":"[PATCH] Docs: split out long-running subprocess handshake","fromName":"Jonathan Tan","fromEmail":"jonathantanmy@google.com","sentAt":"2018-01-25T18:53:24Z","receivedAt":"2018-01-25T18:53:39Z","isPatch":true,"sender":{"key":"jonathantanmy@fastmail.com","avatar":null},"body":"Separating out the implementation of the handshake when starting a\nlong-running subprocess (for example, as is done for a clean/smudge\nfilter) was done in commit fa64a2fdbeed (\"sub-process: refactor\nhandshake to common function\", 2017-07-26), but its documentation still\nresides in gitattributes. Split out the documentation as well.\n\nSigned-off-by: Jonathan Tan <jonathantanmy@google.com>\n---\nThis is extracted from my patch from July 2017 [1], which later got\nsuperseded by another patch set that no longer used a long-running\nsubprocess.\n\nI think this patch (or something similar) is something we'll need sooner\nor later, but I'm also OK if we wait until we have a second usage of the\nlong-running subprocess to merge it in.\n\n[1]\nhttps://public-inbox.org/git/eadce97b6a1e80345a2621e71ce187e9e6bc05bf.1501532294.git.jonathantanmy@google.com/#t\n---\n Documentation/Makefile                             |  1 +\n Documentation/gitattributes.txt                    | 54 ++++------------------\n .../technical/long-running-process-protocol.txt    | 50 ++++++++++++++++++++\n sub-process.h                                      |  4 +-\n 4 files changed, 61 insertions(+), 48 deletions(-)\n create mode 100644 Documentation/technical/long-running-process-protocol.txt\n\ndiff --git a/Documentation/Makefile b/Documentation/Makefile\nindex 4ae9ba5c8..6232143cb 100644\n--- a/Documentation/Makefile\n+++ b/Documentation/Makefile\n@@ -72,6 +72,7 @@ TECH_DOCS += SubmittingPatches\n TECH_DOCS += technical/hash-function-transition\n TECH_DOCS += technical/http-protocol\n TECH_DOCS += technical/index-format\n+TECH_DOCS += technical/long-running-process-protocol\n TECH_DOCS += technical/pack-format\n TECH_DOCS += technical/pack-heuristics\n TECH_DOCS += technical/pack-protocol\ndiff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt\nindex 30687de81..c21f5ca10 100644\n--- a/Documentation/gitattributes.txt\n+++ b/Documentation/gitattributes.txt\n@@ -392,46 +392,14 @@ Long Running Filter Process\n If the filter command (a string value) is defined via\n `filter.<driver>.process` then Git can process all blobs with a\n single filter invocation for the entire life of a single Git\n-command. This is achieved by using a packet format (pkt-line,\n-see technical/protocol-common.txt) based protocol over standard\n-input and standard output as follows. All packets, except for the\n-\"*CONTENT\" packets and the \"0000\" flush packet, are considered\n-text and therefore are terminated by a LF.\n-\n-Git starts the filter when it encounters the first file\n-that needs to be cleaned or smudged. After the filter started\n-Git sends a welcome message (\"git-filter-client\"), a list of supported\n-protocol version numbers, and a flush packet. Git expects to read a welcome\n-response message (\"git-filter-server\"), exactly one protocol version number\n-from the previously sent list, and a flush packet. All further\n-communication will be based on the selected version. The remaining\n-protocol description below documents \"version=2\". Please note that\n-\"version=42\" in the example below does not exist and is only there\n-to illustrate how the protocol would look like with more than one\n-version.\n-\n-After the version negotiation Git sends a list of all capabilities that\n-it supports and a flush packet. Git expects to read a list of desired\n-capabilities, which must be a subset of the supported capabilities list,\n-and a flush packet as response:\n-------------------------\n-packet:          git> git-filter-client\n-packet:          git> version=2\n-packet:          git> version=42\n-packet:          git> 0000\n-packet:          git< git-filter-server\n-packet:          git< version=2\n-packet:          git< 0000\n-packet:          git> capability=clean\n-packet:          git> capability=smudge\n-packet:          git> capability=not-yet-invented\n-packet:          git> 0000\n-packet:          git< capability=clean\n-packet:          git< capability=smudge\n-packet:          git< 0000\n-------------------------\n-Supported filter capabilities in version 2 are \"clean\", \"smudge\",\n-and \"delay\".\n+command. This is achieved by using the long-running process protocol\n+(described in technical/long-running-process-protocol.txt).\n+\n+When Git encounters the first file that needs to be cleaned or smudged,\n+it starts the filter and performs the handshake. In the handshake, the\n+welcome message sent by Git is \"git-filter-client\", only version 2 is\n+suppported, and the supported capabilities are \"clean\", \"smudge\", and\n+\"delay\".\n \n Afterwards Git sends a list of \"key=value\" pairs terminated with\n a flush packet. The list will contain at least the filter command\n@@ -517,12 +485,6 @@ the protocol then Git will stop the filter process and restart it\n with the next file that needs to be processed. Depending on the\n `filter.<driver>.required` flag Git will interpret that as error.\n \n-After the filter has processed a command it is expected to wait for\n-a \"key=value\" list containing the next command. Git will close\n-the command pipe on exit. The filter is expected to detect EOF\n-and exit gracefully on its own. Git will wait until the filter\n-process has stopped.\n-\n Delay\n ^^^^^\n \ndiff --git a/Documentation/technical/long-running-process-protocol.txt b/Documentation/technical/long-running-process-protocol.txt\nnew file mode 100644\nindex 000000000..aa0aa9af1\n--- /dev/null\n+++ b/Documentation/technical/long-running-process-protocol.txt\n@@ -0,0 +1,50 @@\n+Long-running process protocol\n+=============================\n+\n+This protocol is used when Git needs to communicate with an external\n+process throughout the entire life of a single Git command. All\n+communication is in pkt-line format (see technical/protocol-common.txt)\n+over standard input and standard output.\n+\n+Handshake\n+---------\n+\n+Git starts by sending a welcome message (for example,\n+\"git-filter-client\"), a list of supported protocol version numbers, and\n+a flush packet. Git expects to read the welcome message with \"server\"\n+instead of \"client\" (for example, \"git-filter-server\"), exactly one\n+protocol version number from the previously sent list, and a flush\n+packet. All further communication will be based on the selected version.\n+The remaining protocol description below documents \"version=2\". Please\n+note that \"version=42\" in the example below does not exist and is only\n+there to illustrate how the protocol would look like with more than one\n+version.\n+\n+After the version negotiation Git sends a list of all capabilities that\n+it supports and a flush packet. Git expects to read a list of desired\n+capabilities, which must be a subset of the supported capabilities list,\n+and a flush packet as response:\n+------------------------\n+packet:          git> git-filter-client\n+packet:          git> version=2\n+packet:          git> version=42\n+packet:          git> 0000\n+packet:          git< git-filter-server\n+packet:          git< version=2\n+packet:          git< 0000\n+packet:          git> capability=clean\n+packet:          git> capability=smudge\n+packet:          git> capability=not-yet-invented\n+packet:          git> 0000\n+packet:          git< capability=clean\n+packet:          git< capability=smudge\n+packet:          git< 0000\n+------------------------\n+\n+Shutdown\n+--------\n+\n+Git will close\n+the command pipe on exit. The filter is expected to detect EOF\n+and exit gracefully on its own. Git will wait until the filter\n+process has stopped.\ndiff --git a/sub-process.h b/sub-process.h\nindex 49701998c..71b18ad5a 100644\n--- a/sub-process.h\n+++ b/sub-process.h\n@@ -73,8 +73,8 @@ static inline struct child_process *subprocess_get_child_process(\n }\n \n /*\n- * Perform the version and capability negotiation as described in the \"Long\n- * Running Filter Process\" section of the gitattributes documentation using the\n+ * Perform the version and capability negotiation as described in the\n+ * \"Handshake\" section of long-running-process-protocol.txt using the\n  * given requested versions and capabilities. The \"versions\" and \"capabilities\"\n  * parameters are arrays terminated by a 0 or blank struct.\n  *\n-- \n2.16.0.rc2.37.ge0d575025.dirty\n\n"}]}