From: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>

S-o-b in the middle of a sentence, at the beginning of the sentence
but it is just because of text wrapping, or a full paragraph of valid
S-o-b in the middle of the message. All these are not S-o-b, but
detected as is. Fix them.

[bc: add two additional tests to demonstrate shortcomings of the current
   code:

   1. failure to detect non-conforming elements in the footer when last
      line matches committer's s-o-b.
   2. failure to handle various s-o-b -like elements in the footer as
      conforming. e.g. "Change-id: IXXXX or Bug: 1234"

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
Signed-off-by: Brandon Casey <bca...@nvidia.com>
---
 log-tree.c              | 37 +++++++++++++++++--
 t/t4014-format-patch.sh | 95 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 130 insertions(+), 2 deletions(-)

diff --git a/log-tree.c b/log-tree.c
index 4f86def..14ebf69 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -260,14 +260,47 @@ static void append_signoff(struct strbuf *sb, const char 
*signoff)
        int has_signoff = 0;
        char *cp;
 
-       cp = sb->buf;
+       /*
+        * Only search in the last paragrah, don't be fooled by a
+        * paragraph full of valid S-o-b in the middle.
+        */
+       cp = sb->buf + sb->len - 1;
+       while (cp > sb->buf) {
+               if (cp[0] == '\n' && cp[1] == '\n') {
+                       cp += 2;
+                       break;
+               }
+               cp--;
+       }
 
        /* First see if we already have the sign-off by the signer */
        while ((cp = strstr(cp, signed_off_by))) {
+               const char *s = cp;
+               cp += strlen(signed_off_by);
+
+               if (!has_signoff && s > sb->buf) {
+                       /*
+                        * S-o-b in the middle of a sentence is not
+                        * really S-o-b
+                        */
+                       if (s[-1] != '\n')
+                               continue;
+
+                       if (s - 1 > sb->buf && s[-2] == '\n')
+                               ; /* the first S-o-b */
+                       else if (!detect_any_signoff(sb->buf, s - sb->buf))
+                               /*
+                                * The previous line looks like an
+                                * S-o-b. There's still no guarantee
+                                * that it's an actual S-o-b. For that
+                                * we need to look back until we find
+                                * a blank line, which is too costly.
+                                */
+                               continue;
+               }
 
                has_signoff = 1;
 
-               cp += strlen(signed_off_by);
                if (cp + signoff_len >= sb->buf + sb->len)
                        break;
                if (strncmp(cp, signoff, signoff_len))
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index dfe9209..30e37a7 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -1062,6 +1062,60 @@ EOF
        test_cmp expected actual
 '
 
+test_expect_success 'signoff: not really a signoff' '
+       append_signoff <<\EOF >actual &&
+subject
+
+I want to mention about Signed-off-by: here.
+EOF
+       cat >expected <<\EOF &&
+4:Subject: [PATCH] subject
+8:
+9:I want to mention about Signed-off-by: here.
+10:
+11:Signed-off-by: C O Mitter <commit...@example.com>
+EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'signoff: not really a signoff (2)' '
+       append_signoff <<\EOF >actual &&
+subject
+
+My unfortunate
+Signed-off-by: example happens to be wrapped here.
+EOF
+       cat >expected <<\EOF &&
+4:Subject: [PATCH] subject
+8:
+10:Signed-off-by: example happens to be wrapped here.
+11:
+12:Signed-off-by: C O Mitter <commit...@example.com>
+EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
+       append_signoff <<\EOF >actual &&
+subject
+
+Signed-off-by: my@house
+Signed-off-by: your@house
+
+A lot of houses.
+EOF
+       cat >expected <<\EOF &&
+4:Subject: [PATCH] subject
+8:
+9:Signed-off-by: my@house
+10:Signed-off-by: your@house
+11:
+13:
+14:Signed-off-by: C O Mitter <commit...@example.com>
+EOF
+       test_cmp expected actual
+'
+
 test_expect_success 'signoff: the same signoff at the end' '
        append_signoff <<\EOF >actual &&
 subject
@@ -1109,4 +1163,45 @@ EOF
        test_cmp expected actual
 '
 
+test_expect_failure 'signoff: detect garbage in non-conforming footer' '
+       append_signoff <<\EOF >actual &&
+subject
+
+body
+
+Tested-by: my@house
+Some Trash
+Signed-off-by: C O Mitter <commit...@example.com>
+EOF
+       cat >expected <<\EOF &&
+4:Subject: [PATCH] subject
+8:
+10:
+13:Signed-off-by: C O Mitter <commit...@example.com>
+14:
+15:Signed-off-by: C O Mitter <commit...@example.com>
+EOF
+       test_cmp expected actual
+'
+
+test_expect_failure 'signoff: footer begins with non-signoff without @ sign' '
+       append_signoff <<\EOF >actual &&
+subject
+
+body
+
+Tested-by: my@house
+Change-id: Ideadbeef
+Signed-off-by: C O Mitter <commit...@example.com>
+Bug: 1234
+EOF
+       cat >expected <<\EOF &&
+4:Subject: [PATCH] subject
+8:
+10:
+13:Signed-off-by: C O Mitter <commit...@example.com>
+EOF
+       test_cmp expected actual
+'
+
 test_done
-- 
1.8.0.284.g959048a

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to