Git is actually more lenient here than I thought. As long as the
identity contains the "<>" delimiters, Git will allow an empty email, so
we should accept the same thing. I also discovered that an identity with
only an email set will use the email as the name, so I've implemented
that behavior as well.
When processing mail-formatted patches, the default cleanup removed all
leading content in square brackets, but this pattern is often used to
identify tickets or other information that should remain in the commit
title. Git supports disabling this the the `-k` and `-b` flags, which we
simulate with the new SubjectCleanMode options.
Use WithSubjectCleanMode(SubjectCleanPatchOnly) to only remove bracketed
strings that contain "PATCH", keeping others that are (probably) part of
the actual commit message.
Note that because of the mail parsing library, we cannot replicate the
`-k` flag exactly and always clean leading and trailing whitespace.
Use standard string functions instead of removing leading whitespace in
a custom loop. This also makes the distinction between the two types of
mail header parsing a bit clearer.
`git am` will accept patches which aren't fully RFC-compliant, as long
as they start with `From` and have a `Subject` line. Relax
ParsePatchHeader() so that it will accept such patches as well.
Specifically, it will tolerate patches of the form:
From: <foo@company.com>
In this case, the `Author` field will contain `foo@company.com
<foo@company.com>`. Duplicate this behavior.
Signed-off-by: George Dunlap <george.dunlap@citrix.com>
Co-authored-by: George Dunlap <george.dunlap@citrix.com>
...when parsing emails, similar to `git am`.
Add a new field, `BodyAppendix` to PatchHeader.
Modify `scanMessageBody` to accept a boolean argument saying whether
to separate out the appendix or not. Do this by keeping two string
builders, and having it switch to the appendix builder when it finds a
`---` line.
Handling the newlines at the end as expected requires moving things
around a bit.
First, we were trimming space from the line once to decide whether the
line was empty, and then trimming space again if we determined it
wasn't empty. This only needs to be done once.
Then, do all the trimming (both of whitespace and the prefix) first,
before deciding what to do about the line.
Request BodyAppendix separately when parsing a mail, but not a commit
message.
Add some tests to verify that it works as expected.
Signed-off-by: George Dunlap <george.dunlap@citrix.com>
Co-authored-by: George Dunlap <george.dunlap@citrix.com>
Primarily to get rid of [PATCH] at the front, but while we're here
just be generally compatible with `git am`:
* Remove `re` and variations
* Remove whitespace
* Remove anything in brackets
But only at the very beginning of the subject.
Store anything removed in this way in PatchHeader.SubjectPrefix.
Inspired by
https://github.com/git/git/blob/master/mailinfo.c:cleanup_subject()
Signed-off-by: George Dunlap <george.dunlap@citrix.com>
Co-authored-by: George Dunlap <george.dunlap@citrix.com>
Removed the distinction between parsed and raw dates and simply return
an error for unsupported date formats. Arbitrary date support was
probably a premature optimization and would be better supported by a
method to register custom date parsing functions.
Simple time.Time fields make the structure easier to use and mean that
a zero value always indicates the patch did not include a date.
A closer look at the Git source shows that the rfc2822 and default
formats do not zero-pad days, so we need to accept single-digit days
when parsing. The single-digit pattern will also accept the padded
format, so there's no loss of functionality.
Change the parsing test to use single-digit values to emphasize when
padding is required and when it is not.
Git usually refers to the whole thing (title + body) as the "commit
message", so using different terms for the parts clarifies things. Also
add a new Message() function that returns the combined string.
This function parses patch headers (the preamble returned by the
existing Parse function) to extract information about the commit that
generated the patch. This is useful when patches are an interchange
format and this library is applying commits generated elsewhere.
Because of the variety of header formats, parsing is fairly lenient and
best-effort, although certain invalid input does cause errors.
This also extracts some test utilities from the apply tests for reuse.