Jonathan Tan <jonathantanmy@xxxxxxxxxx> writes: > One alternative is to postpone this decision by changing sequencer > only (and not trailer) to tolerate other lines in the trailer. This > would make them even more divergent (sequencer supports arbitrary > lines while trailer doesn't), but they were divergent already > (sequencer supports "(cherry picked by" but trailer doesn't). Given that we internally do not use the "trailers" for anything real, anything you decide to do here would be an improvement ;-) Before, users couldn't even get any of the examples (below, from your message) recognized as trailer blocks. > Signed-off-by: A <author@xxxxxxxxxxx> > [This has nothing to do with the above line] > Signed-off-by: B <buthor@xxxxxxxxxxx> > > and: > > Link 1: a link > a continuation of the above > > and: > > Signed-off-by: Some body <some@xxxxxxx> (comment > on two lines) So I would say it is perfectly OK if your update works only for cases we can clearly define the semantics for. For example, we can even start with something simple like: * A RFC822-header like line, together with any number of whitespace indented lines that immediately follow it, will be taken as a single logical trailer element (with embedded LF in it if it uses the "line folding"). For the purpose of "replace", the entire single logical trailer element is replaced. * A line that begins with "(cherry picked from" and "[" becomes a single logical trailer element. No continuation of anything fancy. * A line with any other shape is a garbage line in a trailer block. It is kept in its place, but because it does not even have <token> part, it will not participate in locating with "trailer.where", "trailer.ifexists", etc. A block of lines that appear as the last paragraph in a commit message is a trailer block if and only if certain number or percentage of lines are non-garbage lines according to the above definition. The operations done by the codepaths in the core part of the system are much simpler subset of what "interpret-trailers" wants to support, namely, - append "(cherry picked from X)" at the end. - append "S-o-b:" at the end. - append "S-o-b:" unless the same line appears as the last line in the existing trailer block. and these are quite compatible with a simplified definition of what a logical line is illustrated in the above example, I would think. I wonder if we can share a new helper function to do the detection (and classification) of a trailer block and parsing the logical lines out of a commit log message. The function signature could be as simple as taking a single <const char *> (or a strbuf) that holds a commit log message, and splitting it out into something like: struct { const char *whole; const char *end_of_message_proper; struct { const char *token; const char *contents; } *trailer; int alloc_trailers, nr_trailers; }; where - whole points at the first byte of the input, i.e. the beginning of the commit message buffer. - end-of-message-proper points at the first byte of the trailer block into the buffer at "whole". - token is a canonical header name for easy comparison for interpret-trailers (you can use NULL for garbage lines, and made up token like "[bracket]" and "(cherrypick)" that would not clash with real tokens like "Signed-off-by"). - contents is the bytes on the logical line, including the header part E.g. an element in trailer[] array may say { .token = "Signed-off-by", .contents = "Signed-Off-By: Some Body <some@xxxxxxx>\n", } With something like that, you can manipulate the "insert at ...", "replace", etc. in the trailer[] array and then produce an updated commit message fairly easily (i.e. copy out the bytes beginning at "whole" up to "end_of_message_proper", then iterate over trailer[] array and show their contents field). The codepaths in the core part only need to know - how to check the last item in trailer[] array to see if it ends with the same sign-off as they are trying to add. - how to append one new element to the trailer[] array. - reproduce an updated commit log message after the above. Hmm?