Changes On Branch wolfgangTicketCmd
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch wolfgangTicketCmd Excluding Merge-Ins

This is equivalent to a diff from b525add4e0 to 568ead7b41

2010-10-07
19:17
Merge the "ticket" command into the trunk. check-in: 2f5d45eca3 user: drh tags: trunk
18:46
Merge in recent trunk changes. Closed-Leaf check-in: 568ead7b41 user: drh tags: wolfgangTicketCmd
18:40
Merge in changes from wolfgangFormat2CSS_2, with a few minor corrections. check-in: b525add4e0 user: drh tags: trunk
16:12
merged from trunk check-in: 09397a629a user: wolfgang tags: wolfgangTicketCmd
16:04
merged from trunk Closed-Leaf check-in: 2502567f70 user: wolfgang tags: wolfgangFormat2CSS_2
13:37
Update the built-in SQLite to the latest 3.7.3 beta. check-in: daf28132a9 user: drh tags: trunk

Changes to src/report.c.

   143    143   
   144    144   /*
   145    145   ** This is the SQLite authorizer callback used to make sure that the
   146    146   ** SQL statements entered by users do not try to do anything untoward.
   147    147   ** If anything suspicious is tried, set *(char**)pError to an error
   148    148   ** message obtained from malloc.
   149    149   */
   150         -static int report_query_authorizer(
          150  +int report_query_authorizer(
   151    151     void *pError,
   152    152     int code,
   153    153     const char *zArg1,
   154    154     const char *zArg2,
   155    155     const char *zArg3,
   156    156     const char *zArg4
   157    157   ){
................................................................................
   940    940     }else{
   941    941       sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr1);
   942    942       sqlite3_exec(g.db, zSql, output_tab_separated, &count, &zErr2);
   943    943       sqlite3_set_authorizer(g.db, 0, 0);
   944    944       cgi_set_content_type("text/plain");
   945    945     }
   946    946   }
          947  +
          948  +/*
          949  +** report number for full table ticket export
          950  +*/
          951  +static const char zFullTicketRptRn[] = "0";
          952  +
          953  +/*
          954  +** report title for full table ticket export
          955  +*/
          956  +static const char zFullTicketRptTitle[] = "full ticket export";
          957  +
          958  +/*
          959  +** show all reports, which can be used for ticket show.
          960  +** Output is written to stdout as tab delimited table
          961  +*/
          962  +void rpt_list_reports(void){
          963  +  Stmt q;
          964  +  char const aRptOutFrmt[] = "%s\t%s\n";
          965  +
          966  +  printf("Available reports:\n");
          967  +  printf(aRptOutFrmt,"report number","report title");
          968  +  printf(aRptOutFrmt,zFullTicketRptRn,zFullTicketRptTitle);
          969  +  db_prepare(&q,"SELECT rn,title FROM reportfmt ORDER BY rn");
          970  +  while( db_step(&q)==SQLITE_ROW ){
          971  +    const char *zRn = db_column_text(&q, 0);
          972  +    const char *zTitle = db_column_text(&q, 1);
          973  +
          974  +    printf(aRptOutFrmt,zRn,zTitle);
          975  +  }
          976  +  db_finalize(&q);
          977  +}
          978  +
          979  +/*
          980  +** user defined separator used by ticket show command
          981  +*/
          982  +static const char *zSep = 0;
          983  +
          984  +/*
          985  +** select the quoting algorithm for "ticket show"
          986  +*/
          987  +#if INTERFACE
          988  +typedef enum eTktShowEnc { tktNoTab=0, tktFossilize=1 } tTktShowEncoding;
          989  +#endif
          990  +static tTktShowEncoding tktEncode = tktNoTab;
          991  +
          992  +/*
          993  +** Output the text given in the argument.  Convert tabs and newlines into
          994  +** spaces.
          995  +*/
          996  +static void output_no_tabs_file(const char *z){
          997  +  switch( tktEncode ){
          998  +    case tktFossilize:
          999  +      { char *zFosZ;
         1000  +
         1001  +        if( z && *z ){
         1002  +          zFosZ = fossilize(z,-1);
         1003  +          printf("%s",zFosZ);
         1004  +          free(zFosZ);
         1005  +        }
         1006  +        break;
         1007  +      }
         1008  +    default:
         1009  +      while( z && z[0] ){
         1010  +        int i, j;
         1011  +        for(i=0; z[i] && (!isspace(z[i]) || z[i]==' '); i++){}
         1012  +        if( i>0 ){
         1013  +          printf("%.*s", i, z);
         1014  +        }
         1015  +        for(j=i; isspace(z[j]); j++){}
         1016  +        if( j>i ){
         1017  +          printf("%*s", j-i, "");
         1018  +        }
         1019  +        z += j;
         1020  +      }
         1021  +      break; 
         1022  +  }
         1023  +}
         1024  +
         1025  +/*
         1026  +** Output a row as a tab-separated line of text.
         1027  +*/
         1028  +int output_separated_file(
         1029  +  void *pUser,     /* Pointer to row-count integer */
         1030  +  int nArg,        /* Number of columns in this result row */
         1031  +  char **azArg,    /* Text of data in all columns */
         1032  +  char **azName    /* Names of the columns */
         1033  +){
         1034  +  int *pCount = (int*)pUser;
         1035  +  int i;
         1036  +
         1037  +  if( *pCount==0 ){
         1038  +    for(i=0; i<nArg; i++){
         1039  +      output_no_tabs_file(azName[i]);
         1040  +      printf("%s", i<nArg-1 ? (zSep?zSep:"\t") : "\n");
         1041  +    }
         1042  +  }
         1043  +  ++*pCount;
         1044  +  for(i=0; i<nArg; i++){
         1045  +    output_no_tabs_file(azArg[i]);
         1046  +    printf("%s", i<nArg-1 ? (zSep?zSep:"\t") : "\n");
         1047  +  }
         1048  +  return 0;
         1049  +}
         1050  +
         1051  +/*
         1052  +** Generate a report.  The rn query parameter is the report number.
         1053  +** The output is written to stdout as flat file. The zFilter paramater
         1054  +** is a full WHERE-condition.
         1055  +*/
         1056  +void rptshow( 
         1057  +    const char *zRep,
         1058  +    const char *zSepIn,
         1059  +    const char *zFilter,
         1060  +    tTktShowEncoding enc
         1061  +){
         1062  +  Stmt q;
         1063  +  char *zSql;
         1064  +  const char *zTitle;
         1065  +  const char *zOwner;
         1066  +  const char *zClrKey;
         1067  +  char *zErr1 = 0;
         1068  +  char *zErr2 = 0;
         1069  +  int count = 0;
         1070  +  int rn;
         1071  +
         1072  +  if (!zRep || !strcmp(zRep,zFullTicketRptRn) || !strcmp(zRep,zFullTicketRptTitle) ){
         1073  +    zTitle = zFullTicketRptTitle;
         1074  +    zSql = "SELECT * FROM ticket";
         1075  +    zOwner = g.zLogin;
         1076  +    zClrKey = "";
         1077  +  }else{
         1078  +    rn = atoi(zRep);
         1079  +    if( rn ){
         1080  +      db_prepare(&q,
         1081  +       "SELECT title, sqlcode, owner, cols FROM reportfmt WHERE rn=%d", rn);
         1082  +    }else{
         1083  +      db_prepare(&q,
         1084  +       "SELECT title, sqlcode, owner, cols FROM reportfmt WHERE title='%s'", zRep);
         1085  +    }
         1086  +    if( db_step(&q)!=SQLITE_ROW ){
         1087  +      db_finalize(&q);
         1088  +      rpt_list_reports();
         1089  +      fossil_fatal("unkown report format(%s)!",zRep);
         1090  +    }
         1091  +    zTitle = db_column_malloc(&q, 0);
         1092  +    zSql = db_column_malloc(&q, 1);
         1093  +    zOwner = db_column_malloc(&q, 2);
         1094  +    zClrKey = db_column_malloc(&q, 3);
         1095  +    db_finalize(&q);
         1096  +  }
         1097  +  if( zFilter ){
         1098  +    zSql = mprintf("SELECT * FROM (%s) WHERE %s",zSql,zFilter);
         1099  +  }
         1100  +  count = 0;
         1101  +  tktEncode = enc;
         1102  +  zSep = zSepIn;
         1103  +  sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr1);
         1104  +  sqlite3_exec(g.db, zSql, output_separated_file, &count, &zErr2);
         1105  +  sqlite3_set_authorizer(g.db, 0, 0);
         1106  +  if( zFilter ){
         1107  +    free(zSql);
         1108  +  }
         1109  +}
         1110  +

