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