help-gnats
[Top][All Lists]
Advanced

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

Patch: Required fields on inital PR creation


From: Mel Hatzis
Subject: Patch: Required fields on inital PR creation
Date: Tue, 15 Oct 2002 16:42:58 -0700
User-agent: Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.0.0) Gecko/20020530

Please review (and hopefully accept) the following patch that fixes a bug
in the 'on-change require' functionality and also expands the Gnats grammar
to allow for "required input fields" upon initial PR creation.

1/ The "require { fields }" functionality that's part of the on-change edit
   options for a field is only doing a check for field_value == NULL right now
   (rather than also checking for empty strings). Since field values are
   generally initialized to an empty string (upon creation), the 'require'
   clause is basically useless. The patch adds a check for field_value == "".

2/ It is extremely useful to allow the Gnats administrator to configure
   Gnats so that a predefined set of fields must be assigned a value upon 
initial
   PR creation. Together with the field's own 'on-change require' clause, this
   allows for fields that can never have a null (blank) value.
   Allowing the Gnats administrator to enforce non-null fields this way provides
   a powerful mechanism toward improved data integrity.

The following snippet of the default-provided dbconfig demonstrates how this
patch allows one to define the "Quarter" field as a field that can never be 
null:

  field "Quarter" {
      description "What quarter does the PR fall into?"
      text
      query-default inexact-regexp
      textsearch

      # never allow the user to edit this field and reset it to a blank
      on-change {
          require { "Quarter" }
      }
  }
  ...
  initial-entry {
      fields {
          "Notify-List" "Submitter-Id" "Originator" "Organization" "Synopsis"
          "Confidential" "Severity" "Priority" "Category" "Class" "Quarter"
          "Release" "Environment" "Description" "How-To-Repeat" "Fix"
      }

      # ensure a value for Quarter is provided before accepting new PRs
      require { "Quarter" }
  }

--
Mel Hatzis
Juniper Networks, Inc.
Index: doc/p-admin.texi
===================================================================
RCS file: /cvsroot/gnats/gnats/doc/p-admin.texi,v
retrieving revision 1.27
diff -b -u -p -r1.27 p-admin.texi
--- doc/p-admin.texi    14 Oct 2002 22:11:58 -0000      1.27
+++ doc/p-admin.texi    15 Oct 2002 23:09:41 -0000
@@ -1069,12 +1069,16 @@ separator character.
 An @code{initial-entry} section in the @file{dbconfig} file is used to
 describe which fields should be present on initial PR entry; this is
 used by tools such as send-pr to determine which fields to include in a
-``blank'' PR template. The general format for the @code{initial-entry}
-section is
+``blank'' PR template. An optional @code{require} parameter can be
+defined to specify a subset of the @code{intial-entry} fields which must
+be assigned a value upon initial creation of the PR.
+
+The general format for the @code{initial-entry} section is
 
 @example
 initial-entry @{
 @ @ fields @{ "fieldname" [ "fieldname" ... ] @}
+@ @ [ require @{ "fieldname" [ "fieldname" ... ] @} ]
 @}
 @end example
 
Index: gnats/database.c
===================================================================
RCS file: /cvsroot/gnats/gnats/gnats/database.c,v
retrieving revision 1.23
diff -b -u -p -r1.23 database.c
--- gnats/database.c    29 Oct 2001 22:40:26 -0000      1.23
+++ gnats/database.c    15 Oct 2002 23:09:41 -0000
@@ -39,6 +39,7 @@ struct databaseInfo
   char *databaseName;
   AdmEntry *databaseEnt;
   ChangeActions changeActions;
+  FieldList requiredInputFields;
   DatabaseFieldInfo fieldInfo;
   AdmEntry *hostList;
   IndexDesc indexDesc;
@@ -83,6 +84,7 @@ newDatabaseInfo (void)
   res->databaseName = NULL;
   res->databaseEnt = NULL;
   res->changeActions = NULL;
+  res->requiredInputFields = NULL;
   res->fieldInfo = NULL;
   res->hostList = NULL;
   res->indexDesc = NULL;
