Fossil

Check-in [ab0a0d76]
Login

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

Overview
Comment:Start a new branch that strives to contain only code for which we hold clear title.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | clear-title
Files: files | file ages | folders
SHA1:ab0a0d7640af00faa6da3a44ce807c5d28d86b5a
User & Date: drh 2010-01-19 18:11:57
Context
2010-01-20
15:55
Pull in the latest fixes from the trunk. check-in: a3161f5f user: drh tags: clear-title
2010-01-19
18:11
Start a new branch that strives to contain only code for which we hold clear title. check-in: ab0a0d76 user: drh tags: clear-title
17:34
Cleanup of the code used to resolve tag names in contexts where an artifact ID can be entered. check-in: bf56b2dd user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/add.c.

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
** COMMAND: rename
**
** Usage: %fossil mv|rename OLDNAME NEWNAME
**    or: %fossil mv|rename OLDNAME... DIR
**
** Move or rename one or more files within the tree
**
** This command does not rename the files on disk.  All this command does is
** record the fact that filenames have changed so that appropriate notations
** can be made at the next commit/checkin.
*/
void mv_cmd(void){
  int i;
  int vid;
  char *zDest;
  Blob dest;







|
|







227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
** COMMAND: rename
**
** Usage: %fossil mv|rename OLDNAME NEWNAME
**    or: %fossil mv|rename OLDNAME... DIR
**
** Move or rename one or more files within the tree
**
** This command does not rename the files on disk.  This command merely
** records the fact that filenames have changed so that appropriate notations
** can be made at the next commit/checkin.
*/
void mv_cmd(void){
  int i;
  int vid;
  char *zDest;
  Blob dest;

Changes to src/allrepo.c.

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
..
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
** Usage: %fossil all (list|ls|pull|push|rebuild|sync)
**
** The ~/.fossil file records the location of all repositories for a
** user.  This command performs certain operations on all repositories
** that can be useful before or after a period of disconnection operation.
** Available operations are:
**
**    list       Display the location of all repositories
**
**    ls         An alias for "list"
**
**    pull       Run a "pull" operation on all repositories
**
**    push       Run a "push" on all repositories
**
**    rebuild    Rebuild on all repositories
**
................................................................................
  
  if( g.argc<3 ){
    usage("list|ls|pull|push|rebuild|sync");
  }
  n = strlen(g.argv[2]);
  db_open_config(1);
  zCmd = g.argv[2];
  if( strncmp(zCmd, "list", n)==0 ){
    zCmd = "list";
  }else if( strncmp(zCmd, "ls", n)==0 ){ /* alias for "list" above */
    zCmd = "list";
  }else if( strncmp(zCmd, "push", n)==0 ){
    zCmd = "push -autourl -R";
  }else if( strncmp(zCmd, "pull", n)==0 ){
    zCmd = "pull -autourl -R";
  }else if( strncmp(zCmd, "rebuild", n)==0 ){
    zCmd = "rebuild";







|
<
<







 







|
<
<







60
61
62
63
64
65
66
67


68
69
70
71
72
73
74
..
89
90
91
92
93
94
95
96


97
98
99
100
101
102
103
** Usage: %fossil all (list|ls|pull|push|rebuild|sync)
**
** The ~/.fossil file records the location of all repositories for a
** user.  This command performs certain operations on all repositories
** that can be useful before or after a period of disconnection operation.
** Available operations are:
**
**    list | ls  Display the location of all repositories


**
**    pull       Run a "pull" operation on all repositories
**
**    push       Run a "push" on all repositories
**
**    rebuild    Rebuild on all repositories
**
................................................................................
  
  if( g.argc<3 ){
    usage("list|ls|pull|push|rebuild|sync");
  }
  n = strlen(g.argv[2]);
  db_open_config(1);
  zCmd = g.argv[2];
  if( strncmp(zCmd, "list", n)==0 || strncmp(zCmd,"ls",n)==0 ){


    zCmd = "list";
  }else if( strncmp(zCmd, "push", n)==0 ){
    zCmd = "push -autourl -R";
  }else if( strncmp(zCmd, "pull", n)==0 ){
    zCmd = "pull -autourl -R";
  }else if( strncmp(zCmd, "rebuild", n)==0 ){
    zCmd = "rebuild";

Changes to src/branch.c.

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  Manifest mParent;      /* Parsed parent manifest */
  Blob mcksum;           /* Self-checksum on the manifest */
 
  noSign = find_option("nosign","",0)!=0;
  zColor = find_option("bgcolor","c",1);
  verify_all_options();
  if( g.argc<5 ){
    usage("new BRANCH-NAME BASE-CHECK-IN ?-bgcolor COLOR?");
  }
  db_find_and_open_repository(1);  
  noSign = db_get_int("omitsign", 0)|noSign;
  
  /* fossil branch new name */
  zBranch = g.argv[3];
  if( zBranch==0 || zBranch[0]==0 ){
................................................................................
      "SELECT tagname FROM tagxref, tag"
      " WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid"
      "   AND tagtype>0 AND tagname GLOB 'sym-*'"
      " ORDER BY tagname",
      rootid);
  while( db_step(&q)==SQLITE_ROW ){
    const char *zTag = db_column_text(&q, 0);
    blob_appendf(&branch, "T -%F *\n", zTag);
  }
  db_finalize(&q);
  
  blob_appendf(&branch, "U %F\n", g.zLogin);
  md5sum_blob(&branch, &mcksum);
  blob_appendf(&branch, "Z %b\n", &mcksum);
  if( !noSign && clearsign(&branch, &branch) ){
................................................................................
}

/*
** COMMAND: branch
**
** Usage: %fossil branch SUBCOMMAND ... ?-R|--repository FILE?
**
** Run various subcommands on the branches of the open repository or
** of the repository identified by the -R or --repository option.
**
**    %fossil branch new BRANCH-NAME BASIS ?-bgcolor COLOR? 
**
**        Create a new branch BRANCH-NAME off of check-in BASIS.
**        You can optionally give the branch a default color.
**







|







 







|







 







|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  Manifest mParent;      /* Parsed parent manifest */
  Blob mcksum;           /* Self-checksum on the manifest */
 
  noSign = find_option("nosign","",0)!=0;
  zColor = find_option("bgcolor","c",1);
  verify_all_options();
  if( g.argc<5 ){
    usage("new BRANCH-NAME CHECK-IN ?-bgcolor COLOR?");
  }
  db_find_and_open_repository(1);  
  noSign = db_get_int("omitsign", 0)|noSign;
  
  /* fossil branch new name */
  zBranch = g.argv[3];
  if( zBranch==0 || zBranch[0]==0 ){
................................................................................
      "SELECT tagname FROM tagxref, tag"
      " WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid"
      "   AND tagtype>0 AND tagname GLOB 'sym-*'"
      " ORDER BY tagname",
      rootid);
  while( db_step(&q)==SQLITE_ROW ){
    const char *zTag = db_column_text(&q, 0);
    blob_appendf(&branch, "T -%F *\n", zTag); 
  }
  db_finalize(&q);
  
  blob_appendf(&branch, "U %F\n", g.zLogin);
  md5sum_blob(&branch, &mcksum);
  blob_appendf(&branch, "Z %b\n", &mcksum);
  if( !noSign && clearsign(&branch, &branch) ){
................................................................................
}

/*
** COMMAND: branch
**
** Usage: %fossil branch SUBCOMMAND ... ?-R|--repository FILE?
**
** Run various subcommands to manage branches of the open repository or
** of the repository identified by the -R or --repository option.
**
**    %fossil branch new BRANCH-NAME BASIS ?-bgcolor COLOR? 
**
**        Create a new branch BRANCH-NAME off of check-in BASIS.
**        You can optionally give the branch a default color.
**

Changes to src/cgi.c.

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
...
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
...
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
...
324
325
326
327
328
329
330


331
332
333
334
335
336
337
....
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304


1305
1306
1307

1308
1309
1310
1311
1312
1313
1314
** services to CGI programs.  There are procedures for parsing and
** dispensing QUERY_STRING parameters and cookies, the "mprintf()"
** formatting function and its cousins, and routines to encode and
** decode strings in HTML or HTTP.
*/
#include "config.h"
#ifdef __MINGW32__
#  include <windows.h>           /* for Sleep once server works again */
#  include <winsock2.h>          /* socket operations */
#  define sleep Sleep            /* windows does not have sleep, but Sleep */
#  include <ws2tcpip.h>          
#else
#  include <sys/socket.h>
#  include <netinet/in.h>
#  include <arpa/inet.h>
#  include <sys/times.h>
#  include <sys/time.h>
#  include <sys/wait.h>
#  include <sys/select.h>
#endif
#ifdef __EMX__
   typedef int socklen_t;
#endif
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "cgi.h"

................................................................................
  const char *zName,    /* Name of the cookie */
  const char *zValue,   /* Value of the cookie.  Automatically escaped */
  const char *zPath,    /* Path cookie applies to.  NULL means "/" */
  int lifetime          /* Expiration of the cookie in seconds from now */
){
  if( zPath==0 ) zPath = g.zTop;
  if( lifetime>0 ){
    char *zDate;
    lifetime += (int)time(0);
    zDate = cgi_rfc822_datestamp(lifetime);
    blob_appendf(&extraHeader,
       "Set-Cookie: %s=%t; Path=%s; expires=%s; Version=1\r\n",
        zName, zValue, zPath, zDate);
    if( zDate[0] ) free( zDate );
  }else{
    blob_appendf(&extraHeader,
       "Set-Cookie: %s=%t; Path=%s; Version=1\r\n",
       zName, zValue, zPath);
  }
}

................................................................................
}
#endif

/*
** Do a normal HTTP reply
*/
void cgi_reply(void){
  int total_size = 0;
  if( iReplyStatus<=0 ){
    iReplyStatus = 200;
    zReplyStatus = "OK";
  }

#if 0
  if( iReplyStatus==200 && check_cache_control() ) {
................................................................................
    */
    iReplyStatus = 304;
    zReplyStatus = "Not Modified";
  }
#endif

  if( g.fullHttpReply ){
    char *zDate = cgi_rfc822_datestamp(time(0));
    fprintf(g.httpOut, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
    fprintf(g.httpOut, "Date: %s\r\n", zDate );
    if( zDate[0] ) free( zDate );
    fprintf(g.httpOut, "Connection: close\r\n");
  }else{
    fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
  }

  if( blob_size(&extraHeader)>0 ){
    fprintf(g.httpOut, "%s", blob_buffer(&extraHeader));
................................................................................
    ** case of most /getfile calls for specific versions, the only way the
    ** content changes is if someone breaks the SCM. And if that happens, a
    ** stale cache is the least of the problem. So we provide an Expires
    ** header set to a reasonable period (default: one week).
    */
    /*time_t expires = time(0) + atoi(db_config("constant_expires","604800"));*/
    time_t expires = time(0) + 604800;
    char * zDate = cgi_rfc822_datestamp(expires);
    fprintf(g.httpOut, "Expires: %s\r\n", zDate );
    if( zDate[0] ) free( zDate );
  }

  /* Content intended for logged in users should only be cached in
  ** the browser, not some shared location.
  */
  fprintf(g.httpOut, "Cache-control: no-cache, no-store\r\n");
  fprintf(g.httpOut, "Content-Type: %s; charset=utf-8\r\n", zContentType);
................................................................................
    cgi_combine_header_and_body();
    blob_compress(&cgiContent[0], &cgiContent[0]);
  }

  if( iReplyStatus != 304 ) {
    total_size = blob_size(&cgiContent[0]) + blob_size(&cgiContent[1]);
    fprintf(g.httpOut, "Content-Length: %d\r\n", total_size);


  }
  fprintf(g.httpOut, "\r\n");
  if( total_size>0 && iReplyStatus != 304 ){
    int i, size;
    for(i=0; i<2; i++){
      size = blob_size(&cgiContent[i]);
      if( size>0 ){
................................................................................
    {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 0};
static const char *azMonths[] =
    {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 0};


/*
** Returns an RFC822-formatted time string suitable for HTTP headers, among
** other things.
** Returned timezone is always GMT as required by HTTP/1.1 specification.
** The returned string is allocated with malloc() and must be freed
** with free().
**
** See http://www.faqs.org/rfcs/rfc822.html, section 5
** and http://www.faqs.org/rfcs/rfc2616.html, section 3.3.
*/
char *cgi_rfc822_datestamp(time_t now){
  struct tm *pTm;
  pTm = gmtime(&now);
  if( pTm==0 ) return "";


  return mprintf("%s, %d %s %02d %02d:%02d:%02d GMT",
                 azDays[pTm->tm_wday], pTm->tm_mday, azMonths[pTm->tm_mon],
                 pTm->tm_year+1900, pTm->tm_hour, pTm->tm_min, pTm->tm_sec);

}

/*
** Parse an RFC822-formatted timestamp as we'd expect from HTTP and return
** a Unix epoch time. <= zero is returned on failure.
**
** Note that this won't handle all the _allowed_ HTTP formats, just the







|
|
|
|

|
|
|
|
|
|
|


|







 







<

<

|
|
<







 







|







 







<

|
<







 







<
|
<







 







>
>







 







|
|
|
|
<







|
>
>
|
|
|
>







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
193
194
195
196
197
198
199

200

201
202
203

204
205
206
207
208
209
210
...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
...
279
280
281
282
283
284
285

286
287

288
289
290
291
292
293
294
...
301
302
303
304
305
306
307

308

309
310
311
312
313
314
315
...
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
....
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290

1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
** services to CGI programs.  There are procedures for parsing and
** dispensing QUERY_STRING parameters and cookies, the "mprintf()"
** formatting function and its cousins, and routines to encode and
** decode strings in HTML or HTTP.
*/
#include "config.h"
#ifdef __MINGW32__
# include <windows.h>           /* for Sleep once server works again */
# include <winsock2.h>          /* socket operations */
# define sleep Sleep            /* windows does not have sleep, but Sleep */
# include <ws2tcpip.h>          
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <sys/times.h>
# include <sys/time.h>
# include <sys/wait.h>
# include <sys/select.h>
#endif
#ifdef __EMX__
  typedef int socklen_t;
#endif
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "cgi.h"

................................................................................
  const char *zName,    /* Name of the cookie */
  const char *zValue,   /* Value of the cookie.  Automatically escaped */
  const char *zPath,    /* Path cookie applies to.  NULL means "/" */
  int lifetime          /* Expiration of the cookie in seconds from now */
){
  if( zPath==0 ) zPath = g.zTop;
  if( lifetime>0 ){

    lifetime += (int)time(0);

    blob_appendf(&extraHeader,
       "Set-Cookie: %s=%t; Path=%s; expires=%z; Version=1\r\n",
        zName, zValue, zPath, cgi_rfc822_datestamp(lifetime));

  }else{
    blob_appendf(&extraHeader,
       "Set-Cookie: %s=%t; Path=%s; Version=1\r\n",
       zName, zValue, zPath);
  }
}

................................................................................
}
#endif

/*
** Do a normal HTTP reply
*/
void cgi_reply(void){
  int total_size;
  if( iReplyStatus<=0 ){
    iReplyStatus = 200;
    zReplyStatus = "OK";
  }

#if 0
  if( iReplyStatus==200 && check_cache_control() ) {
................................................................................
    */
    iReplyStatus = 304;
    zReplyStatus = "Not Modified";
  }
#endif

  if( g.fullHttpReply ){

    fprintf(g.httpOut, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
    fprintf(g.httpOut, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));

    fprintf(g.httpOut, "Connection: close\r\n");
  }else{
    fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
  }

  if( blob_size(&extraHeader)>0 ){
    fprintf(g.httpOut, "%s", blob_buffer(&extraHeader));
................................................................................
    ** case of most /getfile calls for specific versions, the only way the
    ** content changes is if someone breaks the SCM. And if that happens, a
    ** stale cache is the least of the problem. So we provide an Expires
    ** header set to a reasonable period (default: one week).
    */
    /*time_t expires = time(0) + atoi(db_config("constant_expires","604800"));*/
    time_t expires = time(0) + 604800;

    fprintf(g.httpOut, "Expires: %s\r\n", cgi_rfc822_datestamp(expires));

  }

  /* Content intended for logged in users should only be cached in
  ** the browser, not some shared location.
  */
  fprintf(g.httpOut, "Cache-control: no-cache, no-store\r\n");
  fprintf(g.httpOut, "Content-Type: %s; charset=utf-8\r\n", zContentType);
................................................................................
    cgi_combine_header_and_body();
    blob_compress(&cgiContent[0], &cgiContent[0]);
  }

  if( iReplyStatus != 304 ) {
    total_size = blob_size(&cgiContent[0]) + blob_size(&cgiContent[1]);
    fprintf(g.httpOut, "Content-Length: %d\r\n", total_size);
  }else{
    total_size = 0;
  }
  fprintf(g.httpOut, "\r\n");
  if( total_size>0 && iReplyStatus != 304 ){
    int i, size;
    for(i=0; i<2; i++){
      size = blob_size(&cgiContent[i]);
      if( size>0 ){
................................................................................
    {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 0};
static const char *azMonths[] =
    {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 0};


/*
** Returns an RFC822-formatted time string suitable for HTTP headers.
** The timezone is always GMT.  The value returned is always a
** string obtained from mprintf() and must be freed using free() to
** avoid a memory leak.

**
** See http://www.faqs.org/rfcs/rfc822.html, section 5
** and http://www.faqs.org/rfcs/rfc2616.html, section 3.3.
*/
char *cgi_rfc822_datestamp(time_t now){
  struct tm *pTm;
  pTm = gmtime(&now);
  if( pTm==0 ){
    return mprintf("");
  }else{
    return mprintf("%s, %d %s %02d %02d:%02d:%02d GMT",
                   azDays[pTm->tm_wday], pTm->tm_mday, azMonths[pTm->tm_mon],
                   pTm->tm_year+1900, pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
  }
}

/*
** Parse an RFC822-formatted timestamp as we'd expect from HTTP and return
** a Unix epoch time. <= zero is returned on failure.
**
** Note that this won't handle all the _allowed_ HTTP formats, just the

Changes to src/checkin.c.

439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
...
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
...
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
...
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
...
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
** COMMAND: ci
** COMMAND: commit
**
** Usage: %fossil commit ?OPTIONS? ?FILE...?
**
** Create a new version containing all of the changes in the current
** checkout.  You will be prompted to enter a check-in comment unless
** one of the "-m" or "-M" options are used to specify a comment.
** "-m" takes a single string for the commit message and "-M" requires
** a filename from which to read the commit message. If neither "-m"
** nor "-M" are specified then the editor defined in the "editor"
** fossil option (see %fossil help set) will be used, or from the
** "VISUAL" or "EDITOR" environment variables (in that order) if no
** editor is set.
**
** You will be prompted for your GPG passphrase in order to sign the
** new manifest unless the "--nosign" options is used.  All files that
** have changed will be committed unless some subset of files is
** specified on the command line.
**
** The --branch option followed by a branch name cases the new check-in
................................................................................
**
**    --comment|-m COMMENT-TEXT
**    --branch NEW-BRANCH-NAME
**    --bgcolor COLOR
**    --nosign
**    --force|-f
**    --private
**    --message-file|-M COMMENT-FILE
**    
*/
void commit_cmd(void){
  int rc;
  int vid, nrid, nvid;
  Blob comment;
  const char *zComment;
................................................................................
  int forceFlag = 0;     /* Force a fork */
  char *zManifestFile;   /* Name of the manifest file */
  int nBasename;         /* Length of "g.zLocalRoot/" */
  const char *zBranch;   /* Create a new branch with this name */
  const char *zBgColor;  /* Set background color when branching */
  const char *zDateOvrd; /* Override date string */
  const char *zUserOvrd; /* Override user name */
  const char *zCommentFile; /* Read commit message from this file */
  Blob filename;         /* complete filename */
  Blob manifest;
  Blob muuid;            /* Manifest uuid */
  Blob mcksum;           /* Self-checksum on the manifest */
  Blob cksum1, cksum2;   /* Before and after commit checksums */
  Blob cksum1b;          /* Checksum recorded in the manifest */
 
  url_proxy_options();
  noSign = find_option("nosign",0,0)!=0;
  zComment = find_option("comment","m",1);
  forceFlag = find_option("force", "f", 0)!=0;
  zBranch = find_option("branch","b",1);
  zBgColor = find_option("bgcolor",0,1);
  zCommentFile = find_option("message-file", "M", 1);
  if( find_option("private",0,0) ){
    g.markPrivate = 1;
    if( zBranch==0 ) zBranch = "private";
    if( zBgColor==0 ) zBgColor = "#fec084";  /* Orange */
  }
  zDateOvrd = find_option("date-override",0,1);
  zUserOvrd = find_option("user-override",0,1);
................................................................................
    fossil_fatal("cannot commit against a closed leaf");
  }

  vfile_aggregate_checksum_disk(vid, &cksum1);
  if( zComment ){
    blob_zero(&comment);
    blob_append(&comment, zComment, -1);
  }else if( zCommentFile ){
    blob_zero(&comment);
    blob_read_from_file(&comment, zCommentFile);
  }else{
    char *zInit = db_text(0, "SELECT value FROM vvar WHERE name='ci-comment'");
    prepare_commit_comment(&comment, zInit, zBranch, vid);
    free(zInit);
  }
  if( blob_size(&comment)==0 ){
    Blob ans;
................................................................................
  if( !g.markPrivate ){
    autosync(AUTOSYNC_PUSH);  
  }
  if( count_nonbranch_children(vid)>1 ){
    printf("**** warning: a fork has occurred *****\n");
  }
}

/*
** COMMAND: test-import-manifest
**
** Usage: %fossil test-import-manifest DATE COMMENT ?-p PARENT_RECORDID?... ?-f (FILE_RECORDID PATH)?...
**
** Create a new version containing the specified file
** revisions (if any), and child of the given PARENT version.
*/
void import_manifest_cmd(void){
  const char* zDate;    /* argument - timestamp, as seconds since epoch (int) */
  const char* zComment; /* argument - manifest comment */
  char* zDateFmt;       /* timestamp formatted for the manifest */
  int* zParents;        /* arguments - array of parent references */
  int zParentCount;     /* number of found parent references */
  Blob manifest;        /* container for the manifest to be generated */
  Blob mcksum;          /* Self-checksum on the manifest */
  Blob cksum, cksum2;   /* Before and after commit checksums */
  Blob cksum1b;         /* Checksum recorded in the manifest */
  const char* parent;   /* loop variable when collecting parent references */
  int i, mid;           /* Another loop index, and id of new manifest */
  Stmt q;               /* sql statement to query table of files */
  char* zMidUuid;       /* Uuid for the newly generated manifest */


#define USAGE ("DATE COMMENT ?-p|-parent PARENT_RID...? ?-f|-file (FILE_RID PATH)...?")

  /*
  ** Validate and process arguments, collect information.
  */

  db_must_be_within_tree();

  /* Mandatory arguments */
  if (g.argc < 4) {
    usage (USAGE);
  }

  zDate    = g.argv[2];
  zComment = g.argv[3];

  remove_from_argv (2,2);

  /* Pull the optional parent arguments
  **
  ** Note: In principle it is possible that the loop below extracts
  ** the wrong arguments, if we ever try to import a file whose path
  ** starts with -p/-parent. In that case however the removal of two
  ** arguments will leave the file bereft of an argument and the
  ** recheck of the number of arguments below should catch that.
  **
  ** For a test command this is acceptable, it won't have lots of
  ** safety nets.
  */

  zParentCount = 0;
  zParents = (int*)malloc(sizeof(int)*(1+g.argc));
  /* 1+, to be ok with the default even if no arguments around */

  while ((parent = find_option("parent","p",1)) != NULL) {
    /* Check and store ... */
    zParents [zParentCount] = name_to_rid (parent);
    zParentCount ++;
  }

  /*
  ** Fall back to the root manifest as parent if none were specified
  ** explicitly.
  */

  if (!zParentCount) {
    zParents [zParentCount] = 1; /* HACK: rid 1 is the baseline manifest
				 ** which was entered when the repository
				 ** was created via 'new'. It always has
				 ** rid 1.
				 */
    zParentCount ++;
  }

  /* Pull the file arguments, at least one has to be present. They are
  ** the only things we can have here, now, and they are triples of
  ** '-f FID PATH', so use of find_option is out, and we can check the
  ** number of arguments.
  **
  ** Note: We store the data in a temp. table, so that we later can
  **       pull it sorted, and also easily get the associated hash
  **       identifiers.
  **
  ** Note 2: We expect at least one file, otherwise the manifest won't
  ** be recognized as a baseline by the manifest parser.
  */

  if (((g.argc-2) % 3 != 0) || (g.argc < 5)) {
    usage (USAGE);
  }

  db_begin_transaction();
  db_multi_exec ("CREATE TEMP TABLE __im ("
		 "rid      INTEGER NOT NULL,"
		 "pathname TEXT    NOT NULL)" );

  while (g.argc > 2) {
    /* Check and store ... */
    if (strcmp("-f",   g.argv[2]) &&
	strcmp("-file",g.argv[2])) {
      usage (USAGE);
    }

    /* DANGER The %s for the path might lead itself to an injection
    ** attack. For now (i.e. testing) this is ok, but do something
    ** better in the future.
    */

    db_multi_exec("INSERT INTO __im VALUES(%d,'%s')",
		  name_to_rid (g.argv[3]), g.argv[4] );
    remove_from_argv (2,3);
  }

  verify_all_options();

  /*
  ** Determine the user the manifest will belong to, and check that
  ** this user exists.
  */

  user_select();
  if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){
    fossil_fatal("no such user: %s", g.zLogin);
  }

  /*
  ** Now generate the manifest in memory.
  **
  ** Start with comment and date. The latter is converted to the
  ** proper format before insertion.
  */

  blob_zero(&manifest);

  if (!strlen(zComment)) {
    blob_appendf(&manifest, "C %F\n", "(no comment)");
  } else {
    blob_appendf(&manifest, "C %F\n", zComment);
  }

  zDateFmt = db_text(0, "SELECT datetime(%Q,'unixepoch')",zDate);
  zDateFmt[10] = 'T';
  blob_appendf(&manifest, "D %s\n", zDateFmt);
  free(zDateFmt);

  /*
  ** Follow with all the collected files, properly sorted. Here were
  ** also compute the checksum over the files (paths, sizes,
  ** contents), similar to what 'vfile_aggregate_checksum_repository'
  ** does.
  */

  md5sum_init();
  db_prepare(&q,
	     "SELECT pathname, uuid, __im.rid"
	     " FROM __im JOIN blob ON __im.rid=blob.rid"
	     " ORDER BY 1");

  while( db_step(&q)==SQLITE_ROW ){
    char zBuf[100];
    Blob file;
    const char *zName = db_column_text(&q, 0);
    const char *zUuid = db_column_text(&q, 1);
    int         zRid  = db_column_int (&q, 2);

    /* Extend the manifest */
    blob_appendf(&manifest, "F %F %s\n", zName, zUuid);

    /* Update the checksum */
    md5sum_step_text(zName, -1);
    blob_zero(&file);
    content_get(zRid, &file);
    sprintf(zBuf, " %d\n", blob_size(&file));
    md5sum_step_text(zBuf, -1);
    md5sum_step_blob(&file);
    blob_reset(&file);
  }
  db_finalize(&q);
  md5sum_finish (&cksum);

  /*
  ** Follow with all the specified parents. We know that there is at
  ** least one.
  */

  blob_appendf(&manifest, "P");
  for (i=0;i<zParentCount;i++) {
    char* zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", zParents[i]);
    blob_appendf(&manifest, " %s", zUuid);
    free(zUuid);
  }
  blob_appendf(&manifest, "\n");

  /*
  ** Complete the manifest with user name and the various checksums
  */

  blob_appendf(&manifest, "R %b\n", &cksum);
  blob_appendf(&manifest, "U %F\n", g.zLogin);
  md5sum_blob(&manifest, &mcksum);
  blob_appendf(&manifest, "Z %b\n", &mcksum);

  /*
  ** Now insert the new manifest, try to compress it relative to first
  ** parent (primary).
   */

  /*blob_write_to_file (&manifest, "TEST_MANIFEST");*/

  mid = content_put(&manifest, 0, 0);
  if( mid==0 ){
    fossil_panic("trouble committing manifest: %s", g.zErrMsg);
  }

  content_deltify(zParents[0], mid, 0);

  /* Verify that the repository checksum matches the expected checksum
  ** calculated before the checkin started (and stored as the R record
  ** of the manifest file).
  */

  vfile_aggregate_checksum_manifest(mid, &cksum2, &cksum1b);
  if( blob_compare(&cksum, &cksum1b) ){
    fossil_panic("manifest checksum does not agree with manifest: "
                 "%b versus %b", &cksum, &cksum1b);
  }
  if( blob_compare(&cksum, &cksum2) ){
    fossil_panic("tree checksum does not match manifest after commit: "
                 "%b versus %b", &cksum, &cksum2);
  }

  /*
  ** At last commit all changes, after getting rid of the temp
  ** holder for the files, and release allocated memory.
  */

  db_multi_exec("DROP TABLE __im");
  zMidUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
  db_end_transaction(0);
  free(zParents);

  /*
  ** At the very last inform the caller about the id and uuid of the
  ** new manifest.
  */


  printf("inserted as record %d, %s\n", mid, zMidUuid);
  free(zMidUuid);
  return;

#undef USAGE
}







|
<
<
|
|
|
<







 







<







 







|













|







 







|

|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
439
440
441
442
443
444
445
446


447
448
449

450
451
452
453
454
455
456
...
468
469
470
471
472
473
474

475
476
477
478
479
480
481
...
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
...
811
812
813
814
815
816
817


































































































































































































































































** COMMAND: ci
** COMMAND: commit
**
** Usage: %fossil commit ?OPTIONS? ?FILE...?
**
** Create a new version containing all of the changes in the current
** checkout.  You will be prompted to enter a check-in comment unless
** the comment has been specified on the command-line using "-m".


** The editor defined in the "editor" fossil option (see %fossil help set)
** will be used, or from the "VISUAL" or "EDITOR" environment variables
** (in that order) if no editor is set.

**
** You will be prompted for your GPG passphrase in order to sign the
** new manifest unless the "--nosign" options is used.  All files that
** have changed will be committed unless some subset of files is
** specified on the command line.
**
** The --branch option followed by a branch name cases the new check-in
................................................................................
**
**    --comment|-m COMMENT-TEXT
**    --branch NEW-BRANCH-NAME
**    --bgcolor COLOR
**    --nosign
**    --force|-f
**    --private

**    
*/
void commit_cmd(void){
  int rc;
  int vid, nrid, nvid;
  Blob comment;
  const char *zComment;
................................................................................
  int forceFlag = 0;     /* Force a fork */
  char *zManifestFile;   /* Name of the manifest file */
  int nBasename;         /* Length of "g.zLocalRoot/" */
  const char *zBranch;   /* Create a new branch with this name */
  const char *zBgColor;  /* Set background color when branching */
  const char *zDateOvrd; /* Override date string */
  const char *zUserOvrd; /* Override user name */
  const char *zComFile;  /* Read commit message from this file */
  Blob filename;         /* complete filename */
  Blob manifest;
  Blob muuid;            /* Manifest uuid */
  Blob mcksum;           /* Self-checksum on the manifest */
  Blob cksum1, cksum2;   /* Before and after commit checksums */
  Blob cksum1b;          /* Checksum recorded in the manifest */
 
  url_proxy_options();
  noSign = find_option("nosign",0,0)!=0;
  zComment = find_option("comment","m",1);
  forceFlag = find_option("force", "f", 0)!=0;
  zBranch = find_option("branch","b",1);
  zBgColor = find_option("bgcolor",0,1);
  zComFile = find_option("message-file", "M", 1);
  if( find_option("private",0,0) ){
    g.markPrivate = 1;
    if( zBranch==0 ) zBranch = "private";
    if( zBgColor==0 ) zBgColor = "#fec084";  /* Orange */
  }
  zDateOvrd = find_option("date-override",0,1);
  zUserOvrd = find_option("user-override",0,1);
................................................................................
    fossil_fatal("cannot commit against a closed leaf");
  }

  vfile_aggregate_checksum_disk(vid, &cksum1);
  if( zComment ){
    blob_zero(&comment);
    blob_append(&comment, zComment, -1);
  }else if( zComFile ){
    blob_zero(&comment);
    blob_read_from_file(&comment, zComFile);
  }else{
    char *zInit = db_text(0, "SELECT value FROM vvar WHERE name='ci-comment'");
    prepare_commit_comment(&comment, zInit, zBranch, vid);
    free(zInit);
  }
  if( blob_size(&comment)==0 ){
    Blob ans;
................................................................................
  if( !g.markPrivate ){
    autosync(AUTOSYNC_PUSH);  
  }
  if( count_nonbranch_children(vid)>1 ){
    printf("**** warning: a fork has occurred *****\n");
  }
}


































































































































































































































































Changes to src/checkout.c.

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  }
  blob_reset(&filename);
  manifest_clear(&m);
}

/*
** COMMAND: checkout
** COMMAND: co
**
** Usage: %fossil checkout VERSION ?-f|--force? ?--keep?
**
** Check out a version specified on the command-line.  This command
** will abort if there are edited files in the current checkout unless
** the --force option appears on the command-line.  The --keep option
** leaves files on disk unchanged, except the manifest and manifest.uuid







<







134
135
136
137
138
139
140

141
142
143
144
145
146
147
  }
  blob_reset(&filename);
  manifest_clear(&m);
}

/*
** COMMAND: checkout

**
** Usage: %fossil checkout VERSION ?-f|--force? ?--keep?
**
** Check out a version specified on the command-line.  This command
** will abort if there are edited files in the current checkout unless
** the --force option appears on the command-line.  The --keep option
** leaves files on disk unchanged, except the manifest and manifest.uuid

Changes to src/config.h.

30
31
32
33
34
35
36






37
38
39
40
41
42
43
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>






#include "sqlite3.h"

/*
** Typedef for a 64-bit integer
*/
typedef sqlite_int64 i64;
typedef sqlite_uint64 u64;







>
>
>
>
>
>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
#ifdef __MINGW32__
# include <windows.h>
#else
# include <pwd.h>
#endif

#include "sqlite3.h"

/*
** Typedef for a 64-bit integer
*/
typedef sqlite_int64 i64;
typedef sqlite_uint64 u64;

Deleted src/construct.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*
** Copyright (c) 2007 Andreas Kupries
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public
** License version 2 as published by the Free Software Foundation.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** General Public License for more details.
** 
** You should have received a copy of the GNU General Public
** License along with this library; if not, write to the
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
** Boston, MA  02111-1307, USA.
**
** Author contact information:
**   akupries@shaw.ca
**   
**
*******************************************************************************
**
** This file contains code used to de- and reconstruct a repository
** into and from an indicated directory.
*/
#include "config.h"
#include "construct.h"
#include <assert.h>
#include <sys/types.h>
#include <dirent.h>

/* This function recursively scans the directory hierarchy starting at
** zOrigin and enters all found files into the repository. The uuid is
** generated from the file contents, and not taken from the, possibly
** modified, file name. While function is able to handle the directory
** structure created by 'deconstruct' it can actually much more.
*/

static int import_origin(const char* zOrigin){
  DIR *d;
  int count = 0;
  const char *zFormat;
  const char *zDir = zOrigin;
  struct dirent *pEntry;

  if( zDir[0]==0 ){
     zDir = ".";
     zFormat = "%s%s";
  }else{
     zFormat = "%s/%s";
  }

  d = opendir(zDir);
  if( d ){
    while( (pEntry=readdir(d))!=0 ){
      char *zPath;
      if( pEntry->d_name[0]=='.' ) continue;
      zPath = mprintf(zFormat, zOrigin, pEntry->d_name);
      if( file_isdir(zPath)==1 ){
        count += import_origin(zPath);
      }else if( file_isfile(zPath) ){
	Blob zIn;
	blob_read_from_file (&zIn,zPath);
	content_put (&zIn, 0, 0);
	blob_reset (&zIn);
	count++;
      }
      free (zPath);
    }
  }
  closedir(d);
  return count;
}

/*
** COMMAND: deconstruct 
** Usage %fossil deconstruct ?-R|--repository REPOSITORY? DESTINATION
**
** Populates the indicated DESTINATION directory with copies of all
** artifcats contained within the repository.  Artifacts are named AA/bbbbb
** where AA is the first 2 characters of the artifact ID and bbbbb is the
** remaining 38 characters.
*/

void deconstruct_cmd(void){
  const char* zDestination;
  Blob zOut;
  Stmt q;
  if( (g.argc != 3) && (g.argc != 5) ){
    usage ("?-R|--repository REPOSITORY? DESTINATION");
  }
  db_find_and_open_repository(1);
  zDestination = g.argv[g.argc-1];
  if( !file_isdir (zDestination) ){
    fossil_panic("not a directory: %s", zDestination);
  }
  /* Iterate over all blobs in the repository, retrieve their
   * contents, and write them to a file with a name based on their
   * uuid. Note: Non-writable destination causes bail-out in the first
   * call of blob_write_to_file.
   */
  db_prepare(&q, "SELECT rid,uuid FROM blob");
  while( db_step(&q)==SQLITE_ROW ){
    int         rid   = db_column_int (&q, 0);
    const char *zUuid = db_column_text(&q, 1);
    char       *zFile = mprintf ("%s/%.2s/%s", zDestination, zUuid, zUuid + 2);
    content_get (rid,&zOut);
    blob_write_to_file (&zOut,zFile);
    blob_reset (&zOut);
    free(zFile);
  }
  db_finalize(&q);
}

/*
** COMMAND: reconstruct 
** Usage %fossil reconstruct REPOSITORY ORIGIN
**
** Creates the REPOSITORY and populates it with the artifacts in the
** indicated ORIGIN directory.
*/

void reconstruct_cmd(void){
  const char* zOrigin;
  const char* zRepository;
  int fileCnt;
  int errCnt;

  if( g.argc != 4 ){
    usage ("REPOSITORY ORIGIN");
  }
  zRepository = g.argv[2];
  zOrigin     = g.argv[3];
  if( !file_isdir (zOrigin) ){
    fossil_panic("not a directory: %s", zOrigin);
  }

  /* Create the foundation */
  db_create_repository(zRepository);
  db_open_repository(zRepository);
  db_open_config(0);
  db_begin_transaction();

  db_initial_setup(0, 1);

  printf("project-id: %s\n", db_get("project-code", 0));
  printf("server-id:  %s\n", db_get("server-code", 0));
  printf("admin-user: %s (no password set yet!)\n", g.zLogin);
  printf("baseline:   %s\n", db_text(0, "SELECT uuid FROM blob"));

  /* Scan origin and insert all files found inside */
  fileCnt = import_origin (zOrigin);

  printf("imported:   %d %s\n", fileCnt, fileCnt == 1 ?
	 "file" : "files");

  /* Finalize the repository, rebuild the derived tables */
  errCnt = rebuild_db(0, 0);

  if( errCnt ){
    printf("%d %s. Rolling back changes.\n", errCnt, errCnt == 1 ?
	   "error" : "errors");
    db_end_transaction(1);
  }else{
    db_end_transaction(0);
  }
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















































































































































































































































































































































Changes to src/db.c.

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
....
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
....
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
**    (2)  The "repository" database
**
**    (3)  A local checkout database named "_FOSSIL_" or ".fos"
**         and located at the root of the local copy of the source tree.
**
*/
#include "config.h"
#ifndef __MINGW32__
#  include <pwd.h>
#endif
#ifdef __MINGW32__
#  include <windows.h>
#endif
#include <sqlite3.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "db.h"

#if INTERFACE
................................................................................
** The "setting" command with no arguments lists all properties and their
** values.  With just a property name it shows the value of that property.
** With a value argument it changes the property for the current repository.
**
** The "unset" command clears a property setting.
**
**
**    auto-captcha     If enabled, the Login page will provide a button
**                     which uses JavaScript to fill out the captcha for
**                     the "anonymous" user. (Most bots cannot use JavaScript.)
**
**    autosync         If enabled, automatically pull prior to
**                     commit or update and automatically push
**                     after commit or tag or branch creation.
**
**    clearsign        When enabled (the default), fossil will attempt to
**                     sign all commits with gpg.  When disabled, commits will
**                     be unsigned.
................................................................................
**    web-browser      A shell command used to launch your preferred
**                     web browser when given a URL as an argument.
**                     Defaults to "start" on windows, "open" on Mac,
**                     and "firefox" on Unix.
*/
void setting_cmd(void){
  static const char *azName[] = {
    "auto-captcha",
    "autosync",
    "clearsign",
    "diff-command",
    "dont-push",
    "editor",
    "gdiff-command",
    "http-port",







<
<
<
<
<
<







 







<
<
<
<







 







<







31
32
33
34
35
36
37






38
39
40
41
42
43
44
....
1461
1462
1463
1464
1465
1466
1467




1468
1469
1470
1471
1472
1473
1474
....
1506
1507
1508
1509
1510
1511
1512

1513
1514
1515
1516
1517
1518
1519
**    (2)  The "repository" database
**
**    (3)  A local checkout database named "_FOSSIL_" or ".fos"
**         and located at the root of the local copy of the source tree.
**
*/
#include "config.h"






#include <sqlite3.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "db.h"

#if INTERFACE
................................................................................
** The "setting" command with no arguments lists all properties and their
** values.  With just a property name it shows the value of that property.
** With a value argument it changes the property for the current repository.
**
** The "unset" command clears a property setting.
**
**




**    autosync         If enabled, automatically pull prior to
**                     commit or update and automatically push
**                     after commit or tag or branch creation.
**
**    clearsign        When enabled (the default), fossil will attempt to
**                     sign all commits with gpg.  When disabled, commits will
**                     be unsigned.
................................................................................
**    web-browser      A shell command used to launch your preferred
**                     web browser when given a URL as an argument.
**                     Defaults to "start" on windows, "open" on Mac,
**                     and "firefox" on Unix.
*/
void setting_cmd(void){
  static const char *azName[] = {

    "autosync",
    "clearsign",
    "diff-command",
    "dont-push",
    "editor",
    "gdiff-command",
    "http-port",

Changes to src/main.mk.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
..
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
...
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
...
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
...
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
  $(SRCDIR)/cgi.c \
  $(SRCDIR)/checkin.c \
  $(SRCDIR)/checkout.c \
  $(SRCDIR)/clearsign.c \
  $(SRCDIR)/clone.c \
  $(SRCDIR)/comformat.c \
  $(SRCDIR)/configure.c \
  $(SRCDIR)/construct.c \
  $(SRCDIR)/content.c \
  $(SRCDIR)/db.c \
  $(SRCDIR)/delta.c \
  $(SRCDIR)/deltacmd.c \
  $(SRCDIR)/descendants.c \
  $(SRCDIR)/diff.c \
  $(SRCDIR)/diffcmd.c \
................................................................................
  $(SRCDIR)/name.c \
  $(SRCDIR)/pivot.c \
  $(SRCDIR)/pqueue.c \
  $(SRCDIR)/printf.c \
  $(SRCDIR)/rebuild.c \
  $(SRCDIR)/report.c \
  $(SRCDIR)/rss.c \
  $(SRCDIR)/rstats.c \
  $(SRCDIR)/schema.c \
  $(SRCDIR)/search.c \
  $(SRCDIR)/setup.c \
  $(SRCDIR)/sha1.c \
  $(SRCDIR)/shun.c \
  $(SRCDIR)/skins.c \
  $(SRCDIR)/stat.c \
................................................................................
  cgi_.c \
  checkin_.c \
  checkout_.c \
  clearsign_.c \
  clone_.c \
  comformat_.c \
  configure_.c \
  construct_.c \
  content_.c \
  db_.c \
  delta_.c \
  deltacmd_.c \
  descendants_.c \
  diff_.c \
  diffcmd_.c \
................................................................................
  name_.c \
  pivot_.c \
  pqueue_.c \
  printf_.c \
  rebuild_.c \
  report_.c \
  rss_.c \
  rstats_.c \
  schema_.c \
  search_.c \
  setup_.c \
  sha1_.c \
  shun_.c \
  skins_.c \
  stat_.c \
................................................................................
  cgi.o \
  checkin.o \
  checkout.o \
  clearsign.o \
  clone.o \
  comformat.o \
  configure.o \
  construct.o \
  content.o \
  db.o \
  delta.o \
  deltacmd.o \
  descendants.o \
  diff.o \
  diffcmd.o \
................................................................................
  name.o \
  pivot.o \
  pqueue.o \
  printf.o \
  rebuild.o \
  report.o \
  rss.o \
  rstats.o \
  schema.o \
  search.o \
  setup.o \
  sha1.o \
  shun.o \
  skins.o \
  stat.o \
................................................................................
#
$(SRCDIR)/../manifest:	
	# noop

clean:	
	rm -f *.o *_.c $(APPNAME) VERSION.h
	rm -f translate makeheaders mkindex page_index.h headers
	rm -f add.h allrepo.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h construct.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h finfo.h http.h http_socket.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h pqueue.h printf.h rebuild.h report.h rss.h rstats.h schema.h search.h setup.h sha1.h shun.h skins.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h

page_index.h: $(TRANS_SRC) mkindex
	./mkindex $(TRANS_SRC) >$@
headers:	page_index.h makeheaders VERSION.h
	./makeheaders  add_.c:add.h allrepo_.c:allrepo.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h construct_.c:construct.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h finfo_.c:finfo.h http_.c:http.h http_socket_.c:http_socket.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h rstats_.c:rstats.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h
	touch headers
headers: Makefile
Makefile:
add_.c:	$(SRCDIR)/add.c translate
	./translate $(SRCDIR)/add.c >add_.c

add.o:	add_.c add.h  $(SRCDIR)/config.h
................................................................................
configure_.c:	$(SRCDIR)/configure.c translate
	./translate $(SRCDIR)/configure.c >configure_.c

configure.o:	configure_.c configure.h  $(SRCDIR)/config.h
	$(XTCC) -o configure.o -c configure_.c

configure.h:	headers
construct_.c:	$(SRCDIR)/construct.c translate
	./translate $(SRCDIR)/construct.c >construct_.c

construct.o:	construct_.c construct.h  $(SRCDIR)/config.h
	$(XTCC) -o construct.o -c construct_.c

construct.h:	headers
content_.c:	$(SRCDIR)/content.c translate
	./translate $(SRCDIR)/content.c >content_.c

content.o:	content_.c content.h  $(SRCDIR)/config.h
	$(XTCC) -o content.o -c content_.c

content.h:	headers
................................................................................
rss_.c:	$(SRCDIR)/rss.c translate
	./translate $(SRCDIR)/rss.c >rss_.c

rss.o:	rss_.c rss.h  $(SRCDIR)/config.h
	$(XTCC) -o rss.o -c rss_.c

rss.h:	headers
rstats_.c:	$(SRCDIR)/rstats.c translate
	./translate $(SRCDIR)/rstats.c >rstats_.c

rstats.o:	rstats_.c rstats.h  $(SRCDIR)/config.h
	$(XTCC) -o rstats.o -c rstats_.c

rstats.h:	headers
schema_.c:	$(SRCDIR)/schema.c translate
	./translate $(SRCDIR)/schema.c >schema_.c

schema.o:	schema_.c schema.h  $(SRCDIR)/config.h
	$(XTCC) -o schema.o -c schema_.c

schema.h:	headers







<







 







<







 







<







 







<







 







<







 







<







 







|




|







 







<
<
<
<
<
<
<







 







<
<
<
<
<
<
<







23
24
25
26
27
28
29

30
31
32
33
34
35
36
..
51
52
53
54
55
56
57

58
59
60
61
62
63
64
..
92
93
94
95
96
97
98

99
100
101
102
103
104
105
...
120
121
122
123
124
125
126

127
128
129
130
131
132
133
...
161
162
163
164
165
166
167

168
169
170
171
172
173
174
...
189
190
191
192
193
194
195

196
197
198
199
200
201
202
...
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
...
363
364
365
366
367
368
369







370
371
372
373
374
375
376
...
559
560
561
562
563
564
565







566
567
568
569
570
571
572
  $(SRCDIR)/cgi.c \
  $(SRCDIR)/checkin.c \
  $(SRCDIR)/checkout.c \
  $(SRCDIR)/clearsign.c \
  $(SRCDIR)/clone.c \
  $(SRCDIR)/comformat.c \
  $(SRCDIR)/configure.c \

  $(SRCDIR)/content.c \
  $(SRCDIR)/db.c \
  $(SRCDIR)/delta.c \
  $(SRCDIR)/deltacmd.c \
  $(SRCDIR)/descendants.c \
  $(SRCDIR)/diff.c \
  $(SRCDIR)/diffcmd.c \
................................................................................
  $(SRCDIR)/name.c \
  $(SRCDIR)/pivot.c \
  $(SRCDIR)/pqueue.c \
  $(SRCDIR)/printf.c \
  $(SRCDIR)/rebuild.c \
  $(SRCDIR)/report.c \
  $(SRCDIR)/rss.c \

  $(SRCDIR)/schema.c \
  $(SRCDIR)/search.c \
  $(SRCDIR)/setup.c \
  $(SRCDIR)/sha1.c \
  $(SRCDIR)/shun.c \
  $(SRCDIR)/skins.c \
  $(SRCDIR)/stat.c \
................................................................................
  cgi_.c \
  checkin_.c \
  checkout_.c \
  clearsign_.c \
  clone_.c \
  comformat_.c \
  configure_.c \

  content_.c \
  db_.c \
  delta_.c \
  deltacmd_.c \
  descendants_.c \
  diff_.c \
  diffcmd_.c \
................................................................................
  name_.c \
  pivot_.c \
  pqueue_.c \
  printf_.c \
  rebuild_.c \
  report_.c \
  rss_.c \

  schema_.c \
  search_.c \
  setup_.c \
  sha1_.c \
  shun_.c \
  skins_.c \
  stat_.c \
................................................................................
  cgi.o \
  checkin.o \
  checkout.o \
  clearsign.o \
  clone.o \
  comformat.o \
  configure.o \

  content.o \
  db.o \
  delta.o \
  deltacmd.o \
  descendants.o \
  diff.o \
  diffcmd.o \
................................................................................
  name.o \
  pivot.o \
  pqueue.o \
  printf.o \
  rebuild.o \
  report.o \
  rss.o \

  schema.o \
  search.o \
  setup.o \
  sha1.o \
  shun.o \
  skins.o \
  stat.o \
................................................................................
#
$(SRCDIR)/../manifest:	
	# noop

clean:	
	rm -f *.o *_.c $(APPNAME) VERSION.h
	rm -f translate makeheaders mkindex page_index.h headers
	rm -f add.h allrepo.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h finfo.h http.h http_socket.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h pqueue.h printf.h rebuild.h report.h rss.h schema.h search.h setup.h sha1.h shun.h skins.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h

page_index.h: $(TRANS_SRC) mkindex
	./mkindex $(TRANS_SRC) >$@
headers:	page_index.h makeheaders VERSION.h
	./makeheaders  add_.c:add.h allrepo_.c:allrepo.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h finfo_.c:finfo.h http_.c:http.h http_socket_.c:http_socket.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h
	touch headers
headers: Makefile
Makefile:
add_.c:	$(SRCDIR)/add.c translate
	./translate $(SRCDIR)/add.c >add_.c

add.o:	add_.c add.h  $(SRCDIR)/config.h
................................................................................
configure_.c:	$(SRCDIR)/configure.c translate
	./translate $(SRCDIR)/configure.c >configure_.c

configure.o:	configure_.c configure.h  $(SRCDIR)/config.h
	$(XTCC) -o configure.o -c configure_.c

configure.h:	headers







content_.c:	$(SRCDIR)/content.c translate
	./translate $(SRCDIR)/content.c >content_.c

content.o:	content_.c content.h  $(SRCDIR)/config.h
	$(XTCC) -o content.o -c content_.c

content.h:	headers
................................................................................
rss_.c:	$(SRCDIR)/rss.c translate
	./translate $(SRCDIR)/rss.c >rss_.c

rss.o:	rss_.c rss.h  $(SRCDIR)/config.h
	$(XTCC) -o rss.o -c rss_.c

rss.h:	headers







schema_.c:	$(SRCDIR)/schema.c translate
	./translate $(SRCDIR)/schema.c >schema_.c

schema.o:	schema_.c schema.h  $(SRCDIR)/config.h
	$(XTCC) -o schema.o -c schema_.c

schema.h:	headers

Changes to src/makemake.tcl.

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
  cgi
  checkin
  checkout
  clearsign
  clone
  comformat
  configure
  construct
  content
  db
  delta
  deltacmd
  descendants
  diff
  diffcmd
................................................................................
  name
  pivot
  pqueue
  printf
  rebuild
  report
  rss
  rstats
  schema
  search
  setup
  sha1
  shun
  skins
  stat







<







 







<







17
18
19
20
21
22
23

24
25
26
27
28
29
30
..
45
46
47
48
49
50
51

52
53
54
55
56
57
58
  cgi
  checkin
  checkout
  clearsign
  clone
  comformat
  configure

  content
  db
  delta
  deltacmd
  descendants
  diff
  diffcmd
................................................................................
  name
  pivot
  pqueue
  printf
  rebuild
  report
  rss

  schema
  search
  setup
  sha1
  shun
  skins
  stat

Deleted src/rstats.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
/*
** Copyright (c) 2008 D. Richard Hipp, Kevin Kinnell
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public
** License version 2 as published by the Free Software Foundation.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** General Public License for more details.
** 
** You should have received a copy of the GNU General Public
** License along with this library; if not, write to the
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
** Boston, MA  02111-1307, USA.
**
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
**   kkinnell@megagate.com
**
*******************************************************************************
**
** This file contains code to implement the metrics command.  This is a
** command-line version of the stats page.
**
*/
#include <string.h>
#include "config.h"
#include "rstats.h"

/*
** COMMAND: rstats
**
** Usage: %fossil rstats
**
** Deliver a report of the repository statistics for the
** current checkout.
*/
void rstats_cmd(void){
  i64 t;
  int n, m, fsize, vid;
  char zBuf[100];

  db_must_be_within_tree();
  vid = db_lget_int("checkout",0);
  if( vid==0 ){
    fossil_panic("no checkout");
  }
  fsize = file_size(g.zRepositoryName);
  n = db_int(0, "SELECT count(*) FROM blob");
  m = db_int(0, "SELECT count(*) FROM delta");
  printf(" Number of Artifacts: %d\n", n);
  printf("  %d full text + %d delta blobs\n", (n-m), m);
  if( n>0 ){
    int a, b;
    t = db_int64(0, "SELECT total(size) FROM blob WHERE size>0");
    sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", t);
    if( t/fsize < 5 ){
      b = 10;
      fsize /= 10;
    }else{
      b = 1;
    }
    a = t/fsize;
    printf(" %d bytes average, %s bytes total\n\n",
	   ((int)(((double)t)/(double)n)),
	   (zBuf));
  }
  n = db_int(0, "SELECT count(distinct mid) FROM mlink");
  printf("  Number Of Checkins: %d\n", n);
  n = db_int(0, "SELECT count(*) FROM filename");
  printf("     Number Of Files: %d\n", n);
  n = db_int(0, "SELECT count(*) FROM tag WHERE +tagname GLOB 'wiki-*'");
  printf("Number Of Wiki Pages: %d\n", n);
  n = db_int(0, "SELECT count(*) FROM tag WHERE +tagname GLOB 'tkt-*'");
  printf("   Number Of Tickets: %d\n", n);
  n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event) + 0.99");
  printf(" Duration Of Project: %d days\n", n);
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































Changes to src/setup.c.

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
...
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
  @ <table border="0" cellspacing="20">
  setup_menu_entry("Users", "setup_ulist",
    "Grant privileges to individual users.");
  setup_menu_entry("Access", "setup_access",
    "Control access settings.");
  setup_menu_entry("Configuration", "setup_config",
    "Configure the WWW components of the repository");
  setup_menu_entry("Behavior", "setup_behavior",
    "Configure the SCM behavior of the repository");
  setup_menu_entry("Timeline", "setup_timeline",
    "Timeline display preferences");
  setup_menu_entry("Tickets", "tktsetup",
    "Configure the trouble-ticketing system for this repository");
  setup_menu_entry("Skins", "setup_skin",
    "Select from a menu of prepackaged \"skins\" for the web interface");
  setup_menu_entry("CSS", "setup_editcss",
................................................................................

  @ <hr>
  entry_attribute("Max timeline comment length", 6, 
                  "timeline-max-comment", "tmc", "0");
  @ <p>The maximum length of a comment to be displayed in a timeline.
  @ "0" there is no length limit.</p>

  @ <hr>
  @ <p><input type="submit"  name="submit" value="Apply Changes"></p>
  @ </form>
  db_end_transaction(0);
  style_footer();
}

/*
** WEBPAGE: setup_behavior
*/
void setup_behavior(void){
  login_check_credentials();
  if( !g.okSetup ){
    login_needed();
  }

  style_header("Fossil SCM Behavior");
  db_begin_transaction();
  @ <form action="%s(g.zBaseURL)/setup_behavior" method="POST">
  login_insert_csrf_secret();

  @ <hr>
  onoff_attribute("Automatically synchronize with repository",
                  "autosync", "autosync", 1);
  @ <p>Automatically keeps your work in sync with a centralized server.</p>

  @ <hr>
  onoff_attribute("Show javascript button to fill in CAPTCHA",
                  "auto-captcha", "autocaptcha", 0);
  @ <p>When enabled, a button appears on the login screen for user
  @ "anonymous" that will automatically fill in the CAPTCHA password.
  @ This is less secure that forcing the user to do it manually, but is
  @ probably secure enough and it is certainly more convenient for
  @ anonymous users.</p>

  @ <hr>
  onoff_attribute("Sign all commits with GPG",
                  "clearsign", "clearsign", 1);
  @ <p>When enabled (the default), fossil will attempt to
  @     sign all commits with GPG.  When disabled, commits will
  @    be unsigned.</p>  
  
  @ <hr>
  onoff_attribute("Require local authentication",
                  "localauth", "localauth", 0);
  @ <p>If enabled, require that HTTP connections from
  @         127.0.0.1 be authenticated by password.  If
  @        false, all HTTP requests from localhost have
  @        unrestricted access to the repository.</p>  
  
  @ <hr>
  onoff_attribute("Modification times used to detect changes",
                  "mtime-changes", "mtime-changes", 0);
  @ <p>Use file modification times (mtimes) to detect when files have been modified.</p>  
  
  @ <hr>
  entry_attribute("Diff Command", 16, 
                  "diff-command", "diff-command", "diff");
  @ <p>External command used to generate a textual diff</p>  
  
  @ <hr>
  entry_attribute("Gdiff Command", 16, 
                  "gdiff-command", "gdiff-command", "gdiff");
  @ <p>External command to run when performing a graphical diff. If undefined, text diff will be used.</p>  
    
  @ <hr>
  entry_attribute("Editor", 16, 
                  "editor", "editor", "");
  @ <p>Text editor command used for check-in comments.</p>  
  
  @ <hr>
  entry_attribute("HTTP port", 16, 
                  "http-port", "http-port", "8080");
  @ <p>The TCP/IP port number to use by the "server" and "ui" commands.  Default: 8080</p>  

  @ <hr>
  entry_attribute("PGP Command", 32, 
                  "pgp-command", "pgp-command", "gpg --clearsign -o ");
  @ <p>Command used to clear-sign manifests at check-in.The default is "gpg --clearsign -o ".</p>  
  
  @ <hr>
  entry_attribute("Proxy", 32, 
                  "proxy", "proxy", "off");
  @ <p>URL of the HTTP proxy.</p>  
  
  @ <hr>
  entry_attribute("Web browser", 32, 
                  "web-browser", "web-browser", "");
  @ <p>Default web browser for "fossil ui".</p>  

  @ <hr>
  @ <p><input type="submit"  name="submit" value="Apply Changes"></p>
  @ </form>
  db_end_transaction(0);
  style_footer();
}








<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







62
63
64
65
66
67
68


69
70
71
72
73
74
75
...
791
792
793
794
795
796
797


























































































798
799
800
801
802
803
804
  @ <table border="0" cellspacing="20">
  setup_menu_entry("Users", "setup_ulist",
    "Grant privileges to individual users.");
  setup_menu_entry("Access", "setup_access",
    "Control access settings.");
  setup_menu_entry("Configuration", "setup_config",
    "Configure the WWW components of the repository");


  setup_menu_entry("Timeline", "setup_timeline",
    "Timeline display preferences");
  setup_menu_entry("Tickets", "tktsetup",
    "Configure the trouble-ticketing system for this repository");
  setup_menu_entry("Skins", "setup_skin",
    "Select from a menu of prepackaged \"skins\" for the web interface");
  setup_menu_entry("CSS", "setup_editcss",
................................................................................

  @ <hr>
  entry_attribute("Max timeline comment length", 6, 
                  "timeline-max-comment", "tmc", "0");
  @ <p>The maximum length of a comment to be displayed in a timeline.
  @ "0" there is no length limit.</p>



























































































  @ <hr>
  @ <p><input type="submit"  name="submit" value="Apply Changes"></p>
  @ </form>
  db_end_transaction(0);
  style_footer();
}