Changes On Branch checkin-without-checkout
Not logged in

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

Changes In Branch checkin-without-checkout Excluding Merge-Ins

This is equivalent to a diff from 44ac944a98 to 8d4ce834ed

2020-05-05
04:06
Initial work on ajaxifying /fileedit. Fetching content, preview, and diffs are ajax'd, but save is not yet. check-in: 8edf9dbfc2 user: stephan tags: fileedit-ajaxify
2020-05-04
23:26
Moved some generic fileedit code to style.c. Refactored /fileedit to not require JS to update version info, making this impl pure no-JS. Now to ajaxify it... Closed-Leaf check-in: 8d4ce834ed user: stephan tags: checkin-without-checkout
20:16
Added /fileedit links to /finfo and /artifact. check-in: fe925e7d6d user: stephan tags: checkin-without-checkout
2020-05-03
17:46
Wrap SSL-related features into a FOSSIL_ENABLE_SSL conditional in url.c. check-in: 0a59a82349 user: ashepilko tags: trunk
2020-04-30
16:14
Merged in trunk for related changes. check-in: 03cce1c977 user: stephan tags: checkin-without-checkout
15:29
Add the "forbid-delta-manifests" setting. check-in: 44ac944a98 user: drh tags: trunk
15:00
Fix the file_perm() utility routine so that it actually uses the eFType parameter. check-in: 388b5e5982 user: drh tags: trunk

Changes to src/blob.c.

475
476
477
478
479
480
481












482
483
484
485
486
487
488
** nByte in size.  The blob is truncated if necessary.
*/
void blob_resize(Blob *pBlob, unsigned int newSize){
  pBlob->xRealloc(pBlob, newSize+1);
  pBlob->nUsed = newSize;
  pBlob->aData[newSize] = 0;
}













/*
** Make sure a blob is nul-terminated and is not a pointer to unmanaged
** space.  Return a pointer to the data.
*/
char *blob_materialize(Blob *pBlob){
  blob_resize(pBlob, pBlob->nUsed);







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







475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
** nByte in size.  The blob is truncated if necessary.
*/
void blob_resize(Blob *pBlob, unsigned int newSize){
  pBlob->xRealloc(pBlob, newSize+1);
  pBlob->nUsed = newSize;
  pBlob->aData[newSize] = 0;
}

/*
** Ensures that the given blob has at least the given amount of memory
** allocated to it. Does not modify pBlob->nUsed nor will it reduce
** the currently-allocated amount of memory.
*/
void blob_reserve(Blob *pBlob, unsigned int newSize){
  if(newSize>pBlob->nUsed){
    pBlob->xRealloc(pBlob, newSize);
    pBlob->aData[newSize] = 0;
  }
}

/*
** Make sure a blob is nul-terminated and is not a pointer to unmanaged
** space.  Return a pointer to the data.
*/
char *blob_materialize(Blob *pBlob){
  blob_resize(pBlob, pBlob->nUsed);
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
    blob_reset(&b1);
    blob_reset(&b2);
    blob_reset(&b3);
  }
  fossil_print("ok\n");
}

#if defined(_WIN32) || defined(__CYGWIN__)
/*
** Convert every \n character in the given blob into \r\n.
*/
void blob_add_cr(Blob *p){
  char *z = p->aData;
  int j   = p->nUsed;
  int i, n;







<







1177
1178
1179
1180
1181
1182
1183

1184
1185
1186
1187
1188
1189
1190
    blob_reset(&b1);
    blob_reset(&b2);
    blob_reset(&b3);
  }
  fossil_print("ok\n");
}


/*
** Convert every \n character in the given blob into \r\n.
*/
void blob_add_cr(Blob *p){
  char *z = p->aData;
  int j   = p->nUsed;
  int i, n;
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
  z[j] = 0;
  while( j>i ){
    if( (z[--j] = z[--i]) =='\n' ){
      z[--j] = '\r';
    }
  }
}
#endif

/*
** Remove every \r character from the given blob, replacing each one with
** a \n character if it was not already part of a \r\n pair.
*/
void blob_to_lf_only(Blob *p){
  int i, j;







<







1200
1201
1202
1203
1204
1205
1206

1207
1208
1209
1210
1211
1212
1213
  z[j] = 0;
  while( j>i ){
    if( (z[--j] = z[--i]) =='\n' ){
      z[--j] = '\r';
    }
  }
}


/*
** Remove every \r character from the given blob, replacing each one with
** a \n character if it was not already part of a \r\n pair.
*/
void blob_to_lf_only(Blob *p){
  int i, j;

Changes to src/cgi.c.

62
63
64
65
66
67
68











69
70
71
72
73
74
75
#define PD(x,y)     cgi_parameter((x),(y))
#define PT(x)       cgi_parameter_trimmed((x),0)
#define PDT(x,y)    cgi_parameter_trimmed((x),(y))
#define PB(x)       cgi_parameter_boolean(x)
#define PCK(x)      cgi_parameter_checked(x,1)
#define PIF(x,y)    cgi_parameter_checked(x,y)













/*
** Destinations for output text.
*/
#define CGI_HEADER   0
#define CGI_BODY     1








>
>
>
>
>
>
>
>
>
>
>







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
#define PD(x,y)     cgi_parameter((x),(y))
#define PT(x)       cgi_parameter_trimmed((x),0)
#define PDT(x,y)    cgi_parameter_trimmed((x),(y))
#define PB(x)       cgi_parameter_boolean(x)
#define PCK(x)      cgi_parameter_checked(x,1)
#define PIF(x,y)    cgi_parameter_checked(x,y)

/*
** Shortcut for the cgi_printf() routine.  Instead of using the
**
**    @ ...
**
** notation provided by the translate.c utility, you can also
** optionally use:
**
**    CX(...)
*/
#define CX cgi_printf

/*
** Destinations for output text.
*/
#define CGI_HEADER   0
#define CGI_BODY     1

Changes to src/checkin.c.

1397
1398
1399
1400
1401
1402
1403


















1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427


1428
1429
1430
1431
1432
1433
1434
      g.aCommitFile[jj++] = ii;
    }
    g.aCommitFile[jj] = 0;
    bag_clear(&toCommit);
  }
  return result;
}



















/*
** Make sure the current check-in with timestamp zDate is younger than its
** ancestor identified rid and zUuid.  Throw a fatal error if not.
*/
static void checkin_verify_younger(
  int rid,              /* The record ID of the ancestor */
  const char *zUuid,    /* The artifact ID of the ancestor */
  const char *zDate     /* Date & time of the current check-in */
){
#ifndef FOSSIL_ALLOW_OUT_OF_ORDER_DATES
  int b;
  b = db_exists(
    "SELECT 1 FROM event"
    " WHERE datetime(mtime)>=%Q"
    "   AND type='ci' AND objid=%d",
    zDate, rid
  );
  if( b ){
    fossil_fatal("ancestor check-in [%S] (%s) is not older (clock skew?)"
                 " Use --allow-older to override.", zUuid, zDate);
  }
#endif
}



/*
** zDate should be a valid date string.  Convert this string into the
** format YYYY-MM-DDTHH:MM:SS.  If the string is not a valid date,
** print a fatal error and quit.
*/
char *date_in_standard_format(const char *zInputDate){







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











<
<
<
<
<
|
<
<





>
>







1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432





1433


1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
      g.aCommitFile[jj++] = ii;
    }
    g.aCommitFile[jj] = 0;
    bag_clear(&toCommit);
  }
  return result;
}

/*
** Returns true if the checkin identified by the first parameter is
** older than the given (valid) date/time string, else returns false.
** Also returns true if rid does not refer to a checkin, but it is not
** intended to be used for that case.
*/
int checkin_is_younger(
  int rid,              /* The record ID of the ancestor */
  const char *zDate     /* Date & time of the current check-in */
){
  return db_exists(
    "SELECT 1 FROM event"
    " WHERE datetime(mtime)>=%Q"
    "   AND type='ci' AND objid=%d",
    zDate, rid
  ) ? 0 : 1;
}

/*
** Make sure the current check-in with timestamp zDate is younger than its
** ancestor identified rid and zUuid.  Throw a fatal error if not.
*/
static void checkin_verify_younger(
  int rid,              /* The record ID of the ancestor */
  const char *zUuid,    /* The artifact ID of the ancestor */
  const char *zDate     /* Date & time of the current check-in */
){
#ifndef FOSSIL_ALLOW_OUT_OF_ORDER_DATES





  if(checkin_is_younger(rid,zDate)==0){


    fossil_fatal("ancestor check-in [%S] (%s) is not older (clock skew?)"
                 " Use --allow-older to override.", zUuid, zDate);
  }
#endif
}



