git: 99589993ceb5 - main - git-arc: Fix review title matching

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Mon, 14 Feb 2022 15:07:05 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=99589993ceb5e6ec2511f29899e75bab1ef2f325

commit 99589993ceb5e6ec2511f29899e75bab1ef2f325
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2022-02-14 14:41:49 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2022-02-14 15:06:47 +0000

    git-arc: Fix review title matching
    
    Properly handle the case where the title of one commit is a suffix or
    prefix of the title of a second commit, and one wishes to create reviews
    for both.
    
    Reported by:    chuck
---
 tools/tools/git/git-arc.sh | 33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/tools/tools/git/git-arc.sh b/tools/tools/git/git-arc.sh
index 35a815ece137..835fbd91a7a1 100644
--- a/tools/tools/git/git-arc.sh
+++ b/tools/tools/git/git-arc.sh
@@ -187,6 +187,22 @@ log2diff()
     fi
 }
 
+# Look for an open revision with a title equal to the input string.  Return
+# a possibly empty list of Differential revision IDs.
+title2diff()
+{
+    local title
+
+    title=$1
+    # arc list output always includes ANSI escape sequences, strip them.
+    arc list | sed 's/\x1b\[[0-9;]*m//g' | \
+        awk -F': ' '{
+            if (substr($0, index($0, FS) + length(FS)) == "'"$title"'") {
+                print substr($1, match($1, "D[1-9][0-9]*"))
+            }
+        }'
+}
+
 commit2diff()
 {
     local commit diff title
@@ -204,7 +220,7 @@ commit2diff()
     # Second, search the open reviews returned by 'arc list' looking
     # for a subject match.
     title=$(git show -s --format=%s "$commit")
-    diff=$(arc list | grep -F "$title" | grep -E -o 'D[1-9][0-9]*:' | tr -d ':')
+    diff=$(title2diff "$title")
     if [ -z "$diff" ]; then
         err "could not find review for '${title}'"
     elif [ "$(echo "$diff" | wc -l)" -ne 1 ]; then
@@ -408,9 +424,10 @@ gitarc__create()
 
 gitarc__list()
 {
-    local chash commit commits diff title
+    local chash commit commits diff openrevs title
 
     commits=$(build_commit_list "$@")
+    openrevs=$(arc list)
 
     for commit in $commits; do
         chash=$(git show -s --format='%C(auto)%h' "$commit")
@@ -423,10 +440,10 @@ gitarc__list()
         fi
 
         # This does not use commit2diff as it needs to handle errors
-        # differently and keep the entire status.  The extra 'cat'
-        # after 'fgrep' avoids erroring due to -e.
+        # differently and keep the entire status.
         title=$(git show -s --format=%s "$commit")
-        diff=$(arc list | grep -F "$title" | cat)
+        diff=$(echo "$openrevs" | \
+            awk -F'D[1-9][0-9]*:\.\\[m ' '{if ($2 == "'"$title"'") print $0}')
         if [ -z "$diff" ]; then
             echo "No Review      : $title"
         elif [ "$(echo "$diff" | wc -l)" -ne 1 ]; then
@@ -456,7 +473,7 @@ gitarc__patch()
 
 gitarc__stage()
 {
-    local author branch commit commits diff reviewers tmp
+    local author branch commit commits diff reviewers title tmp
 
     branch=main
     while getopts b: o; do
@@ -482,8 +499,8 @@ gitarc__stage()
     tmp=$(mktemp)
     for commit in $commits; do
         git show -s --format=%B "$commit" > "$tmp"
-        diff=$(arc list | grep -F "$(git show -s --format=%s "$commit")" |
-            grep -E -o 'D[1-9][0-9]*:' | tr -d ':')
+        title=$(git show -s --format=%s "$commit")
+        diff=$(title2diff "$title")
         if [ -n "$diff" ]; then
             # XXX this leaves an extra newline in some cases.
             reviewers=$(diff2reviewers "$diff" | sed '/^$/d' | paste -sd ',' - | sed 's/,/, /g')