Fossil

Check-in [1e9c0e287e]
Login

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

Overview
Comment:Test commands for importing and exporting ticket configurations.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 1e9c0e287e9609f3ee097136ff751d4701278cf5
User & Date: drh 2007-10-03 12:20:00.000
Context
2007-10-03
12:28
Add the tkt.c source file as an empty template. check-in: a3e4a5d27d user: drh tags: trunk
12:20
Test commands for importing and exporting ticket configurations. check-in: 1e9c0e287e user: drh tags: trunk
02:33
Begin adding setup screens for ticket configuration. check-in: 0edee97370 user: drh tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/db.c.
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
  }
}

/*
** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the
** repository and local databases.
*/
const char *db_get(const char *zName, const char *zDefault){
  const char *z = 0;
  if( g.repositoryOpen ){
    z = db_text(0, "SELECT value FROM config WHERE name=%Q", zName);
  }
  if( z==0 ){
    z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName);
  }
  if( z==0 ){







|
|







830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
  }
}

/*
** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the
** repository and local databases.
*/
char *db_get(const char *zName, char *zDefault){
  char *z = 0;
  if( g.repositoryOpen ){
    z = db_text(0, "SELECT value FROM config WHERE name=%Q", zName);
  }
  if( z==0 ){
    z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName);
  }
  if( z==0 ){
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
  db_multi_exec("REPLACE INTO %sconfig(name,value) VALUES(%Q,%d)",
                globalFlag ? "global_" : "", zName, value);
  if( globalFlag && g.repositoryOpen ){
    db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
  }
  db_end_transaction(0);
}
char *db_lget(const char *zName, const char *zDefault){
  return db_text((char*)zDefault, 
                 "SELECT value FROM vvar WHERE name=%Q", zName);
}
void db_lset(const char *zName, const char *zValue){
  db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%Q)", zName, zValue);
}
int db_lget_int(const char *zName, int dflt){







|







883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
  db_multi_exec("REPLACE INTO %sconfig(name,value) VALUES(%Q,%d)",
                globalFlag ? "global_" : "", zName, value);
  if( globalFlag && g.repositoryOpen ){
    db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
  }
  db_end_transaction(0);
}
char *db_lget(const char *zName, char *zDefault){
  return db_text((char*)zDefault, 
                 "SELECT value FROM vvar WHERE name=%Q", zName);
}
void db_lset(const char *zName, const char *zValue){
  db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%Q)", zName, zValue);
}
int db_lget_int(const char *zName, int dflt){
Changes to src/main.c.
594
595
596
597
598
599
600









601
602
603
604
605
606
607
    db_open_repository(g.argv[2]);
  }else{
    db_must_be_within_tree();
  }
  cgi_handle_http_request();
  process_one_web_page();
}










/*
** COMMAND: server
**
** Usage: %fossil server ?-P|--port TCPPORT? ?REPOSITORY?
**
** Open a socket and begin listening and responding to HTTP requests on







>
>
>
>
>
>
>
>
>







594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
    db_open_repository(g.argv[2]);
  }else{
    db_must_be_within_tree();
  }
  cgi_handle_http_request();
  process_one_web_page();
}

/*
** COMMAND: test-http
** Works like the http command but gives setup permission to all users.
*/
void cmd_test_http(void){
  login_set_capabilities("s");
  cmd_http();
}

/*
** COMMAND: server
**
** Usage: %fossil server ?-P|--port TCPPORT? ?REPOSITORY?
**
** Open a socket and begin listening and responding to HTTP requests on
Changes to src/setup.c.
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
** Generate an entry box for an attribute.
*/
static void entry_attribute(
  const char *zLabel,   /* The text label on the entry box */
  int width,            /* Width of the entry box */
  const char *zVar,     /* The corresponding row in the VAR table */
  const char *zQParm,   /* The query parameter */
  const char *zDflt     /* Default value if VAR table entry does not exist */
){
  const char *zVal = db_get(zVar, zDflt);
  const char *zQ = P(zQParm);
  if( zQ && strcmp(zQ,zVal)!=0 ){
    db_set(zVar, zQ, 0);
    zVal = zQ;
  }
  @ <input type="text" name="%s(zQParm)" value="%h(zVal)" size="%d(width)">
  @ %s(zLabel)
}