/*
** zDate should be a valid date string.  Convert this string into the
** format YYYY-MM-DDTHH:MM:SS.  If the string is not a valid date,
** print a fatal error and quit.
*/
char *date_in_standard_format(const char *zInputDate){
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
  
    /*
    ** Do not allow a commit against a closed leaf unless the commit
    ** ends up on a different branch.
    */
    if(
        /* parent check-in has the "closed" tag... */
        db_exists("SELECT 1 FROM tagxref"
                  " WHERE tagid=%d AND rid=%d AND tagtype>0",
                  TAG_CLOSED, vid)
        /* ... and the new check-in has no --branch option or the --branch
        ** option does not actually change the branch */
     && (sCiInfo.zBranch==0
         || db_exists("SELECT 1 FROM tagxref"
                      " WHERE tagid=%d AND rid=%d AND tagtype>0"
                      "   AND value=%Q", TAG_BRANCH, vid, sCiInfo.zBranch))
    ){







<
<
|







2340
2341
2342
2343
2344
2345
2346


2347
2348
2349
2350
2351
2352
2353
2354
  
    /*
    ** Do not allow a commit against a closed leaf unless the commit
    ** ends up on a different branch.
    */
    if(
        /* parent check-in has the "closed" tag... */


       leaf_is_closed(vid)
        /* ... and the new check-in has no --branch option or the --branch
        ** option does not actually change the branch */
     && (sCiInfo.zBranch==0
         || db_exists("SELECT 1 FROM tagxref"
                      " WHERE tagid=%d AND rid=%d AND tagtype>0"
                      "   AND value=%Q", TAG_BRANCH, vid, sCiInfo.zBranch))
    ){

Changes to src/configure.c.

146
147
148
149
150
151
152

153
154
155
156
157
158
159
  { "dotfiles",               CONFIGSET_PROJ },
  { "parent-project-code",    CONFIGSET_PROJ },
  { "parent-project-name",    CONFIGSET_PROJ },
  { "hash-policy",            CONFIGSET_PROJ },
  { "comment-format",         CONFIGSET_PROJ },
  { "mimetypes",              CONFIGSET_PROJ },
  { "forbid-delta-manifests", CONFIGSET_PROJ },


#ifdef FOSSIL_ENABLE_LEGACY_MV_RM
  { "mv-rm-files",            CONFIGSET_PROJ },
#endif

  { "ticket-table",           CONFIGSET_TKT  },
  { "ticket-common",          CONFIGSET_TKT  },







>







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  { "dotfiles",               CONFIGSET_PROJ },
  { "parent-project-code",    CONFIGSET_PROJ },
  { "parent-project-name",    CONFIGSET_PROJ },
  { "hash-policy",            CONFIGSET_PROJ },
  { "comment-format",         CONFIGSET_PROJ },
  { "mimetypes",              CONFIGSET_PROJ },
  { "forbid-delta-manifests", CONFIGSET_PROJ },
  { "fileedit-glob",          CONFIGSET_PROJ },

#ifdef FOSSIL_ENABLE_LEGACY_MV_RM
  { "mv-rm-files",            CONFIGSET_PROJ },
#endif

  { "ticket-table",           CONFIGSET_TKT  },
  { "ticket-common",          CONFIGSET_TKT  },

Changes to src/db.c.

3407
3408
3409
3410
3411
3412
3413









3414
3415
3416
3417
3418
3419
3420
#if !defined(FOSSIL_ENABLE_EXEC_REL_PATHS)
/*
** SETTING: exec-rel-paths   boolean default=off
** When executing certain external commands (e.g. diff and
** gdiff), use relative paths.
*/
#endif









/*
** SETTING: gdiff-command    width=40 default=gdiff
** The value is an external command to run when performing a graphical
** diff. If undefined, text diff will be used.
*/
/*
** SETTING: gmerge-command   width=40







>
>
>
>
>
>
>
>
>







3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
#if !defined(FOSSIL_ENABLE_EXEC_REL_PATHS)
/*
** SETTING: exec-rel-paths   boolean default=off
** When executing certain external commands (e.g. diff and
** gdiff), use relative paths.
*/
#endif

/*
** SETTING: fileedit-glob       width=40 block-text
** A comma- or newline-separated list of globs of filenames
** which are allowed to be edited using the /fileedit page.
** An empty list prohibits editing via that page. Note that
** it cannot edit binary files, so the glob should not
** contain any globs for, e.g., images or PDFs.
*/
/*
** SETTING: gdiff-command    width=40 default=gdiff
** The value is an external command to run when performing a graphical
** diff. If undefined, text diff will be used.
*/
/*
** SETTING: gmerge-command   width=40

Changes to src/default_css.txt.

858
859
860
861
862
863
864




























































































//   border: 1px solid black;
//   vertical-align: top;
// }
// #setup_skinedit_css_defaults > tbody > tr > td:nth-of-type(2) > div {
//   max-width: 30em;
//   overflow: auto;
// }



































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
//   border: 1px solid black;
//   vertical-align: top;
// }
// #setup_skinedit_css_defaults > tbody > tr > td:nth-of-type(2) > div {
//   max-width: 30em;
//   overflow: auto;
// }
// .fileedit-XXX => /fileedit page
form.fileedit textarea {
  font-family: monospace;
  width: 100%;
}
form.fileedit fieldset {
  margin: 0.5em 0 0 0;
  border-radius: 0.5em;
  border-color: inherit;
  border-width: 1px;
}
form.fileedit fieldset > legend {
  margin: 0 0 0 1em;
  padding: 0 0.5em 0 0.5em;
}
form.fileedit fieldset > div {
  margin: 0 0.25em 0.25em 0.25em;
}
form.fileedit fieldset > div > .input-with-label {
  margin: 0.25em 0.5em;
}
form.fileedit fieldset > div > button {
  margin: 0.25em 0.5em;
}
form.fileedit input:invalid {
  border-left: 0.2em dashed red;
}
.fileedit-hint {
  font-size: 80%;
  opacity: 0.75;
}
.fileedit-error-report {
  background: yellow;
  color: darkred;
  margin: 1em 0;
  padding: 0.5em;
  border-radius: 0.5em;
}
code.fileedit-manifest {
  display: block;
  height: 16em;
  overflow: auto;
}
div.fileedit-preview {
  margin: 0;
  padding: 0;
}
.fileedit-preview > div:first-child {
  margin: 1em 0 0 0;
  border-bottom: 1px dashed;
}
div.fileedit-diff {
  margin: 0;
  padding: 0;
}
.fileedit-diff > div:first-child {
  border-bottom: 1px dashed;
}

.input-with-label {
  border: 1px inset #808080;
  border-radius: 0.5em;
  padding: 0.25em 0.4em;
  margin: 0 0.5em;
  display: inline-block;
  cursor: pointer;
}
.input-with-label > * {
  vertical-align: middle;
}
.input-with-label > input {
    margin: 0;
}
.input-with-label > select {
  margin: 0;
}
.input-with-label > input[type=text] {
  margin: 0;
}
.input-with-label > textarea {
  margin: 0;
}
.input-with-label > input[type=checkbox] {
    vertical-align: sub;
}
.input-with-label > input[type=radio] {
    vertical-align: sub;
}
.input-with-label > span {
    margin: 0 0.25em 0 0.25em;
    vertical-align: middle;
}

Added src/fileedit.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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
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
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
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
484
485
486
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
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
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
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
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
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
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
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
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
/*
** Copyright (c) 2020 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
**
** 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.
**
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This file contains code for the /fileedit page and related code.
*/
#include "config.h"
#include "fileedit.h"
#include <assert.h>
#include <stdarg.h>

/*
** State for the "mini-checkin" infrastructure, which enables the
** ability to commit changes to a single file without a checkout
** db, e.g. for use via an HTTP request.
**
** Use CheckinMiniInfo_init() to cleanly initialize one to a known
** valid/empty default state.
**
** Memory for all non-const (char *) members is owned by the
** CheckinMiniInfo instance and is freed by CheckinMiniInfo_cleanup().
*/
struct CheckinMiniInfo {
  Manifest * pParent;  /* parent checkin. Memory is owned by this
                          object. */
  char *zParentUuid;   /* Full UUID of pParent */
  char *zFilename;     /* Name of single file to commit. Must be
                          relative to the top of the repo. */
  Blob fileContent;    /* Content of file referred to by zFilename. */
  Blob fileHash;       /* Hash of this->fileContent, using the repo's
                          preferred hash method. */
  Blob comment;        /* Check-in comment text */
  char *zCommentMimetype;  /* Mimetype of comment. May be NULL */
  char *zUser;         /* User name */
  char *zDate;         /* Optionally force this date string (anything
                          supported by date_in_standard_format()).
                          Maybe be NULL. */
  Blob *pMfOut;        /* If not NULL, checkin_mini() will write a
                          copy of the generated manifest here. This
                          memory is NOT owned by CheckinMiniInfo. */
  int filePerm;        /* Permissions (via file_perm()) of the input
                          file. We need to store this before calling
                          checkin_mini() because the real input file
                          name may differ from the repo-centric
                          this->zFilename, and checkin_mini() requires
                          the permissions of the original file. For
                          web commits, set this to PERM_REG or (when
                          editing executable scripts) PERM_EXE before
                          calling checkin_mini(). */
  int flags;           /* Bitmask of fossil_cimini_flags. */
};
typedef struct CheckinMiniInfo CheckinMiniInfo;

/*
** CheckinMiniInfo::flags values.
*/
enum fossil_cimini_flags {
CIMINI_NONE = 0,
/*
** Tells checkin_mini() to use dry-run mode.
*/
CIMINI_DRY_RUN = 1,
/*
** Tells checkin_mini() to allow forking from a non-leaf commit.
*/
CIMINI_ALLOW_FORK = 1<<1,
/*
** Tells checkin_mini() to dump its generated manifest to stdout.
*/
CIMINI_DUMP_MANIFEST = 1<<2,

/*
** By default, content containing what appears to be a merge conflict
** marker is not permitted. This flag relaxes that requirement.
*/
CIMINI_ALLOW_MERGE_MARKER = 1<<3,

/*
** By default mini-checkins are not allowed to be "older"
** than their parent. i.e. they may not have a timestamp
** which predates their parent. This flag bypasses that
** check.
*/
CIMINI_ALLOW_OLDER = 1<<4,

/*
** Indicates that the content of the newly-checked-in file is
** converted, if needed, to use the same EOL style as the previous
** version of that file. Only the in-memory/in-repo copies are
** affected, not the original file (if any).
*/
CIMINI_CONVERT_EOL_INHERIT = 1<<5,
/*
** Indicates that the input's EOLs should be converted to Unix-style.
*/
CIMINI_CONVERT_EOL_UNIX = 1<<6,
/*
** Indicates that the input's EOLs should be converted to Windows-style.
*/
CIMINI_CONVERT_EOL_WINDOWS = 1<<7,
/*
** A hint to checkin_mini() to "prefer" creation of a delta manifest.
** It may decide not to for various reasons.
*/
CIMINI_PREFER_DELTA = 1<<8,
/*
** A "stronger hint" to checkin_mini() to prefer creation of a delta
** manifest if it at all can. It will decide not to only if creation
** of a delta is not a realistic option. For this to work, it must be
** set together with the CIMINI_PREFER_DELTA flag, but the two cannot
** be combined in this enum.
**
** This option is ONLY INTENDED FOR TESTING, used in bypassing
** heuristics which may otherwise disable generation of a delta on the
** grounds of efficiency (e.g. not generating a delta if the parent
** non-delta only has a few F-cards).
**
** The forbid-delta-manifests repo config option trumps this.
*/
CIMINI_STRONGLY_PREFER_DELTA = 1<<9,
/*
** Tells checkin_mini() to permit the addition of a new file. Normally
** this is disabled because there are many cases where it could cause
** the inadvertent addition of a new file when an update to an
** existing was intended, as a side-effect of name-case differences.
*/
CIMINI_ALLOW_NEW_FILE = 1<<10
};

/*
** Initializes p to a known-valid default state.
*/
static void CheckinMiniInfo_init( CheckinMiniInfo * p ){
  memset(p, 0, sizeof(CheckinMiniInfo));
  p->flags = CIMINI_NONE;
  p->filePerm = -1;
  p->comment = p->fileContent = p->fileHash = empty_blob;
}

/*
** Frees all memory owned by p, but does not free p.
 */
static void CheckinMiniInfo_cleanup( CheckinMiniInfo * p ){
  blob_reset(&p->comment);
  blob_reset(&p->fileContent);
  blob_reset(&p->fileHash);
  if(p->pParent){
    manifest_destroy(p->pParent);
  }
  fossil_free(p->zFilename);
  fossil_free(p->zDate);
  fossil_free(p->zParentUuid);
  fossil_free(p->zCommentMimetype);
  fossil_free(p->zUser);
  CheckinMiniInfo_init(p);
}

/*
** Internal helper which returns an F-card perms string suitable for
** writing into a manifest.
*/
static const char * mfile_permint_mstring(int perm){
  switch(perm){
    case PERM_EXE: return " x";
    case PERM_LNK: return " l";
    default: return "";
  }
}

/*
** Given a ManifestFile permission string (or NULL), it returns one of
** PERM_REG, PERM_EXE, or PERM_LNK.
*/
static int mfile_permstr_int(const char *zPerm){
  if(!zPerm || !*zPerm) return PERM_REG;
  else if(strstr(zPerm,"x")) return PERM_EXE;
  else if(strstr(zPerm,"l")) return PERM_LNK;
  else return PERM_REG/*???*/;
}

static const char * mfile_perm_mstring(const ManifestFile * p){
  return mfile_permint_mstring(manifest_file_mperm(p));
}

/*
** Internal helper for checkin_mini() and friends. Appends an F-card
** for p to pOut.
*/
static void checkin_mini_append_fcard(Blob *pOut, const ManifestFile *p){
  if(p->zUuid){
    assert(*p->zUuid);
    blob_appendf(pOut, "F %F %s%s", p->zName,
                 p->zUuid, mfile_perm_mstring(p));
    if(p->zPrior){
      assert(*p->zPrior);
      blob_appendf(pOut, " %F\n", p->zPrior);
    }else{
      blob_append(pOut, "\n", 1);
    }
  }else{
    /* File was removed from parent delta. */
    blob_appendf(pOut, "F %F\n", p->zName);
  }
}
/*
** Handles the F-card parts for create_manifest_mini().
**
** If asDelta is true, F-cards will be handled as for a delta
** manifest, and the caller MUST have added a B-card to pOut before
** calling this.
**
** Returns 1 on success, 0 on error, and writes any error message to
** pErr (if it's not NULL). The only non-immediately-fatal/panic error
** is if pCI->filePerm is PERM_LNK or pCI would update a PERM_LNK
** in-repo file.
*/
static int create_manifest_mini_fcards( Blob * pOut,
                                        CheckinMiniInfo * pCI,
                                        int asDelta,
                                        Blob * pErr){
  int wroteThisCard = 0;
  const ManifestFile * pFile;
  int (*fncmp)(char const *, char const *) =  /* filename comparator */
    filenames_are_case_sensitive()
    ? fossil_strcmp
    : fossil_stricmp;
#define mf_err(EXPR) if(pErr) blob_appendf EXPR; return 0
#define write_this_card(NAME) \
  blob_appendf(pOut, "F %F %b%s\n", (NAME), &pCI->fileHash, \
               mfile_permint_mstring(pCI->filePerm)); \
  wroteThisCard = 1

  assert(pCI->filePerm!=PERM_LNK && "This should have been validated before.");
  assert(pCI->filePerm==PERM_REG || pCI->filePerm==PERM_EXE);
  if(PERM_LNK==pCI->filePerm){
    goto err_no_symlink;
  }
  manifest_file_rewind(pCI->pParent);
  if(asDelta!=0 && (pCI->pParent->zBaseline==0
                    || pCI->pParent->nFile==0)){
    /* Parent is a baseline or a delta with no F-cards, so this is
    ** the simplest case: create a delta with a single F-card.
    */
    pFile = manifest_file_find(pCI->pParent, pCI->zFilename);
    if(pFile!=0 && manifest_file_mperm(pFile)==PERM_LNK){
      goto err_no_symlink;
    }
    write_this_card(pFile ? pFile->zName : pCI->zFilename);
    return 1;
  }
  while(1){
    int cmp;
    if(asDelta==0){
      pFile = manifest_file_next(pCI->pParent, 0);
    }else{
      /* Parent is a delta manifest with F-cards. Traversal of delta
      ** manifest file entries is normally done via
      ** manifest_file_next(), which takes into account the
      ** differences between the delta and its parent and returns
      ** F-cards from both. Each successive delta from the same
      ** baseline includes all F-card changes from the previous
      ** deltas, so we instead clone the parent's F-cards except for
      ** the one (if any) which matches the new file.
      */
      pFile = pCI->pParent->iFile < pCI->pParent->nFile
        ? &pCI->pParent->aFile[pCI->pParent->iFile++]
        : 0;
    }
    if(0==pFile) break;
    cmp = fncmp(pFile->zName, pCI->zFilename);
    if(cmp<0){
      checkin_mini_append_fcard(pOut,pFile);
    }else{
      if(cmp==0 || 0==wroteThisCard){
        assert(0==wroteThisCard);
        if(PERM_LNK==manifest_file_mperm(pFile)){
          goto err_no_symlink;
        }
        write_this_card(cmp==0 ? pFile->zName : pCI->zFilename);
      }
      if(cmp>0){
        assert(wroteThisCard!=0);
        checkin_mini_append_fcard(pOut,pFile);
      }
    }
  }
  if(wroteThisCard==0){
    write_this_card(pCI->zFilename);
  }
  return 1;
err_no_symlink:
  mf_err((pErr,"Cannot commit or overwrite symlinks "
          "via mini-checkin."));
  return 0;
#undef write_this_card
#undef mf_err
}

/*
** Creates a manifest file, written to pOut, from the state in the
** fully-populated and semantically valid pCI argument. pCI is not
** *semantically* modified but cannot be const because blob_str() may
** need to NUL-terminate any given blob.
**
** Returns true on success. On error, returns 0 and, if pErr is not
** NULL, writes an error message there.
**
** Intended only to be called via checkin_mini() or routines which
** have already completely vetted pCI.
*/
static int create_manifest_mini( Blob * pOut, CheckinMiniInfo * pCI,
                                 Blob * pErr){
  Blob zCard = empty_blob;     /* Z-card checksum */
  int asDelta = 0;
#define mf_err(EXPR) if(pErr) blob_appendf EXPR; return 0

  assert(blob_str(&pCI->fileHash));
  assert(pCI->pParent);
  assert(pCI->zFilename);
  assert(pCI->zUser);
  assert(pCI->zDate);

  /* Potential TODOs include...
  **
  ** - Maybe add support for tags. Those can be edited via /info page,
  **   and feel like YAGNI/feature creep for this purpose.
  */
  blob_zero(pOut);
  manifest_file_rewind(pCI->pParent) /* force load of baseline */;
  /* Determine whether we want to create a delta manifest... */
  if((CIMINI_PREFER_DELTA & pCI->flags)
     && ((CIMINI_STRONGLY_PREFER_DELTA & pCI->flags)
         || (pCI->pParent->pBaseline
             ? pCI->pParent->pBaseline
             : pCI->pParent)->nFile > 15
         /* 15 is arbitrary: don't create a delta when there is only a
         ** tiny gain for doing so. That heuristic is not *quite*
         ** right, in that when we're deriving from another delta, we
         ** really should compare the F-card count between it and its
         ** baseline, and create a delta if the baseline has (say)
         ** twice or more as many F-cards as the previous delta. */)
     && !db_get_boolean("forbid-delta-manifests",0)
     ){
    asDelta = 1;
    blob_appendf(pOut, "B %s\n",
                 pCI->pParent->zBaseline
                 ? pCI->pParent->zBaseline
                 : pCI->zParentUuid);
  }
  blob_reserve(pOut, 1024 *
               (asDelta ? 2 : pCI->pParent->nFile/11+1
                /* In the fossil core repo, each 12-ish F-cards (on
                ** average) take up roughly 1kb */));
  if(blob_size(&pCI->comment)!=0){
    blob_appendf(pOut, "C %F\n", blob_str(&pCI->comment));
  }else{
    blob_append(pOut, "C (no\\scomment)\n", 16);
  }
  blob_appendf(pOut, "D %s\n", pCI->zDate);
  if(create_manifest_mini_fcards(pOut,pCI,asDelta,pErr)==0){
    return 0;
  }
  if(pCI->zCommentMimetype!=0 && pCI->zCommentMimetype[0]!=0){
    blob_appendf(pOut, "N %F\n", pCI->zCommentMimetype);
  }
  blob_appendf(pOut, "P %s\n", pCI->zParentUuid);
  blob_appendf(pOut, "U %F\n", pCI->zUser);
  md5sum_blob(pOut, &zCard);
  blob_appendf(pOut, "Z %b\n", &zCard);
  blob_reset(&zCard);
  return 1;
#undef mf_err
}

/*
** EXPERIMENTAL! Subject to change or removal at any time.
**
** A so-called "single-file/mini/web checkin" is a slimmed-down form
** of the checkin command which accepts only a single file and is
** intended to accept edits to a file via the web interface or from
** the CLI from outside of a checkout.
**
** Being fully non-interactive is a requirement for this function,
** thus it cannot perform autosync or similar activities.
**
** This routine uses the state from the given fully-populated pCI
** argument to add pCI->fileContent to the database, and create and
** save a manifest for that change. Ownership of pCI and its contents
** are unchanged.
**
** This function may may modify pCI as follows:
**
** - If one of Manifest pCI->pParent or pCI->zParentUuid are NULL,
**   then the other will be assigned based on its counterpart. Both
**   may not be NULL.
**
** - pCI->zDate is normalized to/replaced with a valid date/time
**   string. If its original value cannot be validated then
**   this function fails. If pCI->zDate is NULL, the current time
**   is used.
**
** - If the CIMINI_CONVERT_EOL_INHERIT flag is set,
**   pCI->fileContent appears to be plain text, and its line-ending
**   style differs from its previous version, it is converted to the
**   same EOL style as the previous version. If this is done, the
**   pCI->fileHash is re-computed. Note that only pCI->fileContent,
**   not the original file, is affected by the conversion.
**
** - If pCI->fileHash is empty, this routine populates it with the
**   repository's preferred hash algorithm.
**
** - pCI->comment may be converted to Unix-style newlines.
**
** pCI's ownership is not modified.
**
** This function validates several of the inputs and fails if any
** validation fails.
**
** On error, returns false (0) and, if pErr is not NULL, writes a
** diagnostic message there.
** 
** Returns true on success. If pRid is not NULL, the RID of the
** resulting manifest is written to *pRid.
**
** The checkin process is largely influenced by pCI->flags, and that
** must be populated before calling this. See the fossil_cimini_flags
** enum for the docs for each flag.
*/
static int checkin_mini(CheckinMiniInfo * pCI, int *pRid, Blob * pErr){
  Blob mf = empty_blob;             /* output manifest */
  int rid = 0, frid = 0;            /* various RIDs */
  int isPrivate;                    /* whether this is private content
                                       or not */
  ManifestFile * zFilePrev;         /* file entry from pCI->pParent */
  int prevFRid = 0;                 /* RID of file's prev. version */
#define ci_err(EXPR) if(pErr!=0){blob_appendf EXPR;} goto ci_error

  if(!(pCI->flags & CIMINI_DRY_RUN)){
    /* Until this feature is fully vetted, disallow it in the main
    ** fossil repo unless dry-run mode is being used. */
    char * zProjCode = db_get("project-code",0);
    assert(zProjCode);
    if(0==fossil_stricmp("CE59BB9F186226D80E49D1FA2DB29F935CCA0333",
                         zProjCode)){
      fossil_fatal("Never, ever run this in/on the core fossil repo "
                   "in non-dry-run mode until it's been well-vetted. "
                   "Use a temp/test repo.");
    }
    fossil_free(zProjCode);
  }
  db_begin_transaction();

  if(pCI->pParent==0 && pCI->zParentUuid==0){
    ci_err((pErr, "Cannot determine parent version."));
  }
  else if(pCI->pParent==0){
    pCI->pParent = manifest_get_by_name(pCI->zParentUuid, 0);
    if(pCI->pParent==0){
      ci_err((pErr,"Cannot load manifest for [%S].", pCI->zParentUuid));
    }
  }else if(pCI->zParentUuid==0){
    pCI->zParentUuid = rid_to_uuid(pCI->pParent->rid);
    assert(pCI->zParentUuid);
  }

  assert(pCI->pParent->rid>0);
  if(leaf_is_closed(pCI->pParent->rid)){
    ci_err((pErr,"Cannot commit to a closed leaf."));
    /* Remember that in order to override this we'd also need to
    ** cancel TAG_CLOSED on pCI->pParent. There would seem to be no
    ** reason we can't do that via the generated manifest, but the
    ** commit command does not offer that option, so mini-checkin
    ** probably shouldn't, either.
    */
  }
  if( !db_exists("SELECT 1 FROM user WHERE login=%Q", pCI->zUser) ){
    ci_err((pErr,"No such user: %s", pCI->zUser));
  }
  if(!(CIMINI_ALLOW_FORK & pCI->flags)
     && !is_a_leaf(pCI->pParent->rid)){
    ci_err((pErr,"Parent [%S] is not a leaf and forking is disabled.",
            pCI->zParentUuid));
  }
  if(!(CIMINI_ALLOW_MERGE_MARKER & pCI->flags)
     && contains_merge_marker(&pCI->fileContent)){
    ci_err((pErr,"Content appears to contain a merge conflict marker."));
  }
  if(!file_is_simple_pathname(pCI->zFilename, 1)){
    ci_err((pErr,"Invalid filename for use in a repository: %s",
            pCI->zFilename));
  }
  if(!(CIMINI_ALLOW_OLDER & pCI->flags)
     && !checkin_is_younger(pCI->pParent->rid, pCI->zDate)){
    ci_err((pErr,"Checkin time (%s) may not be older "
            "than its parent (%z).",
            pCI->zDate,
            db_text(0, "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%f',%lf)",
                    pCI->pParent->rDate)
            ));
  }
  {
    /*
    ** Normalize the timestamp. We don't use date_in_standard_format()
    ** because that has side-effects we don't want to trigger here.
    */
    char * zDVal = db_text(
         0, "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%f',%Q)",
         pCI->zDate ? pCI->zDate : "now");
    if(zDVal==0 || zDVal[0]==0){
      fossil_free(zDVal);
      ci_err((pErr,"Invalid timestamp string: %s", pCI->zDate));
    }
    fossil_free(pCI->zDate);
    pCI->zDate = zDVal;
  }
  { /* Confirm that only one EOL policy is in place. */
    int n = 0;
    if(CIMINI_CONVERT_EOL_INHERIT & pCI->flags) ++n;
    if(CIMINI_CONVERT_EOL_UNIX & pCI->flags) ++n;
    if(CIMINI_CONVERT_EOL_WINDOWS & pCI->flags) ++n;
    if(n>1){
      ci_err((pErr,"More than 1 EOL conversion policy was specified."));
    }
  }
  /* Potential TODOs include:
  **
  ** - Commit allows an empty checkin only with a flag, but we
  **   currently disallow it entirely. Conform with commit?
  **
  ** Non-TODOs:
  **
  ** - Check for a commit lock would require auto-sync, which this
  **   code cannot do if it's going to be run via a web page.
  */

  /*
  ** Confirm that pCI->zFilename can be found in pCI->pParent.  If
  ** not, fail unless the CIMINI_ALLOW_NEW_FILE flag is set. This is
  ** admittedly an artificial limitation, not strictly necessary. We
  ** do it to hopefully reduce the chance of an "oops" where file
  ** X/Y/z gets committed as X/Y/Z or X/y/z due to a typo or
  ** case-sensitivity mismatch between the user/repo/filesystem, or
  ** some such.
  */
  manifest_file_rewind(pCI->pParent);
  zFilePrev = manifest_file_find(pCI->pParent, pCI->zFilename);
  if(!(CIMINI_ALLOW_NEW_FILE & pCI->flags)
     && (!zFilePrev
         || !zFilePrev->zUuid/*was removed from parent delta manifest*/)
     ){
    ci_err((pErr,"File [%s] not found in manifest [%S]. "
            "Adding new files is currently not permitted.",
            pCI->zFilename, pCI->zParentUuid));
  }else if(zFilePrev
           && manifest_file_mperm(zFilePrev)==PERM_LNK){
    ci_err((pErr,"Cannot save a symlink via a mini-checkin."));
  }
  if(zFilePrev){
    prevFRid = fast_uuid_to_rid(zFilePrev->zUuid);
  }

  if(((CIMINI_CONVERT_EOL_INHERIT & pCI->flags)
      || (CIMINI_CONVERT_EOL_UNIX & pCI->flags)
      || (CIMINI_CONVERT_EOL_WINDOWS & pCI->flags))
     && blob_size(&pCI->fileContent)>0
     ){
    /* Convert to the requested EOL style. Note that this inherently
    ** runs a risk of breaking content, e.g. string literals which
    ** contain embedded newlines. Note that HTML5 specifies that
    ** form-submitted TEXTAREA content gets normalized to CRLF-style:
    **
    ** https://html.spec.whatwg.org/multipage/form-elements.html#the-textarea-element
    */
    const int pseudoBinary = LOOK_LONG | LOOK_NUL;
    const int lookFlags = LOOK_CRLF | pseudoBinary;
    const int lookNew = looks_like_utf8( &pCI->fileContent, lookFlags );
    if(!(pseudoBinary & lookNew)){
      int rehash = 0;
      if(CIMINI_CONVERT_EOL_INHERIT & pCI->flags){
        Blob contentPrev = empty_blob;
        int lookOrig, nOrig;
        content_get(prevFRid, &contentPrev);
        lookOrig = looks_like_utf8(&contentPrev, lookFlags);
        nOrig = blob_size(&contentPrev);
        blob_reset(&contentPrev);
        if(nOrig>0 && lookOrig!=lookNew){
          /* If there is a newline-style mismatch, adjust the new
          ** content version to the previous style, then re-hash the
          ** content. Note that this means that what we insert is NOT
          ** what's in the filesystem.
          */
          if(!(lookOrig & LOOK_CRLF) && (lookNew & LOOK_CRLF)){
            /* Old has Unix-style, new has Windows-style. */
            blob_to_lf_only(&pCI->fileContent);
            rehash = 1;
          }else if((lookOrig & LOOK_CRLF) && !(lookNew & LOOK_CRLF)){
            /* Old has Windows-style, new has Unix-style. */
            blob_add_cr(&pCI->fileContent);
            rehash = 1;
          }
        }
      }else{
        const int oldSize = blob_size(&pCI->fileContent);
        if(CIMINI_CONVERT_EOL_UNIX & pCI->flags){
          blob_to_lf_only(&pCI->fileContent);
        }else{
          assert(CIMINI_CONVERT_EOL_WINDOWS & pCI->flags);
          blob_add_cr(&pCI->fileContent);
        }
        if(blob_size(&pCI->fileContent)!=oldSize){
          rehash = 1;
        }
      }
      if(rehash!=0){
        hname_hash(&pCI->fileContent, 0, &pCI->fileHash);
      }
    }
  }/* end EOL conversion */

  if(blob_size(&pCI->fileHash)==0){
    /* Hash the content if it's not done already... */
    hname_hash(&pCI->fileContent, 0, &pCI->fileHash);
    assert(blob_size(&pCI->fileHash)>0);
  }
  if(zFilePrev){
    /* Has this file been changed since its previous commit?  Note
    ** that we have to delay this check until after the potentially
    ** expensive EOL conversion. */
    assert(blob_size(&pCI->fileHash));
    if(0==fossil_strcmp(zFilePrev->zUuid, blob_str(&pCI->fileHash))
       && manifest_file_mperm(zFilePrev)==pCI->filePerm){
      ci_err((pErr,"File is unchanged. Not saving."));
    }
  }
#if 1
  /* Do we really want to normalize comment EOLs? Web-posting will
  ** submit them in CRLF format. */
  blob_to_lf_only(&pCI->comment);
#endif
  /* Create, save, deltify, and crosslink the manifest... */
  if(create_manifest_mini(&mf, pCI, pErr)==0){
    return 0;
  }
  isPrivate = content_is_private(pCI->pParent->rid);
  rid = content_put_ex(&mf, 0, 0, 0, isPrivate);
  if(pCI->flags & CIMINI_DUMP_MANIFEST){
    fossil_print("%b", &mf);
  }
  if(pCI->pMfOut!=0){
    /* Cross-linking clears mf, so we have to copy it,
    ** instead of taking over its memory. */
    blob_reset(pCI->pMfOut);
    blob_append(pCI->pMfOut, blob_buffer(&mf), blob_size(&mf));
  }
  content_deltify(rid, &pCI->pParent->rid, 1, 0);
  manifest_crosslink(rid, &mf, 0);
  blob_reset(&mf);
  /* Save and deltify the file content... */
  frid = content_put_ex(&pCI->fileContent, blob_str(&pCI->fileHash),
                        0, 0, isPrivate);
  if(zFilePrev!=0){
    assert(prevFRid>0);
    content_deltify(frid, &prevFRid, 1, 0);
  }
  db_end_transaction((CIMINI_DRY_RUN & pCI->flags) ? 1 : 0);
  if(pRid!=0){
    *pRid = rid;
  }
  return 1;
ci_error:
  assert(db_transaction_nesting_depth()>0);
  db_end_transaction(1);
  return 0;
#undef ci_err
}

/*
** COMMAND: test-ci-mini
**
** This is an on-going experiment, subject to change or removal at
** any time.
**
** Usage: %fossil test-ci-mini ?OPTIONS? FILENAME
**
** where FILENAME is a repo-relative name as it would appear in the
** vfile table.
**
** Options:
**
**   --repository|-R REPO      The repository file to commit to.
**   --as FILENAME             The repository-side name of the input
**                             file, relative to the top of the
**                             repository. Default is the same as the
**                             input file name.
**   --comment|-m COMMENT      Required checkin comment.
**   --comment-file|-M FILE    Reads checkin comment from the given file.
**   --revision|-r VERSION     Commit from this version. Default is
**                             the checkout version (if available) or
**                             trunk (if used without a checkout).
**   --allow-fork              Allows the commit to be made against a
**                             non-leaf parent. Note that no autosync
**                             is performed beforehand.
**   --allow-merge-conflict    Allows checkin of a file even if it
**                             appears to contain a fossil merge conflict
**                             marker.
**   --user-override USER      USER to use instead of the current
**                             default.
**   --date-override DATETIME  DATE to use instead of 'now'.
**   --allow-older             Allow a commit to be older than its
**                             ancestor.
**   --convert-eol             Convert EOL style of the checkin to match
**                             the previous version's content. Does not
**                             modify the input file, only the checked-in
**                             content.
**   --delta                   Prefer to generate a delta manifest, if
**                             able. The forbid-delta-manifests repo
**                             config option trumps this, as do certain
**                             heuristics.
**   --allow-new-file          Allow addition of a new file this way.
**                             Disabled by default to avoid that case-
**                             sensitivity errors inadvertently lead to
**                             adding a new file where an update is
**                             intended.
**   --dump-manifest|-d        Dumps the generated manifest to stdout
**                             immediately after it's generated.
**   --save-manifest FILE      Saves the generated manifest to a file
**                             after successfully processing it.
**   --wet-run                 Disables the default dry-run mode.
**
** Example:
**
** %fossil test-ci-mini -R REPO -m ... -r foo --as src/myfile.c myfile.c
**
*/
void test_ci_mini_cmd(){
  CheckinMiniInfo cimi;       /* checkin state */
  int newRid = 0;                /* RID of new version */
  const char * zFilename;        /* argv[2] */
  const char * zComment;         /* -m comment */
  const char * zCommentFile;     /* -M FILE */
  const char * zAsFilename;      /* --as filename */
  const char * zRevision;        /* --revision|-r [=trunk|checkout] */
  const char * zUser;            /* --user-override */
  const char * zDate;            /* --date-override */
  char const * zManifestFile = 0;/* --save-manifest FILE */

  /* This function should perform only the minimal "business logic" it
  ** needs in order to fully/properly populate the CheckinMiniInfo and
  ** then pass it on to checkin_mini() to do most of the validation
  ** and work. The point of this is to avoid duplicate code when a web
  ** front-end is added for checkin_mini().
  */
  CheckinMiniInfo_init(&cimi);
  zComment = find_option("comment","m",1);
  zCommentFile = find_option("comment-file","M",1);
  zAsFilename = find_option("as",0,1);
  zRevision = find_option("revision","r",1);
  zUser = find_option("user-override",0,1);
  zDate = find_option("date-override",0,1);
  zManifestFile = find_option("save-manifest",0,1);
  if(find_option("wet-run",0,0)==0){
    cimi.flags |= CIMINI_DRY_RUN;
  }
  if(find_option("allow-fork",0,0)!=0){
    cimi.flags |= CIMINI_ALLOW_FORK;
  }
  if(find_option("dump-manifest","d",0)!=0){
    cimi.flags |= CIMINI_DUMP_MANIFEST;
  }
  if(find_option("allow-merge-conflict",0,0)!=0){
    cimi.flags |= CIMINI_ALLOW_MERGE_MARKER;
  }
  if(find_option("allow-older",0,0)!=0){
    cimi.flags |= CIMINI_ALLOW_OLDER;
  }
  if(find_option("convert-eol-prev",0,0)!=0){
    cimi.flags |= CIMINI_CONVERT_EOL_INHERIT;
  }
  if(find_option("delta",0,0)!=0){
    cimi.flags |= CIMINI_PREFER_DELTA;
  }
  if(find_option("delta2",0,0)!=0){
    /* Undocumented. For testing only. */
    cimi.flags |= CIMINI_PREFER_DELTA | CIMINI_STRONGLY_PREFER_DELTA;
  }
  if(find_option("allow-new-file",0,0)!=0){
    cimi.flags |= CIMINI_ALLOW_NEW_FILE;
  }
  db_find_and_open_repository(0, 0);
  verify_all_options();
  user_select();
  if(g.argc!=3){
    usage("INFILE");
  }
  if(zComment && zCommentFile){
    fossil_fatal("Only one of -m or -M, not both, may be used.");
  }else{
    if(zCommentFile && *zCommentFile){
      blob_read_from_file(&cimi.comment, zCommentFile, ExtFILE);
    }else if(zComment && *zComment){
      blob_append(&cimi.comment, zComment, -1);
    }
    if(!blob_size(&cimi.comment)){
      fossil_fatal("Non-empty checkin comment is required.");
    }
  }
  db_begin_transaction();
  zFilename = g.argv[2];
  cimi.zFilename = mprintf("%/", zAsFilename ? zAsFilename : zFilename);
  cimi.filePerm = file_perm(zFilename, ExtFILE);
  cimi.zUser = mprintf("%s", zUser ? zUser : login_name());
  if(zDate){
    cimi.zDate = mprintf("%s", zDate);
  }
  if(zRevision==0 || zRevision[0]==0){
    if(g.localOpen/*checkout*/){
      zRevision = db_lget("checkout-hash", 0)/*leak*/;
    }else{
      zRevision = "trunk";
    }
  }
  name_to_uuid2(zRevision, "ci", &cimi.zParentUuid);
  if(cimi.zParentUuid==0){
    fossil_fatal("Cannot determine version to commit to.");
  }
  blob_read_from_file(&cimi.fileContent, zFilename, ExtFILE);
  {
    Blob theManifest = empty_blob; /* --save-manifest target */
    Blob errMsg = empty_blob;
    int rc;
    if(zManifestFile){
      cimi.pMfOut = &theManifest;
    }
    rc = checkin_mini(&cimi, &newRid, &errMsg);
    if(rc){
      assert(blob_size(&errMsg)==0);
    }else{
      assert(blob_size(&errMsg));
      fossil_fatal("%b", &errMsg);
    }
    if(zManifestFile){
      fossil_print("Writing manifest to: %s\n", zManifestFile);
      assert(blob_size(&theManifest)>0);
      blob_write_to_file(&theManifest, zManifestFile);
      blob_reset(&theManifest);
    }
  }
  if(newRid!=0){
    fossil_print("New version%s: %z\n",
                 (cimi.flags & CIMINI_DRY_RUN) ? " (dry run)" : "",
                 rid_to_uuid(newRid));
  }
  db_end_transaction(0/*checkin_mini() will have triggered it to roll
                      ** back in dry-run mode, but we need access to
                      ** the transaction-written db state in this
                      ** routine.*/);
  if(!(cimi.flags & CIMINI_DRY_RUN) && newRid!=0 && g.localOpen!=0){
    fossil_warning("The checkout state is now out of sync "
                   "with regards to this commit. It needs to be "
                   "'update'd or 'close'd and re-'open'ed.");
  }
  CheckinMiniInfo_cleanup(&cimi);
}


/*
** Returns true if the given filename qualifies for online editing by
** the current user, else returns false.
**
** Editing requires that the user have the Write permission and that
** the filename match the glob defined by the fileedit-glob setting.
** A missing or empty value for that glob disables all editing.
*/
int fileedit_is_editable(const char *zFilename){
  static Glob * pGlobs = 0;
  static int once = 0;
  if(0==g.perm.Write || zFilename==0 || *zFilename==0
     || (once!=0 && pGlobs==0)){
    return 0;
  }else if(0==pGlobs){
    char * zGlobs = db_get("fileedit-glob",0);
    once = 1;
    if(0==zGlobs) return 0;
    pGlobs = glob_create(zGlobs);
    fossil_free(zGlobs);
  }
  return glob_match(pGlobs, zFilename);
}

/*
** Emits a script tag which defines window.fossil.fetch(), which works
** similarly (not identically) to the not-quite-ubiquitous global
** fetch().
**
** JS usages:
**
** fossilFetch( URI, onLoadCallback );
**
** fossilFetch( URI, optionsObject );
**
** Noting that URI must be relative to the top of the repository and
** must not start with a slash (if it does, it is stripped). It gets
** %R/ prepended to it.
**
** The optionsObject may be an onload callback or an object with any
** of these properties:
**
** - onload: callback(responseData) (default = output response to
**   console).
**
** - onerror: callback(XHR onload event) (default = console output)
**
** - method: 'POST' | 'GET' (default = 'GET')
**
** - payload: anything acceptable by XHR2.send(ARG) (DOMString,
**   Document, FormData, Blob, File, ArrayBuffer), or a plain object
**   or array, either of which gets JSON.stringify()'d. If set then
**   the method is automatically set to 'POST'. If an object/array is
**   converted to JSON, the content-type is set to 'application/json'.
**   By default XHR2 will set the content type based on the payload
**   type.
**
** - contentType: Optional request content type when POSTing. Ignored
**   if the method is not 'POST'.
**
** - responseType: optional string. One of ("text", "arraybuffer",
**   "blob", or "document") (as specified by XHR2). Default = "text".
**
** - urlParams: string|object. If a string, it is assumed to be a
**   URI-encoded list of params in the form "key1=val1&key2=val2...",
**   with NO leading '?'.  If it is an object, all of its properties
**   get converted to that form. Either way, the parameters get
**   appended to the URL.
**
*/
void fileedit_emit_script_fetch(){
  style_emit_script_tag(0);
  CX("fossil.fetch = function(path,opt){\n");
  CX("  if('/'===path[0]) path = path.substr(1);\n");
  CX("  if(!opt){\n");
  CX("    opt = {onload:(r)=>console.debug('response:',r)};\n");
  CX("  }else if('function'===typeof opt){\n");
  CX("    opt={onload:opt,\n");
  CX("         onerror:(e)=>console.error('ajax error:',e)};\n");
  CX("  }\n");
  CX("  let payload = opt.payload;\n");
  CX("  if(payload){\n");
  CX("    opt.method = 'POST';\n");
  CX("    if(!(payload instanceof FormData)\n");
  CX("       && !(payload instanceof Document)\n");
  CX("       && !(payload instanceof Blob)\n");
  CX("       && !(payload instanceof File)\n");
  CX("       && !(payload instanceof ArrayBuffer)){\n");
  CX("      if('object'===typeof payload || payload instanceof Array){\n");
  CX("        payload = JSON.stringify(payload);\n");
  CX("        opt.contentType = 'application/json';\n");
  CX("      }\n");
  CX("    }\n");
  CX("  }\n");
  CX("  const url=['%R/'+path], x=new XMLHttpRequest();\n");
  CX("  if(opt.urlParams){\n");
  CX("    url.push('?');\n");
  CX("    if('string'===typeof opt.urlParams){\n");
  CX("      url.push(opt.urlParams);\n");
  CX("    }else{/*assume object*/\n");
  CX("      let k, i = 0;\n");
  CX("      for( k in opt.urlParams ){\n");
  CX("        if(i++) url.push('&');\n");
  CX("        url.push(k,'=',encodeURIComponent(opt.urlParams[k]));\n");
  CX("      }\n");
  CX("    }\n");
  CX("  }\n");
  CX("  if('POST'===opt.method && 'string'===typeof opt.contentType){\n");
  CX("    x.setRequestHeader('Content-Type',opt.contentType);\n");
  CX("  }\n");
  CX("  x.open(opt.method||'GET', url.join(''), true);\n");
  CX("  x.responseType=opt.responseType||'text';\n");
  CX("  if(opt.onload){\n");
  CX("    x.onload = function(e){\n");
  CX("      if(200!==this.status){\n");
  CX("        if(opt.onerror) opt.onerror(e);\n");
  CX("        return;\n");
  CX("      }\n");
  CX("      opt.onload(this.response);\n");
  CX("    }\n");
  CX("  }\n");
  CX("  if(payload) x.send(payload);\n");
  CX("  else x.send();\n");
  CX("};\n");
  style_emit_script_tag(1);
};


enum fileedit_render_preview_flags {
FE_PREVIEW_LINE_NUMBERS = 1
};
enum fileedit_render_modes {
FE_RENDER_GUESS = 0,
FE_RENDER_PLAIN_TEXT,
FE_RENDER_HTML,
FE_RENDER_WIKI
};

static int fileedit_render_mode_for_mimetype(const char * zMimetype){
  int rc = FE_RENDER_PLAIN_TEXT;
  if( zMimetype ){
    if( fossil_strcmp(zMimetype, "text/html")==0 ){
      rc = FE_RENDER_HTML;
    }else if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0
              || fossil_strcmp(zMimetype, "text/x-markdown")==0 ){
      rc = FE_RENDER_WIKI;
    }
  }
  return rc;
}

/*
** Performs the PREVIEW mode for /filepage.
*/
static void fileedit_render_preview(Blob * pContent,
                                    const char *zFilename,
                                    int flags, int renderMode,
                                    int nIframeHeightEm){
  const char * zMime;
  zMime = mimetype_from_name(zFilename);
  if(FE_RENDER_GUESS==renderMode){
    renderMode = fileedit_render_mode_for_mimetype(zMime);
  }
  CX("<div class='fileedit-preview'>");
  CX("<div>Preview</div>");
  switch(renderMode){
    case FE_RENDER_HTML:{
      char * z64 = encode64(blob_str(pContent), blob_size(pContent));
      CX("<iframe width='100%%' frameborder='0' "
         "marginwidth='0' style='height:%dem' "
         "marginheight='0' sandbox='allow-same-origin' "
         "id='ifm1' src='data:text/html;base64,%z'"
         "></iframe>",
         nIframeHeightEm ? nIframeHeightEm : 40,
         z64);
      break;
    }
    case FE_RENDER_WIKI:
      wiki_render_by_mimetype(pContent, zMime);
      break;
    default:{
      const char *zExt = strrchr(zFilename,'.');
      const char *zContent = blob_str(pContent);
      if(FE_PREVIEW_LINE_NUMBERS & flags){
        output_text_with_line_numbers(zContent, "on");
      }else if(zExt && zExt[1]){
        CX("<pre><code class='language-%s'>%h</code></pre>",
           zExt+1, zContent);
      }else{
        CX("<pre>%h</pre>", zExt+1, zContent);
      }
      break;
    }
  }
  CX("</div><!--.fileedit-preview-->\n");
}

/*
** Renders diffs for the /fileedit page. pContent is the
** locally-edited content.  frid is the RID of the file's blob entry
** from which pContent is based. zManifestUuid is the checkin version
** to which RID belongs - it is purely informational, for labeling the
** diff view. isSbs is true for side-by-side diffs, false for unified.
*/
static void fileedit_render_diff(Blob * pContent, int frid,
                                 const char * zManifestUuid,
                                 int isSbs){
  Blob orig = empty_blob;
  Blob out = empty_blob;
  u64 diffFlags = DIFF_HTML | DIFF_NOTTOOBIG | DIFF_STRIP_EOLCR
    | (isSbs ? DIFF_SIDEBYSIDE : DIFF_LINENO);
  content_get(frid, &orig);
  text_diff(&orig, pContent, &out, 0, diffFlags);
  CX("<div class='fileedit-diff'>");
  CX("<div>Diff <code>[%S]</code> &rarr; Local Edits</div>",
     zManifestUuid);
  if(isSbs){
    CX("%b",&out);
  }else{
    CX("<pre class='udiff'>%b</pre>",&out);
  }
  CX("</div><!--.fileedit-diff-->\n");
  blob_reset(&orig);
  blob_reset(&out);
}

/*
** Given a repo-relative filename and a manifest RID, returns the UUID
** of the corresponding file entry.  Returns NULL if no match is
** found.  If pFilePerm is not NULL, the file's permission flag value
** is written to *pFilePerm.
*/
static char *fileedit_file_uuid(char const *zFilename,
                                int vid, int *pFilePerm){
  Stmt stmt = empty_Stmt;
  char * zFileUuid = 0;
  db_prepare(&stmt, "SELECT uuid, perm FROM files_of_checkin "
             "WHERE filename=%Q %s AND checkinID=%d",
             zFilename, filename_collation(), vid);
  if(SQLITE_ROW==db_step(&stmt)){
    zFileUuid = mprintf("%s",db_column_text(&stmt, 0));
    if(pFilePerm){
      *pFilePerm = mfile_permstr_int(db_column_text(&stmt, 1));
    }
  }
  db_finalize(&stmt);
  return zFileUuid;
}

/*
** WEBPAGE: fileedit
**
** EXPERIMENTAL and subject to change and removal at any time. The goal
** is to allow online edits of files.
**
** Query parameters:
**
**    file=FILENAME    Repo-relative path to the file.
**    r=VERSION        Checkin version, using any unambiguous
**                     supported symbolic version name.
**
** All other parameters are for internal use only, submitted via the
** form-submission process, and may change with any given revision of
** this code.
*/
void fileedit_page(){
  enum submit_modes {
  SUBMIT_NONE = 0, SUBMIT_SAVE, SUBMIT_PREVIEW,
  SUBMIT_DIFF_SBS, SUBMIT_DIFF_UNIFIED,
  SUBMIT_end /* sentinel for range validation */
  };
  const char * zFilename = PD("file",P("name"));
                                        /* filename. We'll accept 'name'
                                           because that param is handled
                                           specially by the core. */
  const char * zRev = P("r");           /* checkin version */
  const char * zContent = P("content"); /* file content */
  const char * zComment = P("comment"); /* checkin comment */
  const char * zFileMime = 0;           /* File mime type guess */
  CheckinMiniInfo cimi;                 /* Checkin state */
  int submitMode = SUBMIT_NONE;         /* See mapping below */
  int vid, newVid = 0;                  /* checkin rid */
  int frid = 0;                         /* File content rid */
  int previewLn = P("preview_ln")!=0;   /* Line number mode */
  int previewHtmlHeight = 0;            /* iframe height (EMs) */
  int previewRenderMode = FE_RENDER_GUESS; /* preview mode */
  char * zFileUuid = 0;                 /* File content UUID */
  Blob err = empty_blob;                /* Error report */
  Blob submitResult = empty_blob;       /* Error report */
  const char * zFlagCheck = 0;          /* Temp url flag holder */
  Blob endScript = empty_blob;          /* Script code to run at the
                                           end. This content will be
                                           combined into a single JS
                                           function call, thus each
                                           entry must end with a
                                           semicolon. */
  Stmt stmt = empty_Stmt;
  const int loadMode = 0;               /* See next comment block */
  /* loadMode: How to populate the TEXTAREA:
  **
  ** 0: HTML encode: despite my personal reservations regarding HTML
  ** escaping, this seems to be the only reliable approach
  ** until/unless we completely AJAXify this page.
  **
  ** 1: JSON mode: JSON-izes the file content and injects it, via JS,
  ** into the editor TEXTAREA. This works wonderfully until the input
  ** file contains an raw <SCRIPT> tag, at which points the HTML
  ** parser chokes on it.
  **
  ** 2: AJAX mode: can only load content from the db, not preview/dry-run
  ** content. Unless this page is refactored to work solely over AJAX
  ** (which is a potential TODO), this method is only useful on the
  ** initial hit to this page, where the file is loaded.
  **
  ** loadMode is not generally configurable: change it only for
  ** testing/development purposes.
  */
#define fail(EXPR) blob_appendf EXPR; goto end_footer

  assert(loadMode==0 || loadMode==1 || loadMode==2);
  login_check_credentials();
  if( !g.perm.Write ){
    login_needed(g.anon.Write);
    return;
  }
  db_begin_transaction();
  CheckinMiniInfo_init(&cimi);
  submitMode = atoi(PD("submit","0"));
  if(submitMode < SUBMIT_NONE || submitMode >= SUBMIT_end){
    submitMode = 0;
  }
  zFlagCheck = P("comment_mimetype");
  if(zFlagCheck){
    cimi.zCommentMimetype = mprintf("%s",zFlagCheck);
    zFlagCheck = 0;
  }
  cimi.zUser = mprintf("%s",g.zLogin);

  style_header("File Editor");
  /* As of this point, don't use return or fossil_fatal(), use
  ** fail((&err,...))  instead so that we can be sure to do any
  ** cleanup and end the transaction cleanly.
  */
  if(!zRev || !*zRev || !zFilename || !*zFilename){
    fail((&err,"Missing required URL parameters: "
          "file=FILE and r=CHECKIN"));
  }
  if(0==fileedit_is_editable(zFilename)){
    fail((&err,"Filename <code>%h</code> is disallowed "
          "by the <code>fileedit-glob</code> repository "
          "setting.",
          zFilename));
  }
  vid = symbolic_name_to_rid(zRev, "ci");
  if(0==vid){
    fail((&err,"Could not resolve checkin version."));
  }
  cimi.zFilename = mprintf("%s",zFilename);
  zFileMime = mimetype_from_name(zFilename);

  /* Find the repo-side file entry or fail... */
  cimi.zParentUuid = rid_to_uuid(vid);
  zFileUuid = fileedit_file_uuid(zFilename, vid, &cimi.filePerm);
  if(!zFileUuid){
    fail((&err,"Checkin [%S] does not contain file: "
          "<code>%h</code>",
          cimi.zParentUuid, zFilename));
  }
  else if(PERM_LNK==cimi.filePerm){
    fail((&err,"Editing symlinks is not permitted."));
  }
  frid = fast_uuid_to_rid(zFileUuid);
  assert(frid);

  /* Read file content from submit request or repo... */
  if(zContent==0){
    content_get(frid, &cimi.fileContent);
    zContent = blob_size(&cimi.fileContent)
      ? blob_str(&cimi.fileContent) : NULL;
  }else{
    blob_init(&cimi.fileContent,zContent,-1);
  }
  if(looks_like_binary(&cimi.fileContent)){
    fail((&err,"File appears to be binary. Cannot edit: "
          "<code>%h</code>",zFilename));
  }

  /*
  ** TODO?: date-override date selection field. Maybe use
  ** an input[type=datetime-local].
  */
  if(SUBMIT_NONE==submitMode || P("dry_run")!=0){
    cimi.flags |= CIMINI_DRY_RUN;
  }
  if(P("allow_fork")!=0){
    cimi.flags |= CIMINI_ALLOW_FORK;
  }
  if(P("allow_older")!=0){
    cimi.flags |= CIMINI_ALLOW_OLDER;
  }
  if(P("exec_bit")!=0){
    cimi.filePerm = PERM_EXE;
  }
  if(P("allow_merge_conflict")!=0){
    cimi.flags |= CIMINI_ALLOW_MERGE_MARKER;
  }
  if(P("prefer_delta")!=0){
    cimi.flags |= CIMINI_PREFER_DELTA;
  }
  /* EOL conversion policy... */
  {
    const int eolMode = submitMode==SUBMIT_NONE
      ? 0 : atoi(PD("eol","0"));
    switch(eolMode){
      case 1: cimi.flags |= CIMINI_CONVERT_EOL_UNIX; break;
      case 2: cimi.flags |= CIMINI_CONVERT_EOL_WINDOWS; break;
      default: cimi.flags |= CIMINI_CONVERT_EOL_INHERIT; break;
    }
  }
  
  /********************************************************************
  ** All errors which "could" have happened up to this point are of a
  ** degree which keep us from rendering the rest of the page, and
  ** thus fail() has already skipped to the end of the page to render
  ** the errors. Any up-coming errors, barring malloc failure or
  ** similar, are not "that" fatal. We can/should continue rendering
  ** the page, then output the error message at the end.
  **
  ** Because we cannot intercept the output of the PREVIEW and DIFF
  ** rendering, we have to delay the "real work" for those modes until
  ** after the rest of the page has been rendered. In the case of
  ** SAVE, we can capture all of the output, and thus can perform that
  ** work before rendering, which is important so that we have the
  ** proper version information when rendering the rest of the page.
  ********************************************************************/
#undef fail
  while(SUBMIT_SAVE==submitMode){
    Blob manifest = empty_blob;
    /*cimi.flags |= CIMINI_STRONGLY_PREFER_DELTA;*/
    if(zComment && *zComment){
      blob_append(&cimi.comment, zComment, -1);
    }else{
      blob_append(&err,"Empty checkin comment is not permitted.",-1);
      break;
    }
    cimi.pMfOut = &manifest;
    checkin_mini(&cimi, &newVid, &err);
    if(newVid!=0){
      char * zNewUuid = rid_to_uuid(newVid);
      blob_appendf(&submitResult,
                   "<h3>Manifest%s: %S</h3><pre>"
                   "<code class='fileedit-manifest'>%h</code>"
                   "</pre>",
                   (cimi.flags & CIMINI_DRY_RUN) ? " (dry run)" : "",
                   zNewUuid, blob_str(&manifest));
      if(CIMINI_DRY_RUN & cimi.flags){
        fossil_free(zNewUuid);
      }else{
        /* Update cimi version info... */
        assert(cimi.pParent);
        assert(cimi.zParentUuid);
        fossil_free(zFileUuid);
        zFileUuid = fileedit_file_uuid(cimi.zFilename, newVid, 0);
        manifest_destroy(cimi.pParent);
        cimi.pParent = 0;
        fossil_free(cimi.zParentUuid);
        cimi.zParentUuid = zNewUuid;
        zComment = 0;
        cimi.flags |= CIMINI_DRY_RUN /* for sanity's sake */;
      }
    }
    /* On error, the error message is in the err blob and will
    ** be emitted at the end. */
    cimi.pMfOut = 0;
    blob_reset(&manifest);
    break;
  }

  CX("<h1>Editing:</h1>");
  CX("<p class='fileedit-hint'>");
  CX("File: "
     "[<a id='finfo-link' href='%R/finfo?name=%T&m=%!S'>info</a>] "
     "<code>%h</code><br>",
     zFilename, zFileUuid, zFilename);
  CX("Checkin Version: "
     "[<a id='r-link' href='%R/info/%!S'>info</a>] "
     "<code id='r-label'>%s</code><br>",
     cimi.zParentUuid, cimi.zParentUuid);
  CX("Permalink: <code>"
     "<a id='permalink' href='%R/fileedit?file=%T&r=%!S'>"
     "/fileedit?file=%T&r=%!S</a></code><br>"
     "(Clicking the permalink will reload the page and discard "
     "all edits!)",
     zFilename, cimi.zParentUuid,
     zFilename, cimi.zParentUuid);
  CX("</p>");
  CX("<p>This page is <em>NEW AND EXPERIMENTAL</em>. "
     "USE AT YOUR OWN RISK, preferably on a test "
     "repo.</p>\n");
  
  CX("<form action='%R/fileedit#options' method='POST' "
     "class='fileedit'>\n");

  /******* Hidden fields *******/
  CX("<input type='hidden' name='r' value='%s'>",
     cimi.zParentUuid);
  CX("<input type='hidden' name='file' value='%T'>",
     zFilename);

  /******* Content *******/
  CX("<h3>File Content</h3>\n");
  CX("<textarea name='content' id='fileedit-content' "
     "rows='20' cols='80'>");
  if(0==loadMode){
    CX("%h",blob_str(&cimi.fileContent));
  }else{
    CX("Loading...");
    /* Performed via JS later on */
  }
  CX("</textarea>\n");
  /******* Flags/options *******/
  CX("<fieldset class='fileedit-options' id='options'>"
     "<legend>Options</legend><div>"
     /* Chrome does not sanely lay out multiple
     ** fieldset children after the <legend>, so
     ** a containing div is necessary. */);
  style_labeled_checkbox("dry_run", "Dry-run?", "1",
                         "In dry-run mode, the Save button performs "
                         "all work needed for saving but then rolls "
                         "back the transaction, and thus does not "
                         "really save.",
                         cimi.flags & CIMINI_DRY_RUN);
  style_labeled_checkbox("allow_fork", "Allow fork?", "1",
                         "Allow saving to create a fork?",
                         cimi.flags & CIMINI_ALLOW_FORK);
  style_labeled_checkbox("allow_older", "Allow older?", "1",
                         "Allow saving against a parent version "
                         "which has a newer timestamp?",
                         cimi.flags & CIMINI_ALLOW_OLDER);
  style_labeled_checkbox("exec_bit", "Executable?", "1",
                         "Set the executable bit?",
                         PERM_EXE==cimi.filePerm);
  style_labeled_checkbox("allow_merge_conflict",
                         "Allow merge conflict markers?", "1",
                         "Allow saving even if the content contains "
                         "what appear to be fossil merge conflict "
                         "markers?",
                         cimi.flags & CIMINI_ALLOW_MERGE_MARKER);
  style_labeled_checkbox("prefer_delta",
                         "Prefer delta manifest?", "1",
                         "Will create a delta manifest, instead of "
                         "baseline, if conditions are favorable to do "
                         "so. This option is only a suggestion.",
                         cimi.flags & CIMINI_PREFER_DELTA);
  style_select_list_int("eol", "EOL Style",
                        "EOL conversion policy, noting that "
                        "form-processing may implicitly change the "
                        "line endings of the input.",
                        (cimi.flags & CIMINI_CONVERT_EOL_UNIX)
                        ? 1 : (cimi.flags & CIMINI_CONVERT_EOL_WINDOWS
                               ? 2 : 0),
                        "Inherit", 0,
                        "Unix", 1,
                        "Windows", 2,
                        NULL);

  CX("</div></fieldset>") /* end of checkboxes */;

  /******* Comment *******/
  CX("<a id='comment'></a>");
  CX("<fieldset><legend>Commit message</legend><div>");
  CX("<textarea name='comment' rows='3' cols='80'>");
  /* ^^^ adding the 'required' attribute means we cannot even submit
  ** for PREVIEW mode if it's empty :/. */
  if(zComment && *zComment){
    CX("%h", zComment);
  }
  CX("</textarea>\n");
  CX("<div class='fileedit-hint'>Comments use the Fossil wiki markup "
     "syntax.</div>\n"/*TODO: select for fossil/md/plain text*/);
  CX("</div></fieldset>\n");

  /******* Buttons *******/
  CX("<a id='buttons'></a>");
  CX("<fieldset class='fileedit-options'>"
     "<legend>Tell the server to...</legend><div>");
  CX("<button type='submit' name='submit' value='%d'>"
     "Commit</button>", SUBMIT_SAVE);
  CX("<button type='submit' name='submit' value='%d'>"
     "Preview</button>", SUBMIT_PREVIEW);
  {
    /* Preview rendering mode selection... */
    previewRenderMode = atoi(PD("preview_render_mode","0"));
    if(0==previewRenderMode){
      previewRenderMode = fileedit_render_mode_for_mimetype(zFileMime);
    }
    style_select_list_int("preview_render_mode",
                          "Preview Mode",
                          "Preview mode format.",
                          previewRenderMode,
                          "Guess", FE_RENDER_GUESS,
                          "Wiki/Markdown", FE_RENDER_WIKI,
                          "HTML (iframe)", FE_RENDER_HTML,
                          "Plain Text", FE_RENDER_PLAIN_TEXT,
                          NULL);
    if(FE_RENDER_HTML==previewRenderMode){
      /* HTML preview mode iframe height... */
      if(submitMode==SUBMIT_PREVIEW){
        previewHtmlHeight = atoi(PD("preview_html_ems","0"));
      }else{
        previewHtmlHeight = 40;
      }
      /* Allow selection of HTML preview iframe height */
      style_select_list_int("preview_html_ems",
                            "Preview IFrame Height (EMs)",
                            "Height (in EMs) of the iframe used for "
                            "HTML preview",
                            previewHtmlHeight,
                            "", 20, "", 40,
                            "", 60, "", 80,
                            "", 100, NULL);
    }
    else if(FE_RENDER_PLAIN_TEXT==previewRenderMode){
      style_labeled_checkbox("preview_ln",
                             "Add line numbers to plain-text previews?",
                             "1",
                             "If on, plain-text files (only) will get "
                             "line numbers added to the preview.",
                             previewLn);
    }
  }
  CX("<button type='submit' name='submit' value='%d'>"
     "Diff (SBS)</button>", SUBMIT_DIFF_SBS);
  CX("<button type='submit' name='submit' value='%d'>"
     "Diff (Unified)</button>", SUBMIT_DIFF_UNIFIED);
  CX("</div></fieldset>");

  /******* End of form *******/    
  CX("</form>\n");

  /*
  ** We cannot intercept the output for PREVIEW
  ** and DIFF modes, and therefore have to render those
  ** last.
  */
  if(SUBMIT_PREVIEW==submitMode){
    int pflags = 0;
    if(previewLn) pflags |= FE_PREVIEW_LINE_NUMBERS;
    fileedit_render_preview(&cimi.fileContent, cimi.zFilename, pflags,
                            previewRenderMode, previewHtmlHeight);
  }else if(SUBMIT_DIFF_SBS==submitMode
           || SUBMIT_DIFF_UNIFIED==submitMode){
    fileedit_render_diff(&cimi.fileContent, frid, cimi.zParentUuid,
                         SUBMIT_DIFF_SBS==submitMode);
  }

  /* Dynamically populate the editor... */
  fileedit_emit_script_fetch();
  if(1==loadMode || (2==loadMode && submitMode>SUBMIT_NONE)){
    char const * zQuoted = 0;
    if(blob_size(&cimi.fileContent)>0){
      db_prepare(&stmt, "SELECT json_quote(%B)", &cimi.fileContent);
      db_step(&stmt);
      zQuoted = db_column_text(&stmt,0);
    }
    blob_appendf(&endScript,
                 "/* populate editor form */\n"
                 "document.getElementById('fileedit-content')"
                 ".value=%s;", zQuoted ? zQuoted : "'';\n");
    if(stmt.pStmt){
      db_finalize(&stmt);
    }
  }else if(2==loadMode){
    assert(submitMode==SUBMIT_NONE);
    blob_appendf(&endScript,
                 "window.fossil.fetch('raw/%s',{"
                 "onload: (r)=>document.getElementById('fileedit-content')"
                 ".value=r,"
                 "onerror:()=>document.getElementById('fileedit-content')"
                 ".value="
                 "'Error loading content'"
                 "});\n", zFileUuid);
  }

end_footer:
  zContent = 0;
  fossil_free(zFileUuid);
  if(stmt.pStmt){
    db_finalize(&stmt);
  }
  if(blob_size(&err)){
    CX("<div class='fileedit-error-report'>%s</div>",
       blob_str(&err));
  }else if(blob_size(&submitResult)){
    CX("%b",&submitResult);
  }
  blob_reset(&submitResult);
  blob_reset(&err);
  CheckinMiniInfo_cleanup(&cimi);
  if(blob_size(&endScript)>0){
    style_emit_script_tag(0);
    CX("(function(){\n");
    CX("try{\n%b\n}catch(e){console.error('Exception:',e)}\n",
       &endScript);
    CX("})();");
    style_emit_script_tag(1);
  }
  db_end_transaction(0/*noting that dry-run mode will have already
                      ** set this to rollback mode. */);
  style_footer();
}

Changes to src/finfo.c.

619
620
621
622
623
624
625



626
627
628
629
630
631
632
      @ [annotate]</a>
      @ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
      @ [blame]</a>
      @ %z(href("%R/timeline?n=all&uf=%!S",zUuid))[check-ins&nbsp;using]</a>
      if( fpid>0 ){
        @ %z(href("%R/fdiff?v1=%!S&v2=%!S",zPUuid,zUuid))[diff]</a>
      }



      @ </span></span>
    }
    if( fDebug & FINFO_DEBUG_MLINK ){
      int ii;
      char *zAncLink;
      @ <br />fid=%d(frid) pid=%d(fpid) mid=%d(fmid)
      if( nParent>0 ){







>
>
>







619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
      @ [annotate]</a>
      @ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
      @ [blame]</a>
      @ %z(href("%R/timeline?n=all&uf=%!S",zUuid))[check-ins&nbsp;using]</a>
      if( fpid>0 ){
        @ %z(href("%R/fdiff?v1=%!S&v2=%!S",zPUuid,zUuid))[diff]</a>
      }
      if( fileedit_is_editable(zFilename) ){
        @ %z(href("%R/fileedit?file=%T&r=%!S",zFilename,zCkin))[edit]</a>
      }
      @ </span></span>
    }
    if( fDebug & FINFO_DEBUG_MLINK ){
      int ii;
      char *zAncLink;
      @ <br />fid=%d(frid) pid=%d(fpid) mid=%d(fmid)
      if( nParent>0 ){

Changes to src/info.c.

1454
1455
1456
1457
1458
1459
1460



1461
1462
1463
1464
1465
1466
1467
    @ size: %d(szFile))
    if( g.perm.Hyperlink ){
      @ %z(href("%R/annotate?filename=%T&checkin=%!S",zName,zVers))
      @ [annotate]</a>
      @ %z(href("%R/blame?filename=%T&checkin=%!S",zName,zVers))
      @ [blame]</a>
      @ %z(href("%R/timeline?n=all&uf=%!S",zUuid))[check-ins&nbsp;using]</a>



    }
    cnt++;
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_append(pDownloadName, zName, -1);
    }
  }
  if( prevName && showDetail ){







>
>
>







1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
    @ size: %d(szFile))
    if( g.perm.Hyperlink ){
      @ %z(href("%R/annotate?filename=%T&checkin=%!S",zName,zVers))
      @ [annotate]</a>
      @ %z(href("%R/blame?filename=%T&checkin=%!S",zName,zVers))
      @ [blame]</a>
      @ %z(href("%R/timeline?n=all&uf=%!S",zUuid))[check-ins&nbsp;using]</a>
      if( fileedit_is_editable(zName) ){
        @ %z(href("%R/fileedit?file=%T&r=%!S",zName,zVers))[edit]</a>
      }
    }
    cnt++;
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_append(pDownloadName, zName, -1);
    }
  }
  if( prevName && showDetail ){

Changes to src/leaf.c.

150
151
152
153
154
155
156











157
158
159
160
161
162
163
    "EXISTS(SELECT 1 FROM tagxref AS tx"
           " WHERE tx.rid=%s"
             " AND tx.tagid=%d"
             " AND tx.tagtype>0)",
    zVar, TAG_CLOSED
  );
}