Changes to src/tag.c.

   353    353   ** probably complain that no such revision was found. However
   354    354   **
   355    355   **   fossil update tag:decaf
   356    356   **
   357    357   ** will assume that "decaf" is a tag/branch name.
   358    358   **
   359    359   ** only allow --date-override and --user-override in 
   360         -**   %fossil tag add --date-override 'YYYY-MMM-DD HH:MM:SS' \
          360  +**   %fossil tag add --date-override 'YYYY-MMM-DD HH:MM:SS' \\
   361    361   **                   --user-override user 
   362    362   ** in order to import history from other scm systems
   363    363   */
   364    364   void tag_cmd(void){
   365    365     int n;
   366    366     int fRaw = find_option("raw","",0)!=0;
   367    367     int fPropagate = find_option("propagate","",0)!=0;

Changes to src/tkt.c.

   828    828       }else{
   829    829         @ <li>Change %h(z) to "%h(blob_str(&val))"</li>
   830    830       }
   831    831       blob_reset(&val);
   832    832     }
   833    833     @ </ol>
   834    834   }
          835  +
          836  +/*
          837  +** COMMAND: ticket
          838  +** Usage: %fossil ticket SUBCOMMAND ...
          839  +**
          840  +** Run various subcommands to control tickets
          841  +**
          842  +**     %fossil ticket show (REPORTTITLE|REPORTNR) ?TICKETFILTER? ?options?
          843  +**
          844  +**         options can be:
          845  +**           ?-l|--limit LIMITCHAR?
          846  +**           ?-q|--quote?
          847  +**
          848  +**         Run the ticket report, identified by the report format title
          849  +**         used in the gui. The data is written as flat file on stdout,
          850  +**         using "," as separator. The seperator "," can be changed using
          851  +**         the -l or --limit option.
          852  +**         If TICKETFILTER is given on the commandline, the query is
          853  +**         limited with a new WHERE-condition.
          854  +**           example:  Report lists a column # with the uuid
          855  +**                     TICKETFILTER may be [#]='uuuuuuuuu'
          856  +**           example:  Report only lists rows with status not open
          857  +**                     TICKETFILTER: status != 'open'
          858  +**         If the option -q|--quote is used, the tickets are encoded by
          859  +**         quoting special chars(space -> \\s, tab -> \\t, newline -> \\n,
          860  +**         cr -> \\r, formfeed -> \\f, vtab -> \\v, nul -> \\0, \\ -> \\\\).
          861  +**         Otherwise, the simplified encoding as on the show report raw
          862  +**         page in the gui is used.
          863  +**
          864  +**         Instead of the report title its possible to use the report
          865  +**         number. Using the special report number 0 list all columns,
          866  +**         defined in the ticket table.
          867  +**
          868  +**     %fossil ticket list fields
          869  +**
          870  +**         list all fields, defined for ticket in the fossil repository
          871  +**
          872  +**     %fossil ticket list reports
          873  +**
          874  +**         list all ticket reports, defined in the fossil repository
          875  +**
          876  +**     %fossil ticket set TICKETUUID FIELD VALUE ?FIELD VALUE .. ? ?-q|--quote?
          877  +**     %fossil ticket change TICKETUUID FIELD VALUE ?FIELD VALUE .. ? ?-q|--quote?
          878  +**
          879  +**         change ticket identified by TICKETUUID and set the value of
          880  +**         field FIELD to VALUE. Valid field descriptions are:
          881  +**            status, type, severity, priority, resolution,
          882  +**            foundin, private_contact, resolution, title or comment
          883  +**         Field names given above are the ones, defined in a standard
          884  +**         fossil environment. If you have added, deleted columns, you
          885  +**         change the all your configured columns.
          886  +**         You can use more than one field/value pair on the commandline.
          887  +**         Using -q|--quote  enables the special character decoding as
          888  +**         in "ticket show". So it's possible, to set multiline text or
          889  +**         text with special characters.
          890  +**
          891  +**     %fossil ticket add FIELD VALUE ?FIELD VALUE .. ? ?-q|--quote?
          892  +**
          893  +**         like set, but create a new ticket with the given values.
          894  +**
          895  +** The values in set|add are not validated against the definitions
          896  +** given in "Ticket Common Script".
          897  +*/
          898  +void ticket_cmd(void){
          899  +  int n;
          900  +
          901  +  /* do some ints, we want to be inside a checkout */
          902  +  db_must_be_within_tree();
          903  +  db_find_and_open_repository(1);
          904  +  user_select();
          905  +  /*
          906  +  ** Check that the user exists.
          907  +  */
          908  +  if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){
          909  +    fossil_fatal("no such user: %s", g.zLogin);
          910  +  }
          911  +
          912  +  if( g.argc<3 ){
          913  +    usage("add|fieldlist|set|show");
          914  +  }else{
          915  +    n = strlen(g.argv[2]);
          916  +    if( n==1 && g.argv[2][0]=='s' ){
          917  +      /* set/show cannot be distinguished, so show the usage */
          918  +      usage("add|fieldlist|set|show");
          919  +    }else if( strncmp(g.argv[2],"list",n)==0 ){
          920  +      if( g.argc==3 ){
          921  +        usage("list fields|reports");
          922  +      }else{
          923  +        n = strlen(g.argv[3]);
          924  +        if( !strncmp(g.argv[3],"fields",n) ){
          925  +          /* simply show all field names */
          926  +          int i;
          927  +
          928  +          /* read all available ticket fields */
          929  +          getAllTicketFields();
          930  +          for(i=0; i<nField; i++){
          931  +            printf("%s\n",azField[i]);
          932  +          }
          933  +        }else if( !strncmp(g.argv[3],"reports",n) ){
          934  +          rpt_list_reports();
          935  +        }else{
          936  +          fossil_fatal("unknown ticket list option '%s'!",g.argv[3]);
          937  +        }
          938  +      }
          939  +    }else{
          940  +      /* add a new ticket or set fields on existing tickets */
          941  +      tTktShowEncoding tktEncoding;
          942  +
          943  +      tktEncoding = find_option("quote","q",0) ? tktFossilize : tktNoTab;
          944  +      
          945  +      if( strncmp(g.argv[2],"show",n)==0 ){
          946  +        if( g.argc==3 ){
          947  +          usage("show REPORTNR");
          948  +        }else{
          949  +          const char *zRep = 0;
          950  +          const char *zSep = 0;
          951  +          const char *zFilterUuid = 0;
          952  +
          953  +          zSep = find_option("limit","l",1);
          954  +          zRep = g.argv[3];
          955  +          if( !strcmp(zRep,"0") ){
          956  +            zRep = 0;
          957  +          }
          958  +          if( g.argc>4 ){
          959  +            zFilterUuid = g.argv[4];
          960  +          }
          961  +
          962  +          rptshow( zRep, zSep, zFilterUuid, tktEncoding );
          963  +
          964  +        }
          965  +      }else{
          966  +        /* add a new ticket or update an existing ticket */
          967  +        enum { set,add,err } eCmd = err;
          968  +        int i;
          969  +        int rid;
          970  +        const char *zTktUuid;
          971  +        Blob tktchng, cksum;
          972  +
          973  +        /* get command type (set/add) and get uuid, if needed for set */
          974  +        if( strncmp(g.argv[2],"set",n)==0 || strncmp(g.argv[2],"change",n)==0 ){
          975  +          eCmd = set;
          976  +          if( g.argc==3 ){
          977  +            usage("set TICKETUUID");
          978  +          }
          979  +          zTktUuid = db_text(0, 
          980  +            "SELECT tkt_uuid FROM ticket WHERE tkt_uuid GLOB '%s*'", g.argv[3]
          981  +          );
          982  +          if( !zTktUuid ){
          983  +            fossil_fatal("unknown ticket: '%s'!",g.argv[3]);
          984  +          }
          985  +          i=4;
          986  +        }else if( strncmp(g.argv[2],"add",n)==0 ){
          987  +          eCmd = add;
          988  +          i = 3;
          989  +          zTktUuid = db_text(0, "SELECT lower(hex(randomblob(20)))");
          990  +        }
          991  +        /* none of set/add, so show the usage! */
          992  +        if( eCmd==err ){
          993  +          usage("add|fieldlist|set|show");
          994  +        }
          995  +        
          996  +        /* read all given ticket field/value pairs from command line */
          997  +        if( i==g.argc ){
          998  +          fossil_fatal("empty %s command aborted!",g.argv[2]);
          999  +        }
         1000  +        getAllTicketFields();
         1001  +        /* read commandline and assign fields in the azValue array */
         1002  +        while( i<g.argc ){
         1003  +          char *zFName;
         1004  +          char *zFValue;
         1005  +          int j;
         1006  +
         1007  +          zFName = g.argv[i++];
         1008  +          if( i==g.argc ){
         1009  +            fossil_fatal("missing value for '%s'!",zFName);
         1010  +          }
         1011  +          zFValue = g.argv[i++];
         1012  +          j = fieldId(zFName);
         1013  +          if( tktEncoding == tktFossilize ){
         1014  +            zFValue=mprintf("%s",zFValue);
         1015  +            defossilize(zFValue);
         1016  +          }
         1017  +          if( j == -1 ){
         1018  +            fossil_fatal("unknown field name '%s'!",zFName);
         1019  +          }else{
         1020  +            azValue[j] = zFValue;
         1021  +          }
         1022  +        }
         1023  +
         1024  +        /* now add the needed artifacts to the repository */
         1025  +        blob_zero(&tktchng);
         1026  +        { /* add the time to the ticket manifest */
         1027  +          char *zDate;
         1028  +
         1029  +          zDate = db_text(0, "SELECT datetime('now')");
         1030  +          zDate[10] = 'T';
         1031  +          blob_appendf(&tktchng, "D %s\n", zDate);
         1032  +          free(zDate);
         1033  +        }
         1034  +        /* append defined elements */
         1035  +        for(i=0; i<nField; i++){
         1036  +          char *zValue;
         1037  +
         1038  +          zValue = azValue[i];
         1039  +          if( azValue[i] && azValue[i][0] ){
         1040  +            if( strncmp(azField[i], "private_", 8)==0 ){
         1041  +              zValue = db_conceal(zValue, strlen(zValue));
         1042  +              blob_appendf(&tktchng, "J %s %s\n", azField[i], zValue);
         1043  +            }else{
         1044  +              blob_appendf(&tktchng, "J %s %#F\n", azField[i], strlen(zValue), zValue);
         1045  +            }
         1046  +            if( tktEncoding == tktFossilize ){
         1047  +              free(azValue[i]);
         1048  +            }
         1049  +          }
         1050  +        }
         1051  +        blob_appendf(&tktchng, "K %s\n", zTktUuid);
         1052  +        blob_appendf(&tktchng, "U %F\n", g.zLogin);
         1053  +        md5sum_blob(&tktchng, &cksum);
         1054  +        blob_appendf(&tktchng, "Z %b\n", &cksum);
         1055  +        rid = content_put(&tktchng, 0, 0);
         1056  +        if( rid==0 ){
         1057  +          fossil_panic("trouble committing ticket: %s", g.zErrMsg);
         1058  +        }
         1059  +        manifest_crosslink_begin();
         1060  +        manifest_crosslink(rid, &tktchng);
         1061  +        manifest_crosslink_end();
         1062  +	printf("ticket %s succeeded for UID %s\n",
         1063  +	       (eCmd==set?"set":"add"),zTktUuid);
         1064  +      }
         1065  +    }
         1066  +  }
         1067  +}

Changes to win/Makefile.dmc.

   222    222   	+translate$E $** > $@
   223    223   
   224    224   $(OBJDIR)\doc$O : doc_.c doc.h
   225    225   	$(TCC) -o$@ -c doc_.c
   226    226   
   227    227   doc_.c : $(SRCDIR)\doc.c
   228    228   	+translate$E $** > $@
          229  +
          230  +$(OBJDIR)\event$O : event_.c event.h
          231  +	$(TCC) -o$@ -c event_.c
          232  +
          233  +event_.c : $(SRCDIR)\event.c
          234  +	+translate$E $** > $@
   229    235   
   230    236   $(OBJDIR)\encode$O : encode_.c encode.h
   231    237   	$(TCC) -o$@ -c encode_.c
   232    238   
   233    239   encode_.c : $(SRCDIR)\encode.c
   234    240   	+translate$E $** > $@
   235    241