help-gnats
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: 4.0 beta - question on parsing of subject line in PR header


From: Mel Hatzis
Subject: Re: 4.0 beta - question on parsing of subject line in PR header
Date: Thu, 23 May 2002 11:41:16 -0700
User-agent: Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:0.9.8) Gecko/20020206

Milan Zamazal wrote:
"YS" == Yngve Svendsen <address@hidden> writes:


    YS> At 16:19 15.05.2002 -0700, Mel Hatzis wrote:
    >> Thinking about this some more, it would be *really* useful to
    >> allow this regular expression to be overriden in the dbconfig
    >> file. Allowing user's to define their own would provide them the
    >> flexibility to get as fancy as they want with some of the corner
    >> cases where the default regex behaviour is not desirable...such
    >> as "Re: PR 50 (was PR 33)" which matches PR 33.
>> >> Thoughts?

    YS> I agree strongly with this.

Me too.  If someone sends appropriate patches, I'll be happy to
incorporate them.  (If anyone wants to do it before the 4.0 release,
please test it carefully and include documentation patches as well.)


OK, I've attached a patchfile for this.

You can now (optionally) include the following in the database-info
section of the dbconfig file:

    # The regular expression used to determine whether a PR is referenced
    # on an email subject line
    subject-matching {
        "\\<((PR[ \t/])\\|([-a-z0-9_+.]+/))([0-9]+)"
        capture-group "4"
    }

(The above example is exactly analogous to the built-in default)

Regarding documentation, I've updated the man page for dbconfig. One thing
I didn't mention is that if you include a regex which doesn't compile, GNATS
will revert to using the default - and will also email the gnats-admin via punt.

Invalid values for the capture-group similarly generate email to gnats-admin,
though in this case, GNATS does not revert to the default - it simply assumes
no PR's are referenced on the subject line. I'm not clear on whether this
too should revert to using the default, but decided against it since the
associated regex would be valid in this case.

A possible enhancement would be to allow multiple regular expressions to
be specified, each with their own capture group. Alternatively, it might
be nice to allow multiple capture groups, making it possible to update
multiple PR's using a single submission.

--
Mel Hatzis
Juniper Networks, Inc.
Index: database.c
===================================================================
RCS file: /cvsroot/gnats/gnats/gnats/database.c,v
retrieving revision 1.23
diff -b -u -p -r1.23 database.c
--- database.c  29 Oct 2001 22:40:26 -0000      1.23
+++ database.c  23 May 2002 17:17:10 -0000
@@ -29,6 +29,7 @@ struct databaseInfo
   int keepReceivedHeadersFlag;
   int notifyExpireFlag;
   char *binDirValue;
+  SubjectMatchInfo subjectMatch;
   int submitterAckFlag;
   unsigned int businessDay[2];
   unsigned int businessWeek[2];
@@ -69,6 +70,7 @@ newDatabaseInfo (void)
   res->keepReceivedHeadersFlag = 0;
   res->notifyExpireFlag = 0;
   res->binDirValue = NULL;
+  res->subjectMatch = NULL;
   res->submitterAckFlag = 0;
   res->businessDay[0] = 0; res->businessDay[1] = 0;
   res->businessWeek[0] = 0; res->businessWeek[1] = 0;
@@ -248,6 +250,23 @@ setCategoryDirPerms (DatabaseInfo databa
 }
 
 void
+setSubjectMatch (DatabaseInfo database, const char *regex, const char *prIdx)
+{
+  if (databaseValid (database))
+    {
+      if (database->subjectMatch != NULL)
+       {
+         free (database->subjectMatch->regex);
+         free (database->subjectMatch);
+       }
+      database->subjectMatch =
+        (SubjectMatchInfo) xmalloc (sizeof (struct subjectMatchInfo));
+      database->subjectMatch->regex = xstrdup (regex);
+      database->subjectMatch->prIdx = atoi (prIdx);
+    }
+}
+
+void
 addGlobalChangeActions (DatabaseInfo database, ChangeActions actions)
 {
   if (databaseValid (database))
@@ -531,6 +550,19 @@ categoryDirPerms (const DatabaseInfo dat
     }
 }
 