@@ -264,6 +266,15 @@ addGlobalChangeActions (DatabaseInfo dat
 }
 
 void
+setRequiredInputFields (DatabaseInfo database, FieldList list)
+{
+  if (databaseValid (database))
+    {
+      database->requiredInputFields = list;
+    }
+}
+
+void
 setIndexDesc (DatabaseInfo database, IndexDesc new)
 {
   if (databaseValid (database))
@@ -850,6 +861,12 @@ getAuditTrailFormat (const DatabaseInfo 
     }
 }
 
+FieldList
+getRequiredInputFields (const DatabaseInfo database)
+{
+  return database->requiredInputFields;
+}
+
 IndexDesc
 getIndexDesc (const DatabaseInfo database)
 {
@@ -957,6 +974,7 @@ freeDatabaseInfo (DatabaseInfo database)
       clearHostList (database);
       clearInputTemplate (database);
       clearGlobalChangeActions (database);
+      freeFieldList (database->requiredInputFields);
       if (database->databaseName != NULL)
        {
          free (database->databaseName);
Index: gnats/database.h
===================================================================
RCS file: /cvsroot/gnats/gnats/gnats/database.h,v
retrieving revision 1.12
diff -b -u -p -r1.12 database.h
--- gnats/database.h    4 Jul 2001 18:26:28 -0000       1.12
+++ gnats/database.h    15 Oct 2002 23:09:41 -0000
@@ -101,6 +101,7 @@ extern void setBuiltinDBField (DatabaseI
                               FieldIndex fieldIndex);
 extern void setMailFormatList (DatabaseInfo database,
                               MailMessageFormat mailFormatList);
+extern void setRequiredInputFields (DatabaseInfo database, FieldList list);
 
 extern void setIndexDesc (DatabaseInfo database, const IndexDesc desc);
 
@@ -122,6 +123,7 @@ extern ChangeActions globalChangeActions
 extern int createCategoryDirs (const DatabaseInfo database);
 QueryFormat *getAuditTrailFormat (const DatabaseInfo database);
 extern int categoryDirPerms (const DatabaseInfo database);
+extern FieldList getRequiredInputFields (const DatabaseInfo database);
 extern IndexDesc getIndexDesc (const DatabaseInfo database);
 extern InputTemplate *getInputTemplate (const DatabaseInfo database);
 extern QueryFormat *getQueryFormatList (const DatabaseInfo database);
Index: gnats/edit.c
===================================================================
RCS file: /cvsroot/gnats/gnats/gnats/edit.c,v
retrieving revision 1.57
diff -b -u -p -r1.57 edit.c
--- gnats/edit.c        4 Aug 2002 10:58:04 -0000       1.57
+++ gnats/edit.c        15 Oct 2002 23:09:41 -0000
@@ -1104,7 +1104,8 @@ applyChangeAction (ChangeActions action,
 
   while (fields != NULL)
     {
-      if (get_field_value (pr, oldPR, fields->ent, NULL, NULL) == NULL)
+      const char *fldval = get_field_value (pr, oldPR, fields->ent, NULL, 
NULL);
+      if (fldval == NULL || *fldval == '\0')
        {
          setError (err, CODE_INVALID_PR_CONTENTS,
                    "Required field %s missing from PR %s.",
Index: gnats/fconfig.y
===================================================================
RCS file: /cvsroot/gnats/gnats/gnats/fconfig.y,v
retrieving revision 1.35
diff -b -u -p -r1.35 fconfig.y
--- gnats/fconfig.y     8 Dec 2001 20:21:20 -0000       1.35
+++ gnats/fconfig.y     15 Oct 2002 23:09:41 -0000
@@ -7,6 +7,7 @@
   static ChangeActions currChange;
   static FieldEdit *currEdit;
   static QueryFormat *qformat;
+  static FieldList requiredFlds;
   static InputTemplate *inputTemplate;
   static MailMessageFormat mailFormat;
   IndexDesc indexEntry;
@@ -55,13 +56,14 @@
 %type <flist> mailAddressTries MailAddressMember
 %type <mailaddr> mailAddress
 %type <mailaddrlist> mailAddressList
+%type <flist> requiredFieldsList
 %%
 
 config         : configEnts
                | parseError
                ;
 
-configEnts     : databaseInfo fieldDecStmt optQueryList auditTrailFmt 
mailFormatList globalChangeEnts indexDescription inputEnt
+configEnts     : databaseInfo fieldDecStmt optQueryList auditTrailFmt 
mailFormatList globalChangeEnts indexDescription inputDescription
                ;
 
 databaseInfo   : DATABASEINFOTOK '{' databaseInfoList '}'
@@ -637,10 +639,31 @@ indexSep  : SEPARATORTOK QSTRING {
                }
                ;
 
-inputEnt       : INPUTTOK '{' inputFields '}' {
-                   setInputTemplate (databaseBeingDefined, $3);
-               }
+inputDescription: INPUTTOK '{' inputEnt '}'
                | INPUTTOK '{' parseError '}'
+
+inputEnt       : inputFields requiredFields {
+                   setInputTemplate (databaseBeingDefined, $1);
+               }
+                ;
+
+requiredFields  :/* empty */
+                | REQUIRETOK '{' requiredFieldsList '}' {
+                   setRequiredInputFields (databaseBeingDefined, requiredFlds);
+                }
+                | REQUIRETOK '{' parseError '}' {
+                    freeFieldList (requiredFlds);
+                    requiredFlds = NULL;
+                }
+               ;
+
+requiredFieldsList: FieldListMember {
+                   requiredFlds = $1;
+                }
+                | requiredFieldsList FieldListMember {
+                    $1->next = $2;
+                    $$ = $2;
+                }
                ;
 
 inputFields    : FIELDSTOK '{' inputFieldsList '}' {
Index: gnats/file-pr.c
===================================================================
RCS file: /cvsroot/gnats/gnats/gnats/file-pr.c,v
retrieving revision 1.47
diff -b -u -p -r1.47 file-pr.c
--- gnats/file-pr.c     12 Oct 2002 22:52:02 -0000      1.47
+++ gnats/file-pr.c     15 Oct 2002 23:09:41 -0000
@@ -35,6 +35,9 @@ static int run_atpr(PR *pr, AdmEntry *su
 static int getBugNumber        (const DatabaseInfo database, ErrorDesc *err);
 static char* derive_submitter  (PR *pr);
 
+static int missing_required_fields (const DatabaseInfo database, PR *pr,
+                                    ErrorDesc *err);
+
 
 /* Creates a PR file using the contents of PR.  If an error occurs, a
    negative value will be returned an an appropriate error code will
@@ -69,6 +72,11 @@ createNewPRFile (PR *pr, int flag_autocr
       return -1;
     }
 
+  if (missing_required_fields (database, pr, err) > 0)
+    {
+      return -1;
+    }
+
   /*  If we don't have a valid submitter ID, try to get it from the "From:"
       header.  If that doesn't work, use the default from the config file.  */
 
@@ -427,6 +435,28 @@ createNewPRFile (PR *pr, int flag_autocr
     }
 
   return bug_number;
+}
+
+static int
+missing_required_fields (const DatabaseInfo database, PR *pr, ErrorDesc *err)
+{
+  int cnt = 0;
+  FieldList fields = getRequiredInputFields(database);
+
+  while (fields != NULL)
+    {
+      const char *fldval = get_field_value (pr, NULL, fields->ent, NULL, NULL);
+      if (fldval == NULL || *fldval == '\0')
+       {
+          setError (err, CODE_INVALID_PR_CONTENTS,
+                    "Required field %s missing from new PR - cannot submit.",
+                    complexFieldIndexToString (fields->ent),
+                    field_value (pr, NUMBER (pr->database)));
+         cnt++;
+       }
+      fields = fields->next;
+    }
+  return cnt;
 }
 
 /* XXX ??? !!! FIXME Shouldn't be hardcoded.   */

reply via email to

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