]> source.dussan.org Git - gitblit.git/commitdiff
Fix user mention regular expression and group replacement. merged--fixMentionsInTickets-985
authorFlorian Zschocke <florian.zschocke@devolo.de>
Sat, 10 Dec 2016 15:02:21 +0000 (16:02 +0100)
committerFlorian Zschocke <florian.zschocke@devolo.de>
Sat, 10 Dec 2016 15:17:21 +0000 (16:17 +0100)
The regular expression used for user mentions used to work
only inside sentences. Also, since it tested for whitespace, the
whitespace would get replaced, too, which would join lines together.

Instead the new regex uses boundary matchers to match against
word boundaires. As these are not capturing only the actual user
mention can be captured and is then replaced. Also, this way the
regex can ignore punctuation like in "@jim, look at this."

Since Gibtlit now requires Java 7 we can use named capture groups.
This makes the use of a centrally defined regular expression much
safer. The (admittedly only) group to capture the user name is named
"user" and can be referenced by this name. By using the name instead
of a group number, the regex could be changed without the code using
it breaking because the group number changed.

A simple test is added for user mentions, which unfortunately
has to deal with the full markdown replacement, too.

Fixes #985

src/main/java/com/gitblit/Constants.java
src/main/java/com/gitblit/models/TicketModel.java
src/main/java/com/gitblit/tickets/TicketNotifier.java
src/main/java/com/gitblit/utils/MarkdownUtils.java
src/test/java/com/gitblit/tests/MarkdownUtilsTest.java