+SubjectMatchInfo
+subjectMatch (const DatabaseInfo database)
+{
+  if (databaseValid (database))
+    {
+      return database->subjectMatch;
+    }
+  else
+    {
+      return NULL;
+    }
+}
+
 char *
 gnats_adm_dir (const DatabaseInfo database, const char *filename)
 {
@@ -964,6 +996,11 @@ freeDatabaseInfo (DatabaseInfo database)
       if (database->binDirValue != NULL)
        {
          free (database->binDirValue);
+       }
+      if (database->subjectMatch != NULL)
+       {
+         free (database->subjectMatch->regex);
+         free (database->subjectMatch);
        }
       if (database->next != NULL)
        {
Index: database.h
===================================================================
RCS file: /cvsroot/gnats/gnats/gnats/database.h,v
retrieving revision 1.12
diff -b -u -p -r1.12 database.h
--- database.h  4 Jul 2001 18:26:28 -0000       1.12
+++ database.h  23 May 2002 17:17:10 -0000
@@ -24,6 +24,13 @@ Software Foundation, 59 Temple Place - S
 struct databaseInfo;
 typedef struct databaseInfo * DatabaseInfo;
 
+struct subjectMatchInfo
+{
+    char *regex;
+    unsigned int prIdx;
+};
+typedef struct subjectMatchInfo *SubjectMatchInfo;
+
 #include "adm.h"
 #include "mail.h"
 
@@ -93,6 +100,9 @@ extern void addGlobalChangeActions (Data
                                    ChangeActions actions);
 extern void setCategoryDirPerms (DatabaseInfo database, 
                                 const char *value);
+extern void setSubjectMatch(DatabaseInfo database,
+                            const char *regex,
+                            const char *prIdx);
 extern void setInputTemplate (DatabaseInfo database,
                              InputTemplate *template);
 extern void setQueryFormatList (DatabaseInfo database,
@@ -122,6 +132,7 @@ extern ChangeActions globalChangeActions
 extern int createCategoryDirs (const DatabaseInfo database);
 QueryFormat *getAuditTrailFormat (const DatabaseInfo database);
 extern int categoryDirPerms (const DatabaseInfo database);
+extern SubjectMatchInfo subjectMatch (const DatabaseInfo database);
 extern IndexDesc getIndexDesc (const DatabaseInfo database);
 extern InputTemplate *getInputTemplate (const DatabaseInfo database);
 extern QueryFormat *getQueryFormatList (const DatabaseInfo database);
Index: fconfig.y
===================================================================
RCS file: /cvsroot/gnats/gnats/gnats/fconfig.y,v
retrieving revision 1.35
diff -b -u -p -r1.35 fconfig.y
--- fconfig.y   8 Dec 2001 20:21:20 -0000       1.35
+++ fconfig.y   23 May 2002 17:17:10 -0000
@@ -43,8 +43,8 @@
 %token BODYTOK HEADERTOK AUDITTRAILFMTTOK ADDAUDITTRAILTOK 
 %token REQUIRECHANGEREASONTOK READONLYTOK BINARYINDEXTOK RAWTOK
 %token BADTOK AUXFLAGSTOK PRLISTTOK MAXPRSTOK EDITONLYTOK VIRTUALFORMATTOK
-%token CATPERMSTOK
-%type <sval> optChangeExpr
+%token CATPERMSTOK SUBJECTMATCHINGTOK CAPTUREGROUPTOK
+%type <sval> optChangeExpr captureGroup
 %type <qstr> QSTRING
 %type <intval> INTVAL
 %type <adm_field_des> enumFieldList enumFieldMember
@@ -104,6 +104,12 @@ databaseInfoEnt    : DEBUGMODETOK booleanVa
                | CATPERMSTOK QSTRING {
                    setCategoryDirPerms (databaseBeingDefined, qStrVal ($2));
                }
+               | SUBJECTMATCHINGTOK '{' QSTRING captureGroup '}' {
+                   setSubjectMatch(databaseBeingDefined, qStrVal ($3), $4);
+               }
+               ;
+
+captureGroup   : CAPTUREGROUPTOK QSTRING { $$ = takeQString ($2); }
                ;
 
 booleanVal     : FALSETOK { $$ = 0; }
Index: fconfigl.l
===================================================================
RCS file: /cvsroot/gnats/gnats/gnats/fconfigl.l,v
retrieving revision 1.23
diff -b -u -p -r1.23 fconfigl.l
--- fconfigl.l  29 Oct 2001 22:40:38 -0000      1.23
+++ fconfigl.l  23 May 2002 17:17:10 -0000
@@ -305,6 +305,14 @@ create-category-dirs {
     return CREATECATEGORYDIRSTOK;
 }
 
+subject-matching {
+    return SUBJECTMATCHINGTOK;
+}
+
+capture-group {
+    return CAPTUREGROUPTOK;
+}
+
 false {
     return FALSETOK;
 }
Index: file-pr.c
===================================================================
RCS file: /cvsroot/gnats/gnats/gnats/file-pr.c,v
retrieving revision 1.46
diff -b -u -p -r1.46 file-pr.c
--- file-pr.c   16 May 2002 23:24:57 -0000      1.46
+++ file-pr.c   23 May 2002 17:17:11 -0000
@@ -576,6 +576,9 @@ checkIfReply (PR *pr, ErrorDesc *err)
   char case_fold[256];
   char *possiblePrNum;
   reg_syntax_t old_syntax;
+  SubjectMatchInfo subject_match;
+  unsigned prIdx = 4;
+  const char *retval = NULL;
 
   headerValue = header_value (pr, SUBJECT);
 
@@ -593,16 +596,37 @@ checkIfReply (PR *pr, ErrorDesc *err)
     }
   regex.translate = case_fold;
   
+  subject_match = subjectMatch (pr->database);
+  if (subject_match != NULL)
   {
-    const char *const PAT = "\\<((PR[ \t/])\\|([-a-z0-9_+.]+)/)([0-9]+)";
+      retval = re_compile_pattern (subject_match->regex,
+                                   strlen (subject_match->regex), &regex);
+      if (retval == NULL)
+        {
+          prIdx = subject_match->prIdx; /* regex compiled successfully */
+        }
+      else
+        {
+          const char *PAT = "\\<((PR[ \t/])\\|([-a-z0-9_+.]+)/)([0-9]+)";
+          punt (pr->database, 0,
+              "Invalid regular expression defined for 'subject-matching' in 
dbconfig: %s\n\nReverting to default regular expression.\n\n", retval);
     re_compile_pattern (PAT, strlen (PAT), &regex);
   }
+    }
+
   i = re_search (&regex, headerValue, strlen (headerValue), 0,
                 strlen (headerValue), &regs);
   regex.translate = NULL;
   regfree (&regex);
   re_set_syntax (old_syntax);
 
+  if (prIdx >= regs.num_regs || regs.start[prIdx] == -1)
+    {
+      punt (pr->database, 0,
+            "illegal capture-group defined for subject-matching in 
dbconfig\n");
+      return NULL;
+    }
+
   if (i < 0)
     {
       return NULL;
@@ -610,7 +634,7 @@ checkIfReply (PR *pr, ErrorDesc *err)
 
   start = regs.start[0];
   end = regs.end[0];
-  idstart = regs.start[4] - start;
+  idstart = regs.start[prIdx] - start;
 
   free (regs.start);
   free (regs.end);
Index: man/dbconfig.man
===================================================================
RCS file: /cvsroot/gnats/gnats/gnats/man/dbconfig.man,v
retrieving revision 1.1
diff -b -u -p -r1.1 dbconfig.man
--- man/dbconfig.man    10 Mar 2000 04:49:29 -0000      1.1
+++ man/dbconfig.man    23 May 2002 17:17:11 -0000
@@ -131,6 +131,18 @@ to \fItrue\fR.
 .P
 The default value is \fItrue\fR.
 .RE
+.TP
+\fBsubject-matching\fR { "\fIregexp\fR" \fBcapture-group\fR "\fIinteger\fR" }
+Specifies the regular expression used by GNATS to determine whether
+the subject line in a PR header references a PR. The regular expression
+must capture the PR number.  The integer specified by capture-group identifies
+which pattern match group contains the PR number.
+.RS 0.5i
+.P
+If subject-matching is not specified, GNATS uses
+"\\\\<((PR[ \\t/])\\\\|([-a-z0-9_+.]+/))([0-9]+)"
+as the default for \fIregexp\fR with 4 as the associated capture-group integer.
+.RE
 
 .SH "Individual field configuration"
 Each field in a PR is described with a field entry. It has the general 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]