/*
** Schedule a leaf check for "rid" and its parents.
*/
void leaf_eventually_check(int rid){
  static Stmt parentsOf;








>
>
>
>
>
>
>
>
>
>
>







150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
    "EXISTS(SELECT 1 FROM tagxref AS tx"
           " WHERE tx.rid=%s"
             " AND tx.tagid=%d"
             " AND tx.tagtype>0)",
    zVar, TAG_CLOSED
  );
}

/*
** Returns true if vid refers to a closed leaf, else false. vid is
** assumed to refer to a manifest, but this function does not verify
** that.
*/
int leaf_is_closed(int vid){
  return db_exists("SELECT 1 FROM tagxref"
                   " WHERE tagid=%d AND rid=%d AND tagtype>0",
                   TAG_CLOSED, vid);
}

/*
** Schedule a leaf check for "rid" and its parents.
*/
void leaf_eventually_check(int rid){
  static Stmt parentsOf;

Changes to src/main.c.

2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
        }
      }
    }
#else
    zBrowser = db_get("web-browser", "open");
#endif
    if( zIpAddr==0 ){
      zBrowserCmd = mprintf("%s http://localhost:%%d/%s &",
                            zBrowser, zInitPage);
    }else if( strchr(zIpAddr,':') ){
      zBrowserCmd = mprintf("%s http://[%s]:%%d/%s &",
                            zBrowser, zIpAddr, zInitPage);
    }else{
      zBrowserCmd = mprintf("%s http://%s:%%d/%s &",
                            zBrowser, zIpAddr, zInitPage);
    }
  }
  if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
  if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
  db_close(1);
  if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){







|


|


|







2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
        }
      }
    }