index acfc2042250bce5989809d161ee68acc8f9896bc..c71128359c368cf6dc5b718a6cb4154cc8688ac9 100644 (file)
@@ -67,7 +67,7 @@ public class Constants {
         * This regular expression is used when searching for "mentions" in tickets\r
         * (when someone writes @thisOtherUser)\r
         */\r
-       public static final String REGEX_TICKET_MENTION = "\\s@([^\\s]+)";\r
+       public static final String REGEX_TICKET_MENTION = "\\B@(?<user>[^\\s]+)\\b";\r
 \r
        public static final String ZIP_PATH = "/zip/";\r
 \r
index 924400f5375e9825c54c238ddf87965481935f1b..65e29dc06a18348cf9b9cbf9b7e056eaa7a6e85e 100644 (file)
@@ -778,7 +778,7 @@ public class TicketModel implements Serializable, Comparable<TicketModel> {
                                Pattern mentions = Pattern.compile(Constants.REGEX_TICKET_MENTION);
                                Matcher m = mentions.matcher(text);
                                while (m.find()) {
-                                       String username = m.group(1);
+                                       String username = m.group("user");
                                        plusList(Field.mentions, username);
                                }
                        } catch (Exception e) {
index 1d7e4f243e4fcbbcbb45c24a45ad528b17a6e7b1..b913db2572a6182b7b063411e500dc1b27571f8f 100644 (file)
@@ -576,7 +576,7 @@ public class TicketNotifier {
                        Pattern p = Pattern.compile(Constants.REGEX_TICKET_MENTION);
                        Matcher m = p.matcher(lastChange.comment.text);
                        while (m.find()) {
-                               String username = m.group();
+                               String username = m.group("user");
                                ccs.add(username);
                        }
                }
index 794d54ab189aee99b30877a373322a146dcf1743..8371b3c6440c868cda8392e1dd71b53daf8b1e9f 100644 (file)
@@ -138,7 +138,7 @@ public class MarkdownUtils {
                String canonicalUrl = settings.getString(Keys.web.canonicalUrl, "https://localhost:8443");\r
 \r
                // emphasize and link mentions\r
-               String mentionReplacement = String.format(" **[@$1](%1s/user/$1)**", canonicalUrl);\r
+               String mentionReplacement = String.format("**[@${user}](%1s/user/${user})**", canonicalUrl);\r
                text = text.replaceAll(Constants.REGEX_TICKET_MENTION, mentionReplacement);\r
 \r
                // link ticket refs
index e40f1057a42584f776417f8954593f7b29b236b8..bc7aad49a40d00b87325fa7e2a367ca9d8d50be3 100644 (file)
  */\r
 package com.gitblit.tests;\r
 \r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
 import org.junit.Test;\r
 \r
+import com.gitblit.IStoredSettings;\r
+import com.gitblit.Keys;\r
+import com.gitblit.tests.mock.MemorySettings;\r
 import com.gitblit.utils.MarkdownUtils;\r
 \r
 public class MarkdownUtilsTest extends GitblitUnitTest {\r
@@ -39,4 +45,70 @@ public class MarkdownUtilsTest extends GitblitUnitTest {
                assertEquals("<table><tr><td>&lt;test&gt;</td></tr></table>",\r
                                MarkdownUtils.transformMarkdown("<table><tr><td>&lt;test&gt;</td></tr></table>"));\r
        }\r
-}
\ No newline at end of file
+\r
+\r
+       @Test\r
+       public void testUserMentions() {\r
+               IStoredSettings settings = getSettings();\r
+               String repositoryName = "test3";\r
+               String mentionHtml = "<strong><a href=\"http://localhost/user/%1$s\">@%1$s</a></strong>";\r
+\r
+               String input = "@j.doe";\r
+               String output = "<p>" + String.format(mentionHtml, "j.doe") + "</p>";\r
+               assertEquals(output, MarkdownUtils.transformGFM(settings, input, repositoryName));\r
+\r
+               input = " @j.doe";\r
+               output = "<p>" + String.format(mentionHtml, "j.doe") + "</p>";\r
+               assertEquals(output, MarkdownUtils.transformGFM(settings, input, repositoryName));\r
+\r
+               input = "@j.doe.";\r
+               output = "<p>" + String.format(mentionHtml, "j.doe") + ".</p>";\r
+               assertEquals(output, MarkdownUtils.transformGFM(settings, input, repositoryName));\r
+\r
+               input = "To @j.doe: ask @jim.beam!";\r
+               output = "<p>To " + String.format(mentionHtml, "j.doe")\r
+                               + ": ask " + String.format(mentionHtml, "jim.beam") + "!</p>";\r
+               assertEquals(output, MarkdownUtils.transformGFM(settings, input, repositoryName));\r
+\r
+               input =   "@sta.rt\n"\r
+                               + "\n"\r
+                               + "User mentions in tickets are broken.\n"\r
+                               + "So:\n"\r
+                               + "@mc_guyver can fix this.\n"\r
+                               + "@j.doe, can you test after the fix by @m+guyver?\n"\r
+                               + "Please review this, @jim.beam!\n"\r
+                               + "Was reported by @jill and @j!doe from jane@doe yesterday.\n"\r
+                               + "\n"\r
+                               + "@jack.daniels can vote for john@wayne.name hopefully.\n"\r
+                               + "@en.de";\r
+               output =  "<p>" + String.format(mentionHtml, "sta.rt") + "</p>"\r
+                               + "<p>" + "User mentions in tickets are broken.<br/>"\r
+                               + "So:<br/>"\r
+                               + String.format(mentionHtml, "mc_guyver") + " can fix this.<br/>"\r
+                               + String.format(mentionHtml, "j.doe") + ", can you test after the fix by " + String.format(mentionHtml, "m+guyver") + "?<br/>"\r
+                               + "Please review this, " + String.format(mentionHtml, "jim.beam") + "!<br/>"\r
+                               + "Was reported by " + String.format(mentionHtml, "jill")\r
+                               + " and " + String.format(mentionHtml, "j!doe")\r
+                               + " from <a href=\"mailto:&#106;a&#110;&#x65;&#x40;&#x64;&#x6f;&#101;\">&#106;a&#110;&#x65;&#x40;&#x64;&#x6f;&#101;</a> yesterday." \r
+                               + "</p>"\r
+                               + "<p>" + String.format(mentionHtml, "jack.daniels") + " can vote for "\r
+                               + "<a href=\"mailto:&#x6a;&#x6f;h&#110;&#x40;&#119;a&#121;&#110;&#101;.&#110;a&#x6d;&#101;\">&#x6a;&#x6f;h&#110;&#x40;&#119;a&#121;&#110;&#101;.&#110;a&#x6d;&#101;</a> hopefully.<br/>"\r
+                               + String.format(mentionHtml, "en.de")\r
+                               + "</p>";\r
+               assertEquals(output, MarkdownUtils.transformGFM(settings, input, repositoryName));\r
+\r
+       }\r
+\r
+\r
+\r
+\r
+       private MemorySettings getSettings() {\r
+               Map<String, Object> backingMap = new HashMap<String, Object>();\r
+\r
+               backingMap.put(Keys.web.canonicalUrl, "http://localhost");\r
+               backingMap.put(Keys.web.shortCommitIdLength, "7");\r
+\r
+               MemorySettings ms = new MemorySettings(backingMap);\r
+               return ms;\r
+       }\r
+}\r