/*
** Generate a text box for an attribute.
*/
static void textarea_attribute(
  const char *zLabel,   /* The text label on the textarea */
  int rows,             /* Rows in the textarea */
  int cols,             /* Columns in the textarea */
  const char *zVar,     /* The corresponding row in the VAR table */
  const char *zQParm,   /* The query parameter */
  const char *zDflt     /* Default value if VAR table entry does not exist */
){
  const char *zVal = db_get(zVar, zDflt);
  const char *zQ = P(zQParm);
  if( zQ && strcmp(zQ,zVal)!=0 ){
    db_set(zVar, zQ, 0);
    zVal = zQ;
  }







|




















|







448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
** Generate an entry box for an attribute.
*/
static void entry_attribute(
  const char *zLabel,   /* The text label on the entry box */
  int width,            /* Width of the entry box */
  const char *zVar,     /* The corresponding row in the VAR table */
  const char *zQParm,   /* The query parameter */
  char *zDflt     /* Default value if VAR table entry does not exist */
){
  const char *zVal = db_get(zVar, zDflt);
  const char *zQ = P(zQParm);
  if( zQ && strcmp(zQ,zVal)!=0 ){
    db_set(zVar, zQ, 0);
    zVal = zQ;
  }
  @ <input type="text" name="%s(zQParm)" value="%h(zVal)" size="%d(width)">
  @ %s(zLabel)
}

/*
** Generate a text box for an attribute.
*/
static void textarea_attribute(
  const char *zLabel,   /* The text label on the textarea */
  int rows,             /* Rows in the textarea */
  int cols,             /* Columns in the textarea */
  const char *zVar,     /* The corresponding row in the VAR table */
  const char *zQParm,   /* The query parameter */
  char *zDflt           /* Default value if VAR table entry does not exist */
){
  const char *zVal = db_get(zVar, zDflt);
  const char *zQ = P(zQParm);
  if( zQ && strcmp(zQ,zVal)!=0 ){
    db_set(zVar, zQ, 0);
    zVal = zQ;
  }
Changes to src/tktconf.c.
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  ** ticket configuration.  tbldef will hold the ticket table
  ** definition.  sql will hold text to initialize and define
  ** the tktfield table and to insert template text into the
  ** config table
  */
  blob_appendf(&tbldef, 
     "DROP TABLE IF EXISTS ticket;\n"
     "CREATE TABLE ticket(\n"
     "  tktid INTEGER PRIMARY KEY,\n"
     "  tktuuid TEXT UNIQUE,\n"
     "  starttime DATETIME,\n"
     "  lastmod DATETIME"
  );
  blob_appendf(&sql,
     "DROP TABLE IF EXISTS tktfield;\n"
     "CREATE TABLE tktfield(\n"
     "  fidx INTEGER PRIMARY KEY,\n"
     "  name TEXT UNIQUE,\n"
     "  type TEXT,\n"
     "  width INTEGER,\n"
     "  arg\n"
     ");\n"
  );







|







|







150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  ** ticket configuration.  tbldef will hold the ticket table
  ** definition.  sql will hold text to initialize and define
  ** the tktfield table and to insert template text into the
  ** config table
  */
  blob_appendf(&tbldef, 
     "DROP TABLE IF EXISTS ticket;\n"
     "CREATE TABLE repository.ticket(\n"
     "  tktid INTEGER PRIMARY KEY,\n"
     "  tktuuid TEXT UNIQUE,\n"
     "  starttime DATETIME,\n"
     "  lastmod DATETIME"
  );
  blob_appendf(&sql,
     "DROP TABLE IF EXISTS tktfield;\n"
     "CREATE TABLE repository.tktfield(\n"
     "  fidx INTEGER PRIMARY KEY,\n"
     "  name TEXT UNIQUE,\n"
     "  type TEXT,\n"
     "  width INTEGER,\n"
     "  arg\n"
     ");\n"
  );
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
    /*
    **  description <delimiter>
    **  <text>
    */      
    if( blob_eq(&token, "description")
     && blob_token(&line, &arg)
    ){
      int idx;
      Blob content;
      int start;
      int end;

      start = end = blob_tell(pConfig);
      while( blob_line(pConfig, &line) ){
         blob_token(&line, &token);







<







306
307
308
309
310
311
312

313
314
315
316
317
318
319
    /*
    **  description <delimiter>
    **  <text>
    */      
    if( blob_eq(&token, "description")
     && blob_token(&line, &arg)
    ){

      Blob content;
      int start;
      int end;

      start = end = blob_tell(pConfig);
      while( blob_line(pConfig, &line) ){
         blob_token(&line, &token);
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379


















380
381
382
383
384
385
386
  blob_reset(&err);
  return rc;
}

/*
** COMMAND: test-tktconfig-parse
*/
void test_tktconfig_cmd(void){
  Blob config, err;
  if( g.argc!=3 ){
    usage("FILENAME");
  }
  blob_read_from_file(&config, g.argv[2]);
  blob_zero(&err);
  ticket_config_parse(&config, 1, &err);


















  if( blob_size(&err) ){
    blob_write_to_file(&err, "-");
  }
}

/*
** Load the default ticket configuration.







|







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  blob_reset(&err);
  return rc;
}

/*
** COMMAND: test-tktconfig-parse
*/
void test_tktconfig_parse_cmd(void){
  Blob config, err;
  if( g.argc!=3 ){
    usage("FILENAME");
  }
  blob_read_from_file(&config, g.argv[2]);
  blob_zero(&err);
  ticket_config_parse(&config, 1, &err);
  if( blob_size(&err) ){
    blob_write_to_file(&err, "-");
  }
}
/*
** COMMAND: test-tktconfig-import
*/
void test_tktconfig_import_cmd(void){
  Blob config, err;
  db_must_be_within_tree();
  if( g.argc!=3 ){
    usage("FILENAME");
  }
  blob_read_from_file(&config, g.argv[2]);
  blob_zero(&err);
  db_begin_transaction();
  ticket_config_parse(&config, 0, &err);
  db_end_transaction(0);
  if( blob_size(&err) ){
    blob_write_to_file(&err, "-");
  }
}

/*
** Load the default ticket configuration.
559
560
561
562
563
564
565






















































































  blob_zero(&errmsg);
  ticket_config_parse(&config, 0, &errmsg);
  if( blob_size(&errmsg) ){
    fossil_fatal("%b", &errmsg);
  }
  db_end_transaction(0);
}





























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
  blob_zero(&errmsg);
  ticket_config_parse(&config, 0, &errmsg);
  if( blob_size(&errmsg) ){
    fossil_fatal("%b", &errmsg);
  }
  db_end_transaction(0);
}

/*
** Return the length of a string without its trailing whitespace.
*/
static int non_whitespace_length(const char *z){
  int n = strlen(z);
  while( n>0 && isspace(z[n-1]) ){ n--; }
  return n;
}

/*
** Fill the given Blob with text that describes the current
** ticket configuration.  This is the inverse of ticket_config_parse()
*/
void ticket_config_render(Blob *pOut){
  char *zDelim;
  char *zContent;
  Stmt q;
  int n;

  blob_appendf(pOut, "ticket-configuration\n");
  zDelim = db_text(0, "SELECT '--end-of-text--' || hex(random(20))");
  blob_appendf(pOut, "###################################################\n");
  db_prepare(&q, "SELECT name, type, width, arg FROM tktfield");
  while( db_step(&q)==SQLITE_ROW ){
    const char *zName = db_column_text(&q, 0);
    const char *zType = db_column_text(&q, 1);
    int width = db_column_int(&q, 2);
    const char *zArg = db_column_text(&q, 3);
    blob_appendf(pOut, "field %s %s %d %s\n", zName, zType, width, zArg);
  }
  db_finalize(&q);
  blob_appendf(pOut, "###################################################\n");
  blob_appendf(pOut, "template new %s\n", zDelim);
  zContent = db_get("tkt-new-template", 0);
  if( zContent ){
    n = non_whitespace_length(zContent);
    blob_appendf(pOut, "%.*s\n", n, zContent);
    free(zContent);
  }
  blob_appendf(pOut, "%s\n", zDelim);
  blob_appendf(pOut, "###################################################\n");
  blob_appendf(pOut, "template edit %s\n", zDelim);
  zContent = db_get("tkt-edit-template", 0);
  if( zContent ){
    n = non_whitespace_length(zContent);
    blob_appendf(pOut, "%.*s\n", n, zContent);
    free(zContent);
  }
  blob_appendf(pOut, "%s\n", zDelim);
  blob_appendf(pOut, "###################################################\n");
  blob_appendf(pOut, "template view %s\n", zDelim);
  zContent = db_get("tkt-view-template", 0);
  if( zContent ){
    n = non_whitespace_length(zContent);
    blob_appendf(pOut, "%.*s\n", n, zContent);
    free(zContent);
  }
  blob_appendf(pOut, "%s\n", zDelim);
  blob_appendf(pOut, "###################################################\n");
  blob_appendf(pOut, "description %s\n", zDelim);
  zContent = db_get("tkt-desc", 0);
  if( zContent ){
    n = non_whitespace_length(zContent);
    blob_appendf(pOut, "%.*s\n", n, zContent);
    free(zContent);
  }
  blob_appendf(pOut, "%s\n", zDelim);
}

/*
** COMMAND: test-tktconfig-export
** Write the current ticket configuration out to a file.
*/
void tktconfig_render_cmd(void){
  Blob config;

  db_must_be_within_tree();
  if( g.argc!=3 ){
    usage("FILENAME");
  }
  blob_zero(&config);
  ticket_config_render(&config);
  blob_write_to_file(&config, g.argv[2]);
  blob_reset(&config);
}
Changes to src/tktsetup.c.
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
















59
60
61
62
63
64

65
66
67
68
69
70




71
72
73
74







75
76



























77
  @ <dl id="setup">
  setup_menu_entry("Load", "tktsetup_load",
    "Load a predefined ticket configuration");
  setup_menu_entry("Save", "tktsetup_save",
    "Save the current ticket configuration as an artifact");
  setup_menu_entry("Fields", "tktsetup_fields",
    "View or edit the fields allowed in tickets");
  setup_menu_entry("New", "tktsetup_newtemplate",
    "View or edit the template page used for creating a new ticket");
  setup_menu_entry("View", "tktsetup_viewtemplate",
    "View or edit the template page used for viewing a ticket");
  setup_menu_entry("Edit", "tktsetup_edittemplate",
    "View or edit the template page used for editing a ticket");
  @ </dl>

  style_footer();
}

















/*
** WEBPAGE: /tktsetup_load
*/
void tktsetup_load_page(void){
  int loadrid;

  int loaddflt;

  login_check_credentials();
  if( !g.okSetup ){
    login_needed();
  }




  loadrid = atoi(PD("id","0"));
  loaddflt = P("dflt")!=0;
  if( loaddflt ){
    ticket_load_default_config();







    cgi_redirect("tktsetup");
  }



























}







|

|

|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






>
|





>
>
>
>

|
|
|
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  @ <dl id="setup">
  setup_menu_entry("Load", "tktsetup_load",
    "Load a predefined ticket configuration");
  setup_menu_entry("Save", "tktsetup_save",
    "Save the current ticket configuration as an artifact");
  setup_menu_entry("Fields", "tktsetup_fields",
    "View or edit the fields allowed in tickets");
  setup_menu_entry("New", "tktsetup_template?type=new",
    "View or edit the template page used for creating a new ticket");
  setup_menu_entry("View", "tktsetup_template?type=view",
    "View or edit the template page used for viewing a ticket");
  setup_menu_entry("Edit", "tktsetup_template?type=edit",
    "View or edit the template page used for editing a ticket");
  @ </dl>

  style_footer();
}

/*
** Load the ticket configuration in the artifact with rid.
** If an error occurs, return 1 and leave an error message.
*/
static int load_config(int rid, Blob *pErr){
  Blob content;
  int rc;
  if( content_get(rid, &content)==0 ){
    blob_appendf(pErr, "no such artifact: %d", rid);
    return 1;
  }
  rc = ticket_config_parse(&content, 0, pErr);
  blob_reset(&content);
  return rc;
}

/*
** WEBPAGE: /tktsetup_load
*/
void tktsetup_load_page(void){
  int loadrid;
  Blob err;
  Stmt s;

  login_check_credentials();
  if( !g.okSetup ){
    login_needed();
  }
  if( P("dflt")!=0 ){
    ticket_load_default_config();
    cgi_redirect("tktsetup");
  }
  loadrid = atoi(PD("id","0"));
  blob_zero(&err);
  if( loadrid ){
    if( load_config(loadrid, &err) ){
      style_header("Configuration Error");
      @ <p>The following error occurred while trying to load
      @ the configuration in artifact #%d(loadrid):</p>
      @ <blockquote><b>%h(blob_str(&err))</b></blockquote>
      @ <p>Return to the <a href="tktsetup">ticket setup menu</a>.</p>
      style_footer();
    }else{
      cgi_redirect("tktsetup");
    }
    return;
  }
  style_header("Load Configuration");
  @ <p>Select one of the following ticket configurations to load:</p>
  @ <ul>
  @ <li><p>[<a href="tktsetup_load?dflt=1">default</a>]
  @        The default built-in ticket configuration.</p></li>
  db_prepare(&s,
    "SELECT blob.uuid, tagxref.rid, datetime(tagxref.mtime, 'localtime')"
    "  FROM tagxref, blob"
    " WHERE tagxref.tagid=(SELECT tagid FROM tag "
                           "WHERE tagname='ticket_configuration')"
    "   AND blob.rid=tagxref.rid"
    " ORDER BY tagxref.mtime DESC"
  );
  while( db_step(&s)==SQLITE_ROW ){
    const char *zUuid = db_column_text(&s, 0);
    int rid = db_column_int(&s, 1);
    const char *zWhen = db_column_text(&s, 2);
    @ <li><p>[<a href="tktsetup_load?id=%d(rid)">%s(zUuid)</a>].
    @        Configuration created on %s(zWhen).</p></li>
  }
  db_finalize(&s);
  @ <li><p>[<a href="tktsetup">Cancel</a>].  Return to the main
  @        ticket configuration setup menu.</p></li>
  @ </ul>
  style_footer();
}