#else
    zBrowser = db_get("web-browser", "open");
#endif
    if( zIpAddr==0 ){
      zBrowserCmd = mprintf("%s \"http://localhost:%%d/%s\" &",
                            zBrowser, zInitPage);
    }else if( strchr(zIpAddr,':') ){
      zBrowserCmd = mprintf("%s \"http://[%s]:%%d/%s\" &",
                            zBrowser, zIpAddr, zInitPage);
    }else{
      zBrowserCmd = mprintf("%s \"http://%s:%%d/%s\" &",
                            zBrowser, zIpAddr, zInitPage);
    }
  }
  if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
  if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
  db_close(1);
  if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){

Changes to src/main.mk.

52
53
54
55
56
57
58

59
60
61
62
63
64
65
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/etag.c \
  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/extcgi.c \
  $(SRCDIR)/file.c \

  $(SRCDIR)/finfo.c \
  $(SRCDIR)/foci.c \
  $(SRCDIR)/forum.c \
  $(SRCDIR)/fshell.c \
  $(SRCDIR)/fusefs.c \
  $(SRCDIR)/fuzz.c \
  $(SRCDIR)/glob.c \







>







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/etag.c \
  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/extcgi.c \
  $(SRCDIR)/file.c \
  $(SRCDIR)/fileedit.c \
  $(SRCDIR)/finfo.c \
  $(SRCDIR)/foci.c \
  $(SRCDIR)/forum.c \
  $(SRCDIR)/fshell.c \
  $(SRCDIR)/fusefs.c \
  $(SRCDIR)/fuzz.c \
  $(SRCDIR)/glob.c \
285
286
287
288
289
290
291

292
293
294
295
296
297
298
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/etag_.c \
  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/extcgi_.c \
  $(OBJDIR)/file_.c \

  $(OBJDIR)/finfo_.c \
  $(OBJDIR)/foci_.c \
  $(OBJDIR)/forum_.c \
  $(OBJDIR)/fshell_.c \
  $(OBJDIR)/fusefs_.c \
  $(OBJDIR)/fuzz_.c \
  $(OBJDIR)/glob_.c \







>







286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/etag_.c \
  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/extcgi_.c \
  $(OBJDIR)/file_.c \
  $(OBJDIR)/fileedit_.c \
  $(OBJDIR)/finfo_.c \
  $(OBJDIR)/foci_.c \
  $(OBJDIR)/forum_.c \
  $(OBJDIR)/fshell_.c \
  $(OBJDIR)/fusefs_.c \
  $(OBJDIR)/fuzz_.c \
  $(OBJDIR)/glob_.c \
427
428
429
430
431
432
433

434
435
436
437
438
439
440
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/etag.o \
 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/extcgi.o \
 $(OBJDIR)/file.o \

 $(OBJDIR)/finfo.o \
 $(OBJDIR)/foci.o \
 $(OBJDIR)/forum.o \
 $(OBJDIR)/fshell.o \
 $(OBJDIR)/fusefs.o \
 $(OBJDIR)/fuzz.o \
 $(OBJDIR)/glob.o \







>







429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/etag.o \
 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/extcgi.o \
 $(OBJDIR)/file.o \
 $(OBJDIR)/fileedit.o \
 $(OBJDIR)/finfo.o \
 $(OBJDIR)/foci.o \
 $(OBJDIR)/forum.o \
 $(OBJDIR)/fshell.o \
 $(OBJDIR)/fusefs.o \
 $(OBJDIR)/fuzz.o \
 $(OBJDIR)/glob.o \
764
765
766
767
768
769
770

771
772
773
774
775
776
777
	$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
	$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
	$(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
	$(OBJDIR)/event_.c:$(OBJDIR)/event.h \
	$(OBJDIR)/export_.c:$(OBJDIR)/export.h \
	$(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \
	$(OBJDIR)/file_.c:$(OBJDIR)/file.h \

	$(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
	$(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
	$(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \
	$(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
	$(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
	$(OBJDIR)/fuzz_.c:$(OBJDIR)/fuzz.h \
	$(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \







>







767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
	$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
	$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
	$(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
	$(OBJDIR)/event_.c:$(OBJDIR)/event.h \
	$(OBJDIR)/export_.c:$(OBJDIR)/export.h \
	$(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \
	$(OBJDIR)/file_.c:$(OBJDIR)/file.h \
	$(OBJDIR)/fileedit_.c:$(OBJDIR)/fileedit.h \
	$(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
	$(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
	$(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \
	$(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
	$(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
	$(OBJDIR)/fuzz_.c:$(OBJDIR)/fuzz.h \
	$(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \
1190
1191
1192
1193
1194
1195
1196








1197
1198
1199
1200
1201
1202
1203
$(OBJDIR)/file_.c:	$(SRCDIR)/file.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/file.c >$@

$(OBJDIR)/file.o:	$(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/file.o -c $(OBJDIR)/file_.c

$(OBJDIR)/file.h:	$(OBJDIR)/headers









$(OBJDIR)/finfo_.c:	$(SRCDIR)/finfo.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/finfo.c >$@

$(OBJDIR)/finfo.o:	$(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c








>
>
>
>
>
>
>
>







1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
$(OBJDIR)/file_.c:	$(SRCDIR)/file.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/file.c >$@

$(OBJDIR)/file.o:	$(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/file.o -c $(OBJDIR)/file_.c

$(OBJDIR)/file.h:	$(OBJDIR)/headers

$(OBJDIR)/fileedit_.c:	$(SRCDIR)/fileedit.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/fileedit.c >$@

$(OBJDIR)/fileedit.o:	$(OBJDIR)/fileedit_.c $(OBJDIR)/fileedit.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/fileedit.o -c $(OBJDIR)/fileedit_.c

$(OBJDIR)/fileedit.h:	$(OBJDIR)/headers

$(OBJDIR)/finfo_.c:	$(SRCDIR)/finfo.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/finfo.c >$@

$(OBJDIR)/finfo.o:	$(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c

Changes to src/makemake.tcl.

63
64
65
66
67
68
69

70
71
72
73
74
75
76
  doc
  encode
  etag
  event
  extcgi
  export
  file

  finfo
  foci
  forum
  fshell
  fusefs
  fuzz
  glob







>







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  doc
  encode
  etag
  event
  extcgi
  export
  file
  fileedit
  finfo
  foci
  forum
  fshell
  fusefs
  fuzz
  glob

Changes to src/manifest.c.

1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076

  md5sum_init();
  if( !isRepeat ) g.parseCnt[p->type]++;
  return p;

manifest_syntax_error:
  {
    char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
    if( zUuid ){
      blob_appendf(pErr, "artifact [%s] ", zUuid);
      fossil_free(zUuid);
    }
  }
  if( zErr ){
    blob_appendf(pErr, "line %d: %s", lineNo, zErr);







|







1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076

  md5sum_init();
  if( !isRepeat ) g.parseCnt[p->type]++;
  return p;

manifest_syntax_error:
  {
    char *zUuid = rid_to_uuid(rid);
    if( zUuid ){
      blob_appendf(pErr, "artifact [%s] ", zUuid);
      fossil_free(zUuid);
    }
  }
  if( zErr ){
    blob_appendf(pErr, "line %d: %s", lineNo, zErr);
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
  return fnid;
}

/*
** Compute an appropriate mlink.mperm integer for the permission string
** of a file.
*/
int manifest_file_mperm(ManifestFile *pFile){
  int mperm = PERM_REG;
  if( pFile && pFile->zPerm){
    if( strstr(pFile->zPerm,"x")!=0 ){
      mperm = PERM_EXE;
    }else if( strstr(pFile->zPerm,"l")!=0 ){
      mperm = PERM_LNK;
    }







|







1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
  return fnid;
}

/*
** Compute an appropriate mlink.mperm integer for the permission string
** of a file.
*/
int manifest_file_mperm(const ManifestFile *pFile){
  int mperm = PERM_REG;
  if( pFile && pFile->zPerm){
    if( strstr(pFile->zPerm,"x")!=0 ){
      mperm = PERM_EXE;
    }else if( strstr(pFile->zPerm,"l")!=0 ){
      mperm = PERM_LNK;
    }

Changes to src/style.c.

1293
1294
1295
1296
1297
1298
1299






































































































































  cgi_reset_content();
  webpage_error("assertion fault at %s:%d - %s", zFile, iLine, zExpr);
}

#if INTERFACE
# define webpage_assert(T) if(!(T)){webpage_assert_page(__FILE__,__LINE__,#T);}
#endif













































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
  cgi_reset_content();
  webpage_error("assertion fault at %s:%d - %s", zFile, iLine, zExpr);
}

#if INTERFACE
# define webpage_assert(T) if(!(T)){webpage_assert_page(__FILE__,__LINE__,#T);}
#endif

/*
** Outputs a labeled checkbox element. zFieldName is the form element
** name. zLabel is the label for the checkbox. zValue is the optional
** value for the checkbox. zTip is an optional tooltip, which gets set
** as the "title" attribute of the outermost element. If isChecked is
** true, the checkbox gets the "checked" attribute set, else it is
** not.
**
** Resulting structure:
**
** <div class='input-with-label' title={{zTip}}>
**   <input type='checkbox' name={{zFieldName}} value={{zValue}}
**          {{isChecked ? " checked : ""}}/>
**   <span>{{zLabel}}</span>
** </div>
**
** zFieldName, zLabel, and zValue are required. zTip is optional.
**
** Be sure that the input-with-label CSS class is defined sensibly, in
** particular, having its display:inline-block is useful for alignment
** purposes.
*/
void style_labeled_checkbox(const char *zFieldName, const char * zLabel,
                            const char * zValue, const char * zTip,
                            int isChecked){
  CX("<div class='input-with-label'");
  if(zTip && *zTip){
    CX(" title='%h'", zTip);
  }
  CX("><input type='checkbox' name='%s' value='%T'%s/>",
     zFieldName,
     zValue ? zValue : "", isChecked ? " checked" : "");
  CX("<span>%h</span></div>", zLabel);
}

/*
** Outputs a SELECT list from a compile-time list of integers.
** The vargs must be a list of (const char *, int) pairs, terminated
** with a single NULL. Each pair is interpreted as...
**
** If the (const char *) is NULL, it is the end of the list, else
** a new OPTION entry is created. If the string is empty, the
** label and value of the OPTION is the integer part of the pair.
** If the string is not empty, it becomes the label and the integer
** the value. If that value == selectedValue then that OPTION
** element gets the 'selected' attribute.
**
** Note that the pairs are not in (int, const char *) order because
** there is no well-known integer value which we can definitively use
** as a list terminator.
**
** zFieldName is the value of the form element's name attribute.
**
** zLabel is an optional string to use as a "label" for the element
** (see below).
**
** zTooltip is an optional value for the SELECT's title attribute.
**
** The structure of the emitted HTML is:
**
** <div class='input-with-label' title={{zToolTip}}>
**   <span>{{zLabel}}</span>
**   <select>...</select>
** </div>
**
** Example:
**
** style_select_list_int("my_field", "Grapes",
**                      "Select the number of grapes",
**                       atoi(PD("my_field","0")),
**                       "", 1, "2", 2, "Three", 3,
**                       NULL);
** 
*/
void style_select_list_int(const char *zFieldName, const char * zLabel,
                           const char * zToolTip, int selectedVal,
                           ... ){
  va_list vargs;
  va_start(vargs,selectedVal);
  CX("<div class='input-with-label'");
  if(zToolTip && *zToolTip){
    CX(" title='%h'",zToolTip);
  }
  CX(">");
  if(zLabel && *zLabel){
    CX("<span>%h</span>", zLabel);
  }
  CX("<select name='%s'>",zFieldName);
  while(1){
    const char * zOption = va_arg(vargs,char *);
    int v;
    if(NULL==zOption){
      break;
    }
    v = va_arg(vargs,int);
    CX("<option value='%d'%s>",
         v, v==selectedVal ? " selected" : "");
    if(*zOption){
      CX("%s", zOption);
    }else{
      CX("%d",v);
    }
    CX("</option>\n");
  }
  CX("</select>\n");
  if(zLabel && *zLabel){
    CX("</div>\n");
  }
  va_end(vargs);
}


/*
** If passed 0, it emits a script opener tag with this session's
** nonce. If passed non-0 it emits a script closing tag. The very
** first time it is called, it emits some bootstrapping JS code
** immediately after the script opener. Specifically, it defines
** window.fossil if it's not already defined, and may set some
** properties on it.
*/
void style_emit_script_tag(int phase){
  static int once = 0;
  if(0==phase){
    CX("<script nonce='%s'>", style_nonce());
      if(0==once){
        once = 1;
        CX("\nif(!window.fossil) window.fossil={};\n");
        CX("window.fossil.version = %Q;\n", get_version());
      }
  }else{
    CX("</script>\n");
  }
}

Changes to win/Makefile.dmc.

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
TCC    = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
LIBS   = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi

SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0

SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen

SRC   = add_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c

OBJ   = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\webmail$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O


RC=$(DMDIR)\bin\rcc
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__

APPNAME = $(OBJDIR)\fossil$(E)

all: $(APPNAME)

$(APPNAME) : translate$E mkindex$E codecheck1$E headers  $(OBJ) $(OBJDIR)\link
	cd $(OBJDIR)
	codecheck1$E $(SRC)
	$(DMDIR)\bin\link @link

$(OBJDIR)\fossil.res:	$B\win\fossil.rc
	$(RC) $(RCFLAGS) -o$@ $**

$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
	+echo add alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi checkin checkout clearsign clone comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file finfo foci forum fshell fusefs fuzz glob graph gzip hname http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path piechart pivot popen pqueue printf publish purge rebuild regexp repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile webmail wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
	+echo fossil >> $@
	+echo fossil >> $@
	+echo $(LIBS) >> $@
	+echo. >> $@
	+echo fossil >> $@

translate$E: $(SRCDIR)\translate.c







|

|


















|







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
TCC    = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
LIBS   = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi

SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0

SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen

SRC   = add_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c

OBJ   = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\fileedit$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\webmail$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O


RC=$(DMDIR)\bin\rcc
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__

APPNAME = $(OBJDIR)\fossil$(E)

all: $(APPNAME)

$(APPNAME) : translate$E mkindex$E codecheck1$E headers  $(OBJ) $(OBJDIR)\link
	cd $(OBJDIR)
	codecheck1$E $(SRC)
	$(DMDIR)\bin\link @link

$(OBJDIR)\fossil.res:	$B\win\fossil.rc
	$(RC) $(RCFLAGS) -o$@ $**

$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
	+echo add alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi checkin checkout clearsign clone comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file fileedit finfo foci forum fshell fusefs fuzz glob graph gzip hname http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path piechart pivot popen pqueue printf publish purge rebuild regexp repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile webmail wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
	+echo fossil >> $@
	+echo fossil >> $@
	+echo $(LIBS) >> $@
	+echo. >> $@
	+echo fossil >> $@

translate$E: $(SRCDIR)\translate.c
366
367
368
369
370
371
372






373
374
375
376
377
378
379
	+translate$E $** > $@

$(OBJDIR)\file$O : file_.c file.h
	$(TCC) -o$@ -c file_.c

file_.c : $(SRCDIR)\file.c
	+translate$E $** > $@







$(OBJDIR)\finfo$O : finfo_.c finfo.h
	$(TCC) -o$@ -c finfo_.c

finfo_.c : $(SRCDIR)\finfo.c
	+translate$E $** > $@








>
>
>
>
>
>







366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
	+translate$E $** > $@

$(OBJDIR)\file$O : file_.c file.h
	$(TCC) -o$@ -c file_.c

file_.c : $(SRCDIR)\file.c
	+translate$E $** > $@

$(OBJDIR)\fileedit$O : fileedit_.c fileedit.h
	$(TCC) -o$@ -c fileedit_.c

fileedit_.c : $(SRCDIR)\fileedit.c
	+translate$E $** > $@

$(OBJDIR)\finfo$O : finfo_.c finfo.h
	$(TCC) -o$@ -c finfo_.c

finfo_.c : $(SRCDIR)\finfo.c
	+translate$E $** > $@

968
969
970
971
972
973
974
975
976
$(OBJDIR)\zip$O : zip_.c zip.h
	$(TCC) -o$@ -c zip_.c

zip_.c : $(SRCDIR)\zip.c
	+translate$E $** > $@

headers: makeheaders$E page_index.h builtin_data.h default_css.h VERSION.h
	 +makeheaders$E add_.c:add.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backlink_.c:backlink.h backoffice_.c:backoffice.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h capabilities_.c:capabilities.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 cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h deltafunc_.c:deltafunc.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h etag_.c:etag.h event_.c:event.h export_.c:export.h extcgi_.c:extcgi.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h fuzz_.c:fuzz.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h piechart_.c:piechart.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h smtp_.c:smtp.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h webmail_.c:webmail.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
	@copy /Y nul: headers







|

974
975
976
977
978
979
980
981
982
$(OBJDIR)\zip$O : zip_.c zip.h
	$(TCC) -o$@ -c zip_.c

zip_.c : $(SRCDIR)\zip.c
	+translate$E $** > $@

headers: makeheaders$E page_index.h builtin_data.h default_css.h VERSION.h
	 +makeheaders$E add_.c:add.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backlink_.c:backlink.h backoffice_.c:backoffice.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h capabilities_.c:capabilities.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 cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h deltafunc_.c:deltafunc.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h etag_.c:etag.h event_.c:event.h export_.c:export.h extcgi_.c:extcgi.h file_.c:file.h fileedit_.c:fileedit.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h fuzz_.c:fuzz.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h piechart_.c:piechart.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h smtp_.c:smtp.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h webmail_.c:webmail.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
	@copy /Y nul: headers

Changes to win/Makefile.mingw.

474
475
476
477
478
479
480

481
482
483
484
485
486
487
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/etag.c \
  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/extcgi.c \
  $(SRCDIR)/file.c \

  $(SRCDIR)/finfo.c \
  $(SRCDIR)/foci.c \
  $(SRCDIR)/forum.c \
  $(SRCDIR)/fshell.c \
  $(SRCDIR)/fusefs.c \
  $(SRCDIR)/fuzz.c \
  $(SRCDIR)/glob.c \







>







474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/etag.c \
  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/extcgi.c \
  $(SRCDIR)/file.c \
  $(SRCDIR)/fileedit.c \
  $(SRCDIR)/finfo.c \
  $(SRCDIR)/foci.c \
  $(SRCDIR)/forum.c \
  $(SRCDIR)/fshell.c \
  $(SRCDIR)/fusefs.c \
  $(SRCDIR)/fuzz.c \
  $(SRCDIR)/glob.c \
707
708
709
710
711
712
713

714
715
716
717
718
719
720
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/etag_.c \
  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/extcgi_.c \
  $(OBJDIR)/file_.c \

  $(OBJDIR)/finfo_.c \
  $(OBJDIR)/foci_.c \
  $(OBJDIR)/forum_.c \
  $(OBJDIR)/fshell_.c \
  $(OBJDIR)/fusefs_.c \
  $(OBJDIR)/fuzz_.c \
  $(OBJDIR)/glob_.c \







>







708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/etag_.c \
  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/extcgi_.c \
  $(OBJDIR)/file_.c \
  $(OBJDIR)/fileedit_.c \
  $(OBJDIR)/finfo_.c \
  $(OBJDIR)/foci_.c \
  $(OBJDIR)/forum_.c \
  $(OBJDIR)/fshell_.c \
  $(OBJDIR)/fusefs_.c \
  $(OBJDIR)/fuzz_.c \
  $(OBJDIR)/glob_.c \
849
850
851
852
853
854
855

856
857
858
859
860
861
862
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/etag.o \
 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/extcgi.o \
 $(OBJDIR)/file.o \

 $(OBJDIR)/finfo.o \
 $(OBJDIR)/foci.o \
 $(OBJDIR)/forum.o \
 $(OBJDIR)/fshell.o \
 $(OBJDIR)/fusefs.o \
 $(OBJDIR)/fuzz.o \
 $(OBJDIR)/glob.o \







>







851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/etag.o \
 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/extcgi.o \
 $(OBJDIR)/file.o \
 $(OBJDIR)/fileedit.o \
 $(OBJDIR)/finfo.o \
 $(OBJDIR)/foci.o \
 $(OBJDIR)/forum.o \
 $(OBJDIR)/fshell.o \
 $(OBJDIR)/fusefs.o \
 $(OBJDIR)/fuzz.o \
 $(OBJDIR)/glob.o \
1211
1212
1213
1214
1215
1216
1217

1218
1219
1220
1221
1222
1223
1224
		$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
		$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
		$(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
		$(OBJDIR)/event_.c:$(OBJDIR)/event.h \
		$(OBJDIR)/export_.c:$(OBJDIR)/export.h \
		$(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \
		$(OBJDIR)/file_.c:$(OBJDIR)/file.h \

		$(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
		$(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
		$(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \
		$(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
		$(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
		$(OBJDIR)/fuzz_.c:$(OBJDIR)/fuzz.h \
		$(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \







>







1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
		$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
		$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
		$(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
		$(OBJDIR)/event_.c:$(OBJDIR)/event.h \
		$(OBJDIR)/export_.c:$(OBJDIR)/export.h \
		$(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \
		$(OBJDIR)/file_.c:$(OBJDIR)/file.h \
		$(OBJDIR)/fileedit_.c:$(OBJDIR)/fileedit.h \
		$(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
		$(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
		$(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \
		$(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
		$(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
		$(OBJDIR)/fuzz_.c:$(OBJDIR)/fuzz.h \
		$(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \
1639
1640
1641
1642
1643
1644
1645








1646
1647
1648
1649
1650
1651
1652
$(OBJDIR)/file_.c:	$(SRCDIR)/file.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/file.c >$@

$(OBJDIR)/file.o:	$(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/file.o -c $(OBJDIR)/file_.c

$(OBJDIR)/file.h:	$(OBJDIR)/headers









$(OBJDIR)/finfo_.c:	$(SRCDIR)/finfo.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/finfo.c >$@

$(OBJDIR)/finfo.o:	$(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c








>
>
>
>
>
>
>
>







1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
$(OBJDIR)/file_.c:	$(SRCDIR)/file.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/file.c >$@

$(OBJDIR)/file.o:	$(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/file.o -c $(OBJDIR)/file_.c

$(OBJDIR)/file.h:	$(OBJDIR)/headers

$(OBJDIR)/fileedit_.c:	$(SRCDIR)/fileedit.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/fileedit.c >$@

$(OBJDIR)/fileedit.o:	$(OBJDIR)/fileedit_.c $(OBJDIR)/fileedit.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/fileedit.o -c $(OBJDIR)/fileedit_.c

$(OBJDIR)/fileedit.h:	$(OBJDIR)/headers

$(OBJDIR)/finfo_.c:	$(SRCDIR)/finfo.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/finfo.c >$@

$(OBJDIR)/finfo.o:	$(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c

Changes to win/Makefile.msc.

382
383
384
385
386
387
388

389
390
391
392
393
394
395
        doc_.c \
        encode_.c \
        etag_.c \
        event_.c \
        export_.c \
        extcgi_.c \
        file_.c \

        finfo_.c \
        foci_.c \
        forum_.c \
        fshell_.c \
        fusefs_.c \
        fuzz_.c \
        glob_.c \







>







382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
        doc_.c \
        encode_.c \
        etag_.c \
        event_.c \
        export_.c \
        extcgi_.c \
        file_.c \
        fileedit_.c \
        finfo_.c \
        foci_.c \
        forum_.c \
        fshell_.c \
        fusefs_.c \
        fuzz_.c \
        glob_.c \
614
615
616
617
618
619
620

621
622
623
624
625
626
627
        $(OX)\doc$O \
        $(OX)\encode$O \
        $(OX)\etag$O \
        $(OX)\event$O \
        $(OX)\export$O \
        $(OX)\extcgi$O \
        $(OX)\file$O \

        $(OX)\finfo$O \
        $(OX)\foci$O \
        $(OX)\forum$O \
        $(OX)\fshell$O \
        $(OX)\fusefs$O \
        $(OX)\fuzz$O \
        $(OX)\glob$O \







>







615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
        $(OX)\doc$O \
        $(OX)\encode$O \
        $(OX)\etag$O \
        $(OX)\event$O \
        $(OX)\export$O \
        $(OX)\extcgi$O \
        $(OX)\file$O \
        $(OX)\fileedit$O \
        $(OX)\finfo$O \
        $(OX)\foci$O \
        $(OX)\forum$O \
        $(OX)\fshell$O \
        $(OX)\fusefs$O \
        $(OX)\fuzz$O \
        $(OX)\glob$O \
818
819
820
821
822
823
824

825
826
827
828
829
830
831
	echo $(OX)\doc.obj >> $@
	echo $(OX)\encode.obj >> $@
	echo $(OX)\etag.obj >> $@
	echo $(OX)\event.obj >> $@
	echo $(OX)\export.obj >> $@
	echo $(OX)\extcgi.obj >> $@
	echo $(OX)\file.obj >> $@

	echo $(OX)\finfo.obj >> $@
	echo $(OX)\foci.obj >> $@
	echo $(OX)\forum.obj >> $@
	echo $(OX)\fshell.obj >> $@
	echo $(OX)\fusefs.obj >> $@
	echo $(OX)\fuzz.obj >> $@
	echo $(OX)\glob.obj >> $@







>







820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
	echo $(OX)\doc.obj >> $@
	echo $(OX)\encode.obj >> $@
	echo $(OX)\etag.obj >> $@
	echo $(OX)\event.obj >> $@
	echo $(OX)\export.obj >> $@
	echo $(OX)\extcgi.obj >> $@
	echo $(OX)\file.obj >> $@
	echo $(OX)\fileedit.obj >> $@
	echo $(OX)\finfo.obj >> $@
	echo $(OX)\foci.obj >> $@
	echo $(OX)\forum.obj >> $@
	echo $(OX)\fshell.obj >> $@
	echo $(OX)\fusefs.obj >> $@
	echo $(OX)\fuzz.obj >> $@
	echo $(OX)\glob.obj >> $@
1280
1281
1282
1283
1284
1285
1286






1287
1288
1289
1290
1291
1292
1293
	translate$E $** > $@

$(OX)\file$O : file_.c file.h
	$(TCC) /Fo$@ -c file_.c

file_.c : $(SRCDIR)\file.c
	translate$E $** > $@







$(OX)\finfo$O : finfo_.c finfo.h
	$(TCC) /Fo$@ -c finfo_.c

finfo_.c : $(SRCDIR)\finfo.c
	translate$E $** > $@








>
>
>
>
>
>







1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
	translate$E $** > $@

$(OX)\file$O : file_.c file.h
	$(TCC) /Fo$@ -c file_.c

file_.c : $(SRCDIR)\file.c
	translate$E $** > $@

$(OX)\fileedit$O : fileedit_.c fileedit.h
	$(TCC) /Fo$@ -c fileedit_.c

fileedit_.c : $(SRCDIR)\fileedit.c
	translate$E $** > $@

$(OX)\finfo$O : finfo_.c finfo.h
	$(TCC) /Fo$@ -c finfo_.c

finfo_.c : $(SRCDIR)\finfo.c
	translate$E $** > $@

1925
1926
1927
1928
1929
1930
1931

1932
1933
1934
1935
1936
1937
1938
			doc_.c:doc.h \
			encode_.c:encode.h \
			etag_.c:etag.h \
			event_.c:event.h \
			export_.c:export.h \
			extcgi_.c:extcgi.h \
			file_.c:file.h \

			finfo_.c:finfo.h \
			foci_.c:foci.h \
			forum_.c:forum.h \
			fshell_.c:fshell.h \
			fusefs_.c:fusefs.h \
			fuzz_.c:fuzz.h \
			glob_.c:glob.h \







>







1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
			doc_.c:doc.h \
			encode_.c:encode.h \
			etag_.c:etag.h \
			event_.c:event.h \
			export_.c:export.h \
			extcgi_.c:extcgi.h \
			file_.c:file.h \
			fileedit_.c:fileedit.h \
			finfo_.c:finfo.h \
			foci_.c:foci.h \
			forum_.c:forum.h \
			fshell_.c:fshell.h \
			fusefs_.c:fusefs.h \
			fuzz_.c:fuzz.h \
			glob_.c:glob.h \