Fossil SCM

Merge in the Fossil 2.0 and 2.1 enhancements.

drh 2017-03-06 19:51 optimize-pragma merge
Commit 0dc479305f187140fcd79efa9e2a78201eadf6cd
79 files changed +1 -1 +1 -1 +9 -5 +4 -4 +11 -16 +10 -10 +3 -6 +1 +6 +1 +22 -12 +28 -34 +28 -34 +1 -1 +22 -8 +2 -2 +90 +1 -1 +1 -1 +2 -2 +1 -1 +1 -1 +11 +2 -2 +7 -5 +13 -2 +36 +6 -1 +3 +80 -80 +15 -1 +6 -5 +24 -28 +2 -2 +7 -13 +106 -94 +2 -2 +79 -11 +1 +4 -3 +14 -13 +1 -2 +2 -2 +35 -32 +7 -2 +7 -2 +1 -1 +2 -6 +2 -2 +58 -1 +6 -8 +19 -30 +2 -2 +1 -1 +96 -66 +2 -5 +22 -4 +36 +36 +30 +3 -3 +20 -2 +4 -4 +1 -1 +79 -84 +2 -1 +20 +2 -2 +1 +6 +7 -6 +5 -5 +1 -1 +14 -14 +3 -2 +2 -1 +1 -1 +4 -3
+1 -1
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1
-1.37
1
+2.1
22
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 1.37
2
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 2.1
2
+1 -1
--- src/attach.c
+++ src/attach.c
@@ -2,11 +2,11 @@
22
** Copyright (c) 2010 D. Richard Hipp
33
**
44
** This program is free software; you can redistribute it and/or
55
** modify it under the terms of the Simplified BSD License (also
66
** known as the "2-Clause License" or "FreeBSD License".)
7
-
7
+**
88
** This program is distributed in the hope that it will be useful,
99
** but without any warranty; without even the implied warranty of
1010
** merchantability or fitness for a particular purpose.
1111
**
1212
** Author contact information:
1313
--- src/attach.c
+++ src/attach.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2010 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
13
--- src/attach.c
+++ src/attach.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2010 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7 **
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
13
+9 -5
--- src/blob.c
+++ src/blob.c
@@ -2,11 +2,11 @@
22
** Copyright (c) 2006 D. Richard Hipp
33
**
44
** This program is free software; you can redistribute it and/or
55
** modify it under the terms of the Simplified BSD License (also
66
** known as the "2-Clause License" or "FreeBSD License".)
7
-
7
+**
88
** This program is distributed in the hope that it will be useful,
99
** but without any warranty; without even the implied warranty of
1010
** merchantability or fitness for a particular purpose.
1111
**
1212
** Author contact information:
@@ -647,15 +647,19 @@
647647
}
648648
pFrom->iCursor = i;
649649
}
650650
651651
/*
652
-** Return true if the blob contains a valid UUID_SIZE-digit base16 identifier.
652
+** Return true if the blob contains a valid base16 identifier artifact hash.
653
+**
654
+** The value returned is actually one of HNAME_SHA1 OR HNAME_K256 if the
655
+** hash is valid. Both of these are non-zero and therefore "true".
656
+** If the hash is not valid, then HNAME_ERROR is returned, which is zero or
657
+** false.
653658
*/
654
-int blob_is_uuid(Blob *pBlob){
655
- return blob_size(pBlob)==UUID_SIZE
656
- && validate16(blob_buffer(pBlob), UUID_SIZE);
659
+int blob_is_hname(Blob *pBlob){
660
+ return hname_validate(blob_buffer(pBlob), blob_size(pBlob));
657661
}
658662
659663
/*
660664
** Return true if the blob contains a valid filename
661665
*/
662666
--- src/blob.c
+++ src/blob.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -647,15 +647,19 @@
647 }
648 pFrom->iCursor = i;
649 }
650
651 /*
652 ** Return true if the blob contains a valid UUID_SIZE-digit base16 identifier.
 
 
 
 
 
653 */
654 int blob_is_uuid(Blob *pBlob){
655 return blob_size(pBlob)==UUID_SIZE
656 && validate16(blob_buffer(pBlob), UUID_SIZE);
657 }
658
659 /*
660 ** Return true if the blob contains a valid filename
661 */
662
--- src/blob.c
+++ src/blob.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7 **
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -647,15 +647,19 @@
647 }
648 pFrom->iCursor = i;
649 }
650
651 /*
652 ** Return true if the blob contains a valid base16 identifier artifact hash.
653 **
654 ** The value returned is actually one of HNAME_SHA1 OR HNAME_K256 if the
655 ** hash is valid. Both of these are non-zero and therefore "true".
656 ** If the hash is not valid, then HNAME_ERROR is returned, which is zero or
657 ** false.
658 */
659 int blob_is_hname(Blob *pBlob){
660 return hname_validate(blob_buffer(pBlob), blob_size(pBlob));
 
661 }
662
663 /*
664 ** Return true if the blob contains a valid filename
665 */
666
+4 -4
--- src/browse.c
+++ src/browse.c
@@ -315,11 +315,11 @@
315315
FileTreeNode *pSibling; /* Next element in the same subdirectory */
316316
FileTreeNode *pChild; /* List of child nodes */
317317
FileTreeNode *pLastChild; /* Last child on the pChild list */
318318
char *zName; /* Name of this entry. The "tail" */
319319
char *zFullName; /* Full pathname of this entry */
320
- char *zUuid; /* SHA1 hash of this file. May be NULL. */
320
+ char *zUuid; /* Artifact hash of this file. May be NULL. */
321321
double mtime; /* Modification time for this entry */
322322
unsigned nFullName; /* Length of zFullName */
323323
unsigned iLevel; /* Levels of parent directories */
324324
};
325325
@@ -345,11 +345,11 @@
345345
** the tree to be constructed properly.
346346
*/
347347
static void tree_add_node(
348348
FileTree *pTree, /* Tree into which nodes are added */
349349
const char *zPath, /* The full pathname of file to add */
350
- const char *zUuid, /* UUID of the file. Might be NULL. */
350
+ const char *zUuid, /* Hash of the file. Might be NULL. */
351351
double mtime /* Modification time for this entry */
352352
){
353353
int i;
354354
FileTreeNode *pParent; /* Parent (directory) of the next node to insert */
355355
@@ -368,20 +368,20 @@
368368
FileTreeNode *pNew;
369369
int iStart = i;
370370
int nByte;
371371
while( zPath[i] && zPath[i]!='/' ){ i++; }
372372
nByte = sizeof(*pNew) + i + 1;
373
- if( zUuid!=0 && zPath[i]==0 ) nByte += UUID_SIZE+1;
373
+ if( zUuid!=0 && zPath[i]==0 ) nByte += HNAME_MAX+1;
374374
pNew = fossil_malloc( nByte );
375375
memset(pNew, 0, sizeof(*pNew));
376376
pNew->zFullName = (char*)&pNew[1];
377377
memcpy(pNew->zFullName, zPath, i);
378378
pNew->zFullName[i] = 0;
379379
pNew->nFullName = i;
380380
if( zUuid!=0 && zPath[i]==0 ){
381381
pNew->zUuid = pNew->zFullName + i + 1;
382
- memcpy(pNew->zUuid, zUuid, UUID_SIZE+1);
382
+ memcpy(pNew->zUuid, zUuid, strlen(zUuid)+1);
383383
}
384384
pNew->zName = pNew->zFullName + iStart;
385385
if( pTree->pLast ){
386386
pTree->pLast->pNext = pNew;
387387
}else{
388388
--- src/browse.c
+++ src/browse.c
@@ -315,11 +315,11 @@
315 FileTreeNode *pSibling; /* Next element in the same subdirectory */
316 FileTreeNode *pChild; /* List of child nodes */
317 FileTreeNode *pLastChild; /* Last child on the pChild list */
318 char *zName; /* Name of this entry. The "tail" */
319 char *zFullName; /* Full pathname of this entry */
320 char *zUuid; /* SHA1 hash of this file. May be NULL. */
321 double mtime; /* Modification time for this entry */
322 unsigned nFullName; /* Length of zFullName */
323 unsigned iLevel; /* Levels of parent directories */
324 };
325
@@ -345,11 +345,11 @@
345 ** the tree to be constructed properly.
346 */
347 static void tree_add_node(
348 FileTree *pTree, /* Tree into which nodes are added */
349 const char *zPath, /* The full pathname of file to add */
350 const char *zUuid, /* UUID of the file. Might be NULL. */
351 double mtime /* Modification time for this entry */
352 ){
353 int i;
354 FileTreeNode *pParent; /* Parent (directory) of the next node to insert */
355
@@ -368,20 +368,20 @@
368 FileTreeNode *pNew;
369 int iStart = i;
370 int nByte;
371 while( zPath[i] && zPath[i]!='/' ){ i++; }
372 nByte = sizeof(*pNew) + i + 1;
373 if( zUuid!=0 && zPath[i]==0 ) nByte += UUID_SIZE+1;
374 pNew = fossil_malloc( nByte );
375 memset(pNew, 0, sizeof(*pNew));
376 pNew->zFullName = (char*)&pNew[1];
377 memcpy(pNew->zFullName, zPath, i);
378 pNew->zFullName[i] = 0;
379 pNew->nFullName = i;
380 if( zUuid!=0 && zPath[i]==0 ){
381 pNew->zUuid = pNew->zFullName + i + 1;
382 memcpy(pNew->zUuid, zUuid, UUID_SIZE+1);
383 }
384 pNew->zName = pNew->zFullName + iStart;
385 if( pTree->pLast ){
386 pTree->pLast->pNext = pNew;
387 }else{
388
--- src/browse.c
+++ src/browse.c
@@ -315,11 +315,11 @@
315 FileTreeNode *pSibling; /* Next element in the same subdirectory */
316 FileTreeNode *pChild; /* List of child nodes */
317 FileTreeNode *pLastChild; /* Last child on the pChild list */
318 char *zName; /* Name of this entry. The "tail" */
319 char *zFullName; /* Full pathname of this entry */
320 char *zUuid; /* Artifact hash of this file. May be NULL. */
321 double mtime; /* Modification time for this entry */
322 unsigned nFullName; /* Length of zFullName */
323 unsigned iLevel; /* Levels of parent directories */
324 };
325
@@ -345,11 +345,11 @@
345 ** the tree to be constructed properly.
346 */
347 static void tree_add_node(
348 FileTree *pTree, /* Tree into which nodes are added */
349 const char *zPath, /* The full pathname of file to add */
350 const char *zUuid, /* Hash of the file. Might be NULL. */
351 double mtime /* Modification time for this entry */
352 ){
353 int i;
354 FileTreeNode *pParent; /* Parent (directory) of the next node to insert */
355
@@ -368,20 +368,20 @@
368 FileTreeNode *pNew;
369 int iStart = i;
370 int nByte;
371 while( zPath[i] && zPath[i]!='/' ){ i++; }
372 nByte = sizeof(*pNew) + i + 1;
373 if( zUuid!=0 && zPath[i]==0 ) nByte += HNAME_MAX+1;
374 pNew = fossil_malloc( nByte );
375 memset(pNew, 0, sizeof(*pNew));
376 pNew->zFullName = (char*)&pNew[1];
377 memcpy(pNew->zFullName, zPath, i);
378 pNew->zFullName[i] = 0;
379 pNew->nFullName = i;
380 if( zUuid!=0 && zPath[i]==0 ){
381 pNew->zUuid = pNew->zFullName + i + 1;
382 memcpy(pNew->zUuid, zUuid, strlen(zUuid)+1);
383 }
384 pNew->zName = pNew->zFullName + iStart;
385 if( pTree->pLast ){
386 pTree->pLast->pNext = pNew;
387 }else{
388
+11 -16
--- src/bundle.c
+++ src/bundle.c
@@ -35,11 +35,11 @@
3535
@ bcname TEXT,
3636
@ bcvalue ANY
3737
@ );
3838
@ CREATE TABLE IF NOT EXISTS "%w".bblob(
3939
@ blobid INTEGER PRIMARY KEY, -- Blob ID
40
-@ uuid TEXT NOT NULL, -- SHA1 hash of expanded blob
40
+@ uuid TEXT NOT NULL, -- hash of expanded blob
4141
@ sz INT NOT NULL, -- Size of blob after expansion
4242
@ delta ANY, -- Delta compression basis, or NULL
4343
@ notes TEXT, -- Description of content
4444
@ data BLOB -- compressed content
4545
@ );
@@ -439,19 +439,19 @@
439439
" WHERE bix.delta=%d"
440440
" AND bix.blobid=bblob.blobid;",
441441
iSrc
442442
);
443443
while( db_step(&q)==SQLITE_ROW ){
444
- Blob h1, h2, c1, c2;
444
+ Blob h1, c1, c2;
445445
int rid;
446446
blob_zero(&h1);
447447
db_column_blob(&q, 0, &h1);
448448
blob_zero(&c1);
449449
db_column_blob(&q, 1, &c1);
450450
blob_uncompress(&c1, &c1);
451451
blob_zero(&c2);
452
- if( db_column_type(&q,2)==SQLITE_TEXT && db_column_bytes(&q,2)==40 ){
452
+ if( db_column_type(&q,2)==SQLITE_TEXT && db_column_bytes(&q,2)>=HNAME_MIN ){
453453
Blob basis;
454454
rid = db_int(0,"SELECT rid FROM blob WHERE uuid=%Q",
455455
db_column_text(&q,2));
456456
content_get(rid, &basis);
457457
blob_delta_apply(&basis, &c1, &c2);
@@ -461,16 +461,13 @@
461461
blob_delta_apply(pBasis, &c1, &c2);
462462
blob_reset(&c1);
463463
}else{
464464
c2 = c1;
465465
}
466
- sha1sum_blob(&c2, &h2);
467
- if( blob_compare(&h1, &h2)!=0 ){
468
- fossil_fatal("SHA1 hash mismatch - wanted %s, got %s",
469
- blob_str(&h1), blob_str(&h2));
466
+ if( hname_verify_hash(&c2, blob_buffer(&h1), blob_size(&h1))==0 ){
467
+ fossil_fatal("artifact hash error on %b", &h1);
470468
}
471
- blob_reset(&h2);
472469
rid = content_put_ex(&c2, blob_str(&h1), 0, 0, isPriv);
473470
if( rid==0 ){
474471
fossil_fatal("%s", g.zErrMsg);
475472
}else{
476473
if( !isPriv ) content_make_public(rid);
@@ -491,11 +488,11 @@
491488
static void bundle_extract_item(
492489
int blobid, /* ID of the item to extract */
493490
Blob *pOut /* Write the content into this blob */
494491
){
495492
Stmt q;
496
- Blob x, basis, h1, h2;
493
+ Blob x, basis, h1;
497494
static Bag busy;
498495
499496
db_prepare(&q, "SELECT uuid, delta, data FROM bblob"
500497
" WHERE blobid=%d", blobid);
501498
if( db_step(&q)!=SQLITE_ROW ){
@@ -525,17 +522,14 @@
525522
}else{
526523
*pOut = x;
527524
}
528525
blob_zero(&h1);
529526
db_column_blob(&q, 0, &h1);
530
- sha1sum_blob(pOut, &h2);
531
- if( blob_compare(&h1, &h2)!=0 ){
532
- fossil_fatal("SHA1 hash mismatch - wanted %s, got %s",
533
- blob_str(&h1), blob_str(&h2));
527
+ if( hname_verify_hash(pOut, blob_buffer(&h1), blob_size(&h1))==0 ){
528
+ fossil_fatal("incorrect hash for artifact %b", &h1);
534529
}
535530
blob_reset(&h1);
536
- blob_reset(&h2);
537531
bag_remove(&busy, blobid);
538532
db_finalize(&q);
539533
}
540534
541535
/* fossil bundle cat BUNDLE UUID...
@@ -597,12 +591,13 @@
597591
** repo, then the delta encodings cannot be decoded and the bundle cannot
598592
** be extracted. */
599593
zMissingDeltas = db_text(0,
600594
"SELECT group_concat(substr(delta,1,10),' ')"
601595
" FROM bblob"
602
- " WHERE typeof(delta)='text' AND length(delta)=40"
603
- " AND NOT EXISTS(SELECT 1 FROM blob WHERE uuid=bblob.delta)");
596
+ " WHERE typeof(delta)='text' AND length(delta)>=%d"
597
+ " AND NOT EXISTS(SELECT 1 FROM blob WHERE uuid=bblob.delta)",
598
+ HNAME_MIN);
604599
if( zMissingDeltas && zMissingDeltas[0] ){
605600
fossil_fatal("delta basis artifacts not found in repository: %s",
606601
zMissingDeltas);
607602
}
608603
609604
--- src/bundle.c
+++ src/bundle.c
@@ -35,11 +35,11 @@
35 @ bcname TEXT,
36 @ bcvalue ANY
37 @ );
38 @ CREATE TABLE IF NOT EXISTS "%w".bblob(
39 @ blobid INTEGER PRIMARY KEY, -- Blob ID
40 @ uuid TEXT NOT NULL, -- SHA1 hash of expanded blob
41 @ sz INT NOT NULL, -- Size of blob after expansion
42 @ delta ANY, -- Delta compression basis, or NULL
43 @ notes TEXT, -- Description of content
44 @ data BLOB -- compressed content
45 @ );
@@ -439,19 +439,19 @@
439 " WHERE bix.delta=%d"
440 " AND bix.blobid=bblob.blobid;",
441 iSrc
442 );
443 while( db_step(&q)==SQLITE_ROW ){
444 Blob h1, h2, c1, c2;
445 int rid;
446 blob_zero(&h1);
447 db_column_blob(&q, 0, &h1);
448 blob_zero(&c1);
449 db_column_blob(&q, 1, &c1);
450 blob_uncompress(&c1, &c1);
451 blob_zero(&c2);
452 if( db_column_type(&q,2)==SQLITE_TEXT && db_column_bytes(&q,2)==40 ){
453 Blob basis;
454 rid = db_int(0,"SELECT rid FROM blob WHERE uuid=%Q",
455 db_column_text(&q,2));
456 content_get(rid, &basis);
457 blob_delta_apply(&basis, &c1, &c2);
@@ -461,16 +461,13 @@
461 blob_delta_apply(pBasis, &c1, &c2);
462 blob_reset(&c1);
463 }else{
464 c2 = c1;
465 }
466 sha1sum_blob(&c2, &h2);
467 if( blob_compare(&h1, &h2)!=0 ){
468 fossil_fatal("SHA1 hash mismatch - wanted %s, got %s",
469 blob_str(&h1), blob_str(&h2));
470 }
471 blob_reset(&h2);
472 rid = content_put_ex(&c2, blob_str(&h1), 0, 0, isPriv);
473 if( rid==0 ){
474 fossil_fatal("%s", g.zErrMsg);
475 }else{
476 if( !isPriv ) content_make_public(rid);
@@ -491,11 +488,11 @@
491 static void bundle_extract_item(
492 int blobid, /* ID of the item to extract */
493 Blob *pOut /* Write the content into this blob */
494 ){
495 Stmt q;
496 Blob x, basis, h1, h2;
497 static Bag busy;
498
499 db_prepare(&q, "SELECT uuid, delta, data FROM bblob"
500 " WHERE blobid=%d", blobid);
501 if( db_step(&q)!=SQLITE_ROW ){
@@ -525,17 +522,14 @@
525 }else{
526 *pOut = x;
527 }
528 blob_zero(&h1);
529 db_column_blob(&q, 0, &h1);
530 sha1sum_blob(pOut, &h2);
531 if( blob_compare(&h1, &h2)!=0 ){
532 fossil_fatal("SHA1 hash mismatch - wanted %s, got %s",
533 blob_str(&h1), blob_str(&h2));
534 }
535 blob_reset(&h1);
536 blob_reset(&h2);
537 bag_remove(&busy, blobid);
538 db_finalize(&q);
539 }
540
541 /* fossil bundle cat BUNDLE UUID...
@@ -597,12 +591,13 @@
597 ** repo, then the delta encodings cannot be decoded and the bundle cannot
598 ** be extracted. */
599 zMissingDeltas = db_text(0,
600 "SELECT group_concat(substr(delta,1,10),' ')"
601 " FROM bblob"
602 " WHERE typeof(delta)='text' AND length(delta)=40"
603 " AND NOT EXISTS(SELECT 1 FROM blob WHERE uuid=bblob.delta)");
 
604 if( zMissingDeltas && zMissingDeltas[0] ){
605 fossil_fatal("delta basis artifacts not found in repository: %s",
606 zMissingDeltas);
607 }
608
609
--- src/bundle.c
+++ src/bundle.c
@@ -35,11 +35,11 @@
35 @ bcname TEXT,
36 @ bcvalue ANY
37 @ );
38 @ CREATE TABLE IF NOT EXISTS "%w".bblob(
39 @ blobid INTEGER PRIMARY KEY, -- Blob ID
40 @ uuid TEXT NOT NULL, -- hash of expanded blob
41 @ sz INT NOT NULL, -- Size of blob after expansion
42 @ delta ANY, -- Delta compression basis, or NULL
43 @ notes TEXT, -- Description of content
44 @ data BLOB -- compressed content
45 @ );
@@ -439,19 +439,19 @@
439 " WHERE bix.delta=%d"
440 " AND bix.blobid=bblob.blobid;",
441 iSrc
442 );
443 while( db_step(&q)==SQLITE_ROW ){
444 Blob h1, c1, c2;
445 int rid;
446 blob_zero(&h1);
447 db_column_blob(&q, 0, &h1);
448 blob_zero(&c1);
449 db_column_blob(&q, 1, &c1);
450 blob_uncompress(&c1, &c1);
451 blob_zero(&c2);
452 if( db_column_type(&q,2)==SQLITE_TEXT && db_column_bytes(&q,2)>=HNAME_MIN ){
453 Blob basis;
454 rid = db_int(0,"SELECT rid FROM blob WHERE uuid=%Q",
455 db_column_text(&q,2));
456 content_get(rid, &basis);
457 blob_delta_apply(&basis, &c1, &c2);
@@ -461,16 +461,13 @@
461 blob_delta_apply(pBasis, &c1, &c2);
462 blob_reset(&c1);
463 }else{
464 c2 = c1;
465 }
466 if( hname_verify_hash(&c2, blob_buffer(&h1), blob_size(&h1))==0 ){
467 fossil_fatal("artifact hash error on %b", &h1);
 
 
468 }
 
469 rid = content_put_ex(&c2, blob_str(&h1), 0, 0, isPriv);
470 if( rid==0 ){
471 fossil_fatal("%s", g.zErrMsg);
472 }else{
473 if( !isPriv ) content_make_public(rid);
@@ -491,11 +488,11 @@
488 static void bundle_extract_item(
489 int blobid, /* ID of the item to extract */
490 Blob *pOut /* Write the content into this blob */
491 ){
492 Stmt q;
493 Blob x, basis, h1;
494 static Bag busy;
495
496 db_prepare(&q, "SELECT uuid, delta, data FROM bblob"
497 " WHERE blobid=%d", blobid);
498 if( db_step(&q)!=SQLITE_ROW ){
@@ -525,17 +522,14 @@
522 }else{
523 *pOut = x;
524 }
525 blob_zero(&h1);
526 db_column_blob(&q, 0, &h1);
527 if( hname_verify_hash(pOut, blob_buffer(&h1), blob_size(&h1))==0 ){
528 fossil_fatal("incorrect hash for artifact %b", &h1);
 
 
529 }
530 blob_reset(&h1);
 
531 bag_remove(&busy, blobid);
532 db_finalize(&q);
533 }
534
535 /* fossil bundle cat BUNDLE UUID...
@@ -597,12 +591,13 @@
591 ** repo, then the delta encodings cannot be decoded and the bundle cannot
592 ** be extracted. */
593 zMissingDeltas = db_text(0,
594 "SELECT group_concat(substr(delta,1,10),' ')"
595 " FROM bblob"
596 " WHERE typeof(delta)='text' AND length(delta)>=%d"
597 " AND NOT EXISTS(SELECT 1 FROM blob WHERE uuid=bblob.delta)",
598 HNAME_MIN);
599 if( zMissingDeltas && zMissingDeltas[0] ){
600 fossil_fatal("delta basis artifacts not found in repository: %s",
601 zMissingDeltas);
602 }
603
604
+10 -10
--- src/checkin.c
+++ src/checkin.c
@@ -377,11 +377,11 @@
377377
** As a special case, the --no-merge option does not inhibit this default.
378378
** This default shows exactly the set of changes that would be checked
379379
** in by the commit command.
380380
**
381381
** If no filter options are used, or if the --merge option is used, the
382
-** SHA1 hash of each merge contributor check-in version is displayed at
382
+** artifact hash of each merge contributor check-in version is displayed at
383383
** the end of the report. The --no-merge option is useful to display the
384384
** default set of changed files without the merge contributors.
385385
**
386386
** If change type classification is enabled, each output line starts with
387387
** a code describing the file's change type, e.g. EDITED or RENAMED. It
@@ -412,11 +412,11 @@
412412
**
413413
** General options:
414414
** --abs-paths Display absolute pathnames.
415415
** --rel-paths Display pathnames relative to the current working
416416
** directory.
417
-** --sha1sum Verify file status using SHA1 hashing rather than
417
+** --hash Verify file status using hashing rather than
418418
** relying on file mtimes.
419419
** --case-sensitive <BOOL> Override case-sensitive setting.
420420
** --dotfiles Include unmanaged files beginning with a dot.
421421
** --ignore <CSG> Ignore unmanaged files matching CSG glob patterns.
422422
** --no-dir-symlinks Disables support for directory symlinks.
@@ -464,11 +464,11 @@
464464
{"no-merge", C_MERGE }, {"no-classify", C_CLASSIFY },
465465
};
466466
467467
Blob report = BLOB_INITIALIZER;
468468
enum {CHANGES, STATUS} command = *g.argv[1]=='s' ? STATUS : CHANGES;
469
- int useSha1sum = find_option("sha1sum", 0, 0)!=0;
469
+ int useHash = find_option("hash", 0, 0)!=0;
470470
int showHdr = command==CHANGES && find_option("header", 0, 0);
471471
int verboseFlag = command==CHANGES && find_option("verbose", "v", 0);
472472
const char *zIgnoreFlag = find_option("ignore", 0, 1);
473473
unsigned scanFlags = 0;
474474
unsigned flags = 0;
@@ -528,11 +528,11 @@
528528
529529
/* We should be done with options. */
530530
verify_all_options();
531531
532532
/* Check for changed files. */
533
- vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
533
+ vfile_check_signature(vid, useHash ? CKSIG_HASH : 0);
534534
535535
/* Search for unmanaged files if requested. */
536536
if( flags & C_EXTRA ){
537537
Glob *pIgnore = glob_create(zIgnoreFlag);
538538
locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
@@ -1985,12 +1985,12 @@
19851985
** The --private option creates a private check-in that is never synced.
19861986
** Children of private check-ins are automatically private.
19871987
**
19881988
** The --tag option applies the symbolic tag name to the check-in.
19891989
**
1990
-** The --sha1sum option detects edited files by computing each file's
1991
-** SHA1 hash rather than just checking for changes to its size or mtime.
1990
+** The --hash option detects edited files by computing each file's
1991
+** artifact hash rather than just checking for changes to its size or mtime.
19921992
**
19931993
** Options:
19941994
** --allow-conflict allow unresolved merge conflicts
19951995
** --allow-empty allow a commit with no changes
19961996
** --allow-fork allow the commit to fork
@@ -2010,11 +2010,11 @@
20102010
** input and assumes an answer of 'No' for every
20112011
** question.
20122012
** --no-warnings omit all warnings about file contents
20132013
** --nosign do not attempt to sign this commit with gpg
20142014
** --private do not sync changes and their descendants
2015
-** --sha1sum verify file status using SHA1 hashing rather
2015
+** --hash verify file status using hashing rather
20162016
** than relying on file mtimes
20172017
** --tag TAG-NAME assign given tag TAG-NAME to the check-in
20182018
** --date-override DATETIME DATE to use instead of 'now'
20192019
** --user-override USER USER to use instead of the current default
20202020
**
@@ -2033,11 +2033,11 @@
20332033
int nvid; /* Blob-id of the new check-in */
20342034
Blob comment; /* Check-in comment */
20352035
const char *zComment; /* Check-in comment */
20362036
Stmt q; /* Various queries */
20372037
char *zUuid; /* UUID of the new check-in */
2038
- int useSha1sum = 0; /* True to verify file status using SHA1 hashing */
2038
+ int useHash = 0; /* True to verify file status using hashing */
20392039
int noSign = 0; /* True to omit signing the manifest using GPG */
20402040
int isAMerge = 0; /* True if checking in a merge */
20412041
int noWarningFlag = 0; /* True if skipping all warnings */
20422042
int noPrompt = 0; /* True if skipping all prompts */
20432043
int forceFlag = 0; /* Undocumented: Disables all checks */
@@ -2068,11 +2068,11 @@
20682068
Blob ans;
20692069
char cReply;
20702070
20712071
memset(&sCiInfo, 0, sizeof(sCiInfo));
20722072
url_proxy_options();
2073
- useSha1sum = find_option("sha1sum", 0, 0)!=0;
2073
+ useHash = find_option("hash", 0, 0)!=0;
20742074
noSign = find_option("nosign",0,0)!=0;
20752075
forceDelta = find_option("delta",0,0)!=0;
20762076
forceBaseline = find_option("baseline",0,0)!=0;
20772077
if( forceDelta && forceBaseline ){
20782078
fossil_fatal("cannot use --delta and --baseline together");
@@ -2232,11 +2232,11 @@
22322232
*/
22332233
if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){
22342234
fossil_fatal("no such user: %s", g.zLogin);
22352235
}
22362236
2237
- hasChanges = unsaved_changes(useSha1sum ? CKSIG_SHA1 : 0);
2237
+ hasChanges = unsaved_changes(useHash ? CKSIG_HASH : 0);
22382238
db_begin_transaction();
22392239
db_record_repository_filename(0);
22402240
if( hasChanges==0 && !isAMerge && !allowEmpty && !forceFlag ){
22412241
fossil_fatal("nothing has changed; use --allow-empty to override");
22422242
}
22432243
--- src/checkin.c
+++ src/checkin.c
@@ -377,11 +377,11 @@
377 ** As a special case, the --no-merge option does not inhibit this default.
378 ** This default shows exactly the set of changes that would be checked
379 ** in by the commit command.
380 **
381 ** If no filter options are used, or if the --merge option is used, the
382 ** SHA1 hash of each merge contributor check-in version is displayed at
383 ** the end of the report. The --no-merge option is useful to display the
384 ** default set of changed files without the merge contributors.
385 **
386 ** If change type classification is enabled, each output line starts with
387 ** a code describing the file's change type, e.g. EDITED or RENAMED. It
@@ -412,11 +412,11 @@
412 **
413 ** General options:
414 ** --abs-paths Display absolute pathnames.
415 ** --rel-paths Display pathnames relative to the current working
416 ** directory.
417 ** --sha1sum Verify file status using SHA1 hashing rather than
418 ** relying on file mtimes.
419 ** --case-sensitive <BOOL> Override case-sensitive setting.
420 ** --dotfiles Include unmanaged files beginning with a dot.
421 ** --ignore <CSG> Ignore unmanaged files matching CSG glob patterns.
422 ** --no-dir-symlinks Disables support for directory symlinks.
@@ -464,11 +464,11 @@
464 {"no-merge", C_MERGE }, {"no-classify", C_CLASSIFY },
465 };
466
467 Blob report = BLOB_INITIALIZER;
468 enum {CHANGES, STATUS} command = *g.argv[1]=='s' ? STATUS : CHANGES;
469 int useSha1sum = find_option("sha1sum", 0, 0)!=0;
470 int showHdr = command==CHANGES && find_option("header", 0, 0);
471 int verboseFlag = command==CHANGES && find_option("verbose", "v", 0);
472 const char *zIgnoreFlag = find_option("ignore", 0, 1);
473 unsigned scanFlags = 0;
474 unsigned flags = 0;
@@ -528,11 +528,11 @@
528
529 /* We should be done with options. */
530 verify_all_options();
531
532 /* Check for changed files. */
533 vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
534
535 /* Search for unmanaged files if requested. */
536 if( flags & C_EXTRA ){
537 Glob *pIgnore = glob_create(zIgnoreFlag);
538 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
@@ -1985,12 +1985,12 @@
1985 ** The --private option creates a private check-in that is never synced.
1986 ** Children of private check-ins are automatically private.
1987 **
1988 ** The --tag option applies the symbolic tag name to the check-in.
1989 **
1990 ** The --sha1sum option detects edited files by computing each file's
1991 ** SHA1 hash rather than just checking for changes to its size or mtime.
1992 **
1993 ** Options:
1994 ** --allow-conflict allow unresolved merge conflicts
1995 ** --allow-empty allow a commit with no changes
1996 ** --allow-fork allow the commit to fork
@@ -2010,11 +2010,11 @@
2010 ** input and assumes an answer of 'No' for every
2011 ** question.
2012 ** --no-warnings omit all warnings about file contents
2013 ** --nosign do not attempt to sign this commit with gpg
2014 ** --private do not sync changes and their descendants
2015 ** --sha1sum verify file status using SHA1 hashing rather
2016 ** than relying on file mtimes
2017 ** --tag TAG-NAME assign given tag TAG-NAME to the check-in
2018 ** --date-override DATETIME DATE to use instead of 'now'
2019 ** --user-override USER USER to use instead of the current default
2020 **
@@ -2033,11 +2033,11 @@
2033 int nvid; /* Blob-id of the new check-in */
2034 Blob comment; /* Check-in comment */
2035 const char *zComment; /* Check-in comment */
2036 Stmt q; /* Various queries */
2037 char *zUuid; /* UUID of the new check-in */
2038 int useSha1sum = 0; /* True to verify file status using SHA1 hashing */
2039 int noSign = 0; /* True to omit signing the manifest using GPG */
2040 int isAMerge = 0; /* True if checking in a merge */
2041 int noWarningFlag = 0; /* True if skipping all warnings */
2042 int noPrompt = 0; /* True if skipping all prompts */
2043 int forceFlag = 0; /* Undocumented: Disables all checks */
@@ -2068,11 +2068,11 @@
2068 Blob ans;
2069 char cReply;
2070
2071 memset(&sCiInfo, 0, sizeof(sCiInfo));
2072 url_proxy_options();
2073 useSha1sum = find_option("sha1sum", 0, 0)!=0;
2074 noSign = find_option("nosign",0,0)!=0;
2075 forceDelta = find_option("delta",0,0)!=0;
2076 forceBaseline = find_option("baseline",0,0)!=0;
2077 if( forceDelta && forceBaseline ){
2078 fossil_fatal("cannot use --delta and --baseline together");
@@ -2232,11 +2232,11 @@
2232 */
2233 if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){
2234 fossil_fatal("no such user: %s", g.zLogin);
2235 }
2236
2237 hasChanges = unsaved_changes(useSha1sum ? CKSIG_SHA1 : 0);
2238 db_begin_transaction();
2239 db_record_repository_filename(0);
2240 if( hasChanges==0 && !isAMerge && !allowEmpty && !forceFlag ){
2241 fossil_fatal("nothing has changed; use --allow-empty to override");
2242 }
2243
--- src/checkin.c
+++ src/checkin.c
@@ -377,11 +377,11 @@
377 ** As a special case, the --no-merge option does not inhibit this default.
378 ** This default shows exactly the set of changes that would be checked
379 ** in by the commit command.
380 **
381 ** If no filter options are used, or if the --merge option is used, the
382 ** artifact hash of each merge contributor check-in version is displayed at
383 ** the end of the report. The --no-merge option is useful to display the
384 ** default set of changed files without the merge contributors.
385 **
386 ** If change type classification is enabled, each output line starts with
387 ** a code describing the file's change type, e.g. EDITED or RENAMED. It
@@ -412,11 +412,11 @@
412 **
413 ** General options:
414 ** --abs-paths Display absolute pathnames.
415 ** --rel-paths Display pathnames relative to the current working
416 ** directory.
417 ** --hash Verify file status using hashing rather than
418 ** relying on file mtimes.
419 ** --case-sensitive <BOOL> Override case-sensitive setting.
420 ** --dotfiles Include unmanaged files beginning with a dot.
421 ** --ignore <CSG> Ignore unmanaged files matching CSG glob patterns.
422 ** --no-dir-symlinks Disables support for directory symlinks.
@@ -464,11 +464,11 @@
464 {"no-merge", C_MERGE }, {"no-classify", C_CLASSIFY },
465 };
466
467 Blob report = BLOB_INITIALIZER;
468 enum {CHANGES, STATUS} command = *g.argv[1]=='s' ? STATUS : CHANGES;
469 int useHash = find_option("hash", 0, 0)!=0;
470 int showHdr = command==CHANGES && find_option("header", 0, 0);
471 int verboseFlag = command==CHANGES && find_option("verbose", "v", 0);
472 const char *zIgnoreFlag = find_option("ignore", 0, 1);
473 unsigned scanFlags = 0;
474 unsigned flags = 0;
@@ -528,11 +528,11 @@
528
529 /* We should be done with options. */
530 verify_all_options();
531
532 /* Check for changed files. */
533 vfile_check_signature(vid, useHash ? CKSIG_HASH : 0);
534
535 /* Search for unmanaged files if requested. */
536 if( flags & C_EXTRA ){
537 Glob *pIgnore = glob_create(zIgnoreFlag);
538 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
@@ -1985,12 +1985,12 @@
1985 ** The --private option creates a private check-in that is never synced.
1986 ** Children of private check-ins are automatically private.
1987 **
1988 ** The --tag option applies the symbolic tag name to the check-in.
1989 **
1990 ** The --hash option detects edited files by computing each file's
1991 ** artifact hash rather than just checking for changes to its size or mtime.
1992 **
1993 ** Options:
1994 ** --allow-conflict allow unresolved merge conflicts
1995 ** --allow-empty allow a commit with no changes
1996 ** --allow-fork allow the commit to fork
@@ -2010,11 +2010,11 @@
2010 ** input and assumes an answer of 'No' for every
2011 ** question.
2012 ** --no-warnings omit all warnings about file contents
2013 ** --nosign do not attempt to sign this commit with gpg
2014 ** --private do not sync changes and their descendants
2015 ** --hash verify file status using hashing rather
2016 ** than relying on file mtimes
2017 ** --tag TAG-NAME assign given tag TAG-NAME to the check-in
2018 ** --date-override DATETIME DATE to use instead of 'now'
2019 ** --user-override USER USER to use instead of the current default
2020 **
@@ -2033,11 +2033,11 @@
2033 int nvid; /* Blob-id of the new check-in */
2034 Blob comment; /* Check-in comment */
2035 const char *zComment; /* Check-in comment */
2036 Stmt q; /* Various queries */
2037 char *zUuid; /* UUID of the new check-in */
2038 int useHash = 0; /* True to verify file status using hashing */
2039 int noSign = 0; /* True to omit signing the manifest using GPG */
2040 int isAMerge = 0; /* True if checking in a merge */
2041 int noWarningFlag = 0; /* True if skipping all warnings */
2042 int noPrompt = 0; /* True if skipping all prompts */
2043 int forceFlag = 0; /* Undocumented: Disables all checks */
@@ -2068,11 +2068,11 @@
2068 Blob ans;
2069 char cReply;
2070
2071 memset(&sCiInfo, 0, sizeof(sCiInfo));
2072 url_proxy_options();
2073 useHash = find_option("hash", 0, 0)!=0;
2074 noSign = find_option("nosign",0,0)!=0;
2075 forceDelta = find_option("delta",0,0)!=0;
2076 forceBaseline = find_option("baseline",0,0)!=0;
2077 if( forceDelta && forceBaseline ){
2078 fossil_fatal("cannot use --delta and --baseline together");
@@ -2232,11 +2232,11 @@
2232 */
2233 if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){
2234 fossil_fatal("no such user: %s", g.zLogin);
2235 }
2236
2237 hasChanges = unsaved_changes(useHash ? CKSIG_HASH : 0);
2238 db_begin_transaction();
2239 db_record_repository_filename(0);
2240 if( hasChanges==0 && !isAMerge && !allowEmpty && !forceFlag ){
2241 fossil_fatal("nothing has changed; use --allow-empty to override");
2242 }
2243
+3 -6
--- src/checkout.c
+++ src/checkout.c
@@ -134,24 +134,19 @@
134134
** "manifest.tags".
135135
*/
136136
void manifest_to_disk(int vid){
137137
char *zManFile;
138138
Blob manifest;
139
- Blob hash;
140139
Blob taglist;
141140
int flg;
142141
143142
flg = db_get_manifest_setting();
144143
145
- if( flg & (MFESTFLG_RAW|MFESTFLG_UUID) ){
144
+ if( flg & MFESTFLG_RAW ){
146145
blob_zero(&manifest);
147146
content_get(vid, &manifest);
148
- blob_zero(&hash);
149
- sha1sum_blob(&manifest, &hash);
150147
sterilize_manifest(&manifest);
151
- }
152
- if( flg & MFESTFLG_RAW ){
153148
zManFile = mprintf("%smanifest", g.zLocalRoot);
154149
blob_write_to_file(&manifest, zManFile);
155150
free(zManFile);
156151
}else{
157152
if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){
@@ -159,11 +154,13 @@
159154
file_delete(zManFile);
160155
free(zManFile);
161156
}
162157
}
163158
if( flg & MFESTFLG_UUID ){
159
+ Blob hash;
164160
zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
161
+ blob_set_dynamic(&hash, rid_to_uuid(vid));
165162
blob_append(&hash, "\n", 1);
166163
blob_write_to_file(&hash, zManFile);
167164
free(zManFile);
168165
blob_reset(&hash);
169166
}else{
170167
--- src/checkout.c
+++ src/checkout.c
@@ -134,24 +134,19 @@
134 ** "manifest.tags".
135 */
136 void manifest_to_disk(int vid){
137 char *zManFile;
138 Blob manifest;
139 Blob hash;
140 Blob taglist;
141 int flg;
142
143 flg = db_get_manifest_setting();
144
145 if( flg & (MFESTFLG_RAW|MFESTFLG_UUID) ){
146 blob_zero(&manifest);
147 content_get(vid, &manifest);
148 blob_zero(&hash);
149 sha1sum_blob(&manifest, &hash);
150 sterilize_manifest(&manifest);
151 }
152 if( flg & MFESTFLG_RAW ){
153 zManFile = mprintf("%smanifest", g.zLocalRoot);
154 blob_write_to_file(&manifest, zManFile);
155 free(zManFile);
156 }else{
157 if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){
@@ -159,11 +154,13 @@
159 file_delete(zManFile);
160 free(zManFile);
161 }
162 }
163 if( flg & MFESTFLG_UUID ){
 
164 zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
 
165 blob_append(&hash, "\n", 1);
166 blob_write_to_file(&hash, zManFile);
167 free(zManFile);
168 blob_reset(&hash);
169 }else{
170
--- src/checkout.c
+++ src/checkout.c
@@ -134,24 +134,19 @@
134 ** "manifest.tags".
135 */
136 void manifest_to_disk(int vid){
137 char *zManFile;
138 Blob manifest;
 
139 Blob taglist;
140 int flg;
141
142 flg = db_get_manifest_setting();
143
144 if( flg & MFESTFLG_RAW ){
145 blob_zero(&manifest);
146 content_get(vid, &manifest);
 
 
147 sterilize_manifest(&manifest);
 
 
148 zManFile = mprintf("%smanifest", g.zLocalRoot);
149 blob_write_to_file(&manifest, zManFile);
150 free(zManFile);
151 }else{
152 if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){
@@ -159,11 +154,13 @@
154 file_delete(zManFile);
155 free(zManFile);
156 }
157 }
158 if( flg & MFESTFLG_UUID ){
159 Blob hash;
160 zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
161 blob_set_dynamic(&hash, rid_to_uuid(vid));
162 blob_append(&hash, "\n", 1);
163 blob_write_to_file(&hash, zManFile);
164 free(zManFile);
165 blob_reset(&hash);
166 }else{
167
--- src/clone.c
+++ src/clone.c
@@ -175,10 +175,11 @@
175175
db_initial_setup(0, 0, zDefaultUser);
176176
user_select();
177177
db_set("content-schema", CONTENT_SCHEMA, 0);
178178
db_set("aux-schema", AUX_SCHEMA_MAX, 0);
179179
db_set("rebuilt", get_version(), 0);
180
+ db_unset("hash-policy", 0);
180181
remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, g.argv[2]);
181182
url_remember();
182183
if( g.zSSLIdentity!=0 ){
183184
/* If the --ssl-identity option was specified, store it as a setting */
184185
Blob fn;
185186
--- src/clone.c
+++ src/clone.c
@@ -175,10 +175,11 @@
175 db_initial_setup(0, 0, zDefaultUser);
176 user_select();
177 db_set("content-schema", CONTENT_SCHEMA, 0);
178 db_set("aux-schema", AUX_SCHEMA_MAX, 0);
179 db_set("rebuilt", get_version(), 0);
 
180 remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, g.argv[2]);
181 url_remember();
182 if( g.zSSLIdentity!=0 ){
183 /* If the --ssl-identity option was specified, store it as a setting */
184 Blob fn;
185
--- src/clone.c
+++ src/clone.c
@@ -175,10 +175,11 @@
175 db_initial_setup(0, 0, zDefaultUser);
176 user_select();
177 db_set("content-schema", CONTENT_SCHEMA, 0);
178 db_set("aux-schema", AUX_SCHEMA_MAX, 0);
179 db_set("rebuilt", get_version(), 0);
180 db_unset("hash-policy", 0);
181 remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, g.argv[2]);
182 url_remember();
183 if( g.zSSLIdentity!=0 ){
184 /* If the --ssl-identity option was specified, store it as a setting */
185 Blob fn;
186
--- src/config.h
+++ src/config.h
@@ -38,10 +38,15 @@
3838
#endif
3939
4040
#ifdef HAVE_AUTOCONFIG_H
4141
#include "autoconfig.h"
4242
#endif
43
+
44
+/* Enable the hardened SHA1 implemenation by default */
45
+#ifndef FOSSIL_HARDENED_SHA1
46
+# define FOSSIL_HARDENED_SHA1 1
47
+#endif
4348
4449
#ifndef _RC_COMPILE_
4550
4651
/*
4752
** System header files used by all modules
@@ -168,10 +173,11 @@
168173
# endif
169174
#endif
170175
171176
#if !defined(_RC_COMPILE_) && !defined(SQLITE_AMALGAMATION)
172177
178
+#include <stdint.h>
173179
#include "sqlite3.h"
174180
175181
/*
176182
** On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257.
177183
*/
178184
--- src/config.h
+++ src/config.h
@@ -38,10 +38,15 @@
38 #endif
39
40 #ifdef HAVE_AUTOCONFIG_H
41 #include "autoconfig.h"
42 #endif
 
 
 
 
 
43
44 #ifndef _RC_COMPILE_
45
46 /*
47 ** System header files used by all modules
@@ -168,10 +173,11 @@
168 # endif
169 #endif
170
171 #if !defined(_RC_COMPILE_) && !defined(SQLITE_AMALGAMATION)
172
 
173 #include "sqlite3.h"
174
175 /*
176 ** On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257.
177 */
178
--- src/config.h
+++ src/config.h
@@ -38,10 +38,15 @@
38 #endif
39
40 #ifdef HAVE_AUTOCONFIG_H
41 #include "autoconfig.h"
42 #endif
43
44 /* Enable the hardened SHA1 implemenation by default */
45 #ifndef FOSSIL_HARDENED_SHA1
46 # define FOSSIL_HARDENED_SHA1 1
47 #endif
48
49 #ifndef _RC_COMPILE_
50
51 /*
52 ** System header files used by all modules
@@ -168,10 +173,11 @@
173 # endif
174 #endif
175
176 #if !defined(_RC_COMPILE_) && !defined(SQLITE_AMALGAMATION)
177
178 #include <stdint.h>
179 #include "sqlite3.h"
180
181 /*
182 ** On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257.
183 */
184
--- src/configure.c
+++ src/configure.c
@@ -129,10 +129,11 @@
129129
{ "empty-dirs", CONFIGSET_PROJ },
130130
{ "allow-symlinks", CONFIGSET_PROJ },
131131
{ "dotfiles", CONFIGSET_PROJ },
132132
{ "parent-project-code", CONFIGSET_PROJ },
133133
{ "parent-project-name", CONFIGSET_PROJ },
134
+ { "hash-policy", CONFIGSET_PROJ },
134135
135136
#ifdef FOSSIL_ENABLE_LEGACY_MV_RM
136137
{ "mv-rm-files", CONFIGSET_PROJ },
137138
#endif
138139
139140
--- src/configure.c
+++ src/configure.c
@@ -129,10 +129,11 @@
129 { "empty-dirs", CONFIGSET_PROJ },
130 { "allow-symlinks", CONFIGSET_PROJ },
131 { "dotfiles", CONFIGSET_PROJ },
132 { "parent-project-code", CONFIGSET_PROJ },
133 { "parent-project-name", CONFIGSET_PROJ },
 
134
135 #ifdef FOSSIL_ENABLE_LEGACY_MV_RM
136 { "mv-rm-files", CONFIGSET_PROJ },
137 #endif
138
139
--- src/configure.c
+++ src/configure.c
@@ -129,10 +129,11 @@
129 { "empty-dirs", CONFIGSET_PROJ },
130 { "allow-symlinks", CONFIGSET_PROJ },
131 { "dotfiles", CONFIGSET_PROJ },
132 { "parent-project-code", CONFIGSET_PROJ },
133 { "parent-project-name", CONFIGSET_PROJ },
134 { "hash-policy", CONFIGSET_PROJ },
135
136 #ifdef FOSSIL_ENABLE_LEGACY_MV_RM
137 { "mv-rm-files", CONFIGSET_PROJ },
138 #endif
139
140
+22 -12
--- src/content.c
+++ src/content.c
@@ -312,11 +312,11 @@
312312
/*
313313
** COMMAND: artifact*
314314
**
315315
** Usage: %fossil artifact ARTIFACT-ID ?OUTPUT-FILENAME? ?OPTIONS?
316316
**
317
-** Extract an artifact by its SHA1 hash and write the results on
317
+** Extract an artifact by its artifact hash and write the results on
318318
** standard output, or if the optional 4th argument is given, in
319319
** the named output file.
320320
**
321321
** Options:
322322
** -R|--repository FILE Extract artifacts from repository FILE
@@ -497,11 +497,11 @@
497497
** to be responsible for pBlob. This routine does *not* take over
498498
** responsibility for freeing pBlob.
499499
*/
500500
int content_put_ex(
501501
Blob *pBlob, /* Content to add to the repository */
502
- const char *zUuid, /* SHA1 hash of reconstructed pBlob */
502
+ const char *zUuid, /* artifact hash of reconstructed pBlob */
503503
int srcId, /* pBlob is a delta from this entry */
504504
int nBlob, /* pBlob is compressed. Original size is this */
505505
int isPrivate /* The content should be marked private */
506506
){
507507
int size;
@@ -513,25 +513,38 @@
513513
int isDephantomize = 0;
514514
515515
assert( g.repositoryOpen );
516516
assert( pBlob!=0 );
517517
assert( srcId==0 || zUuid!=0 );
518
+ db_begin_transaction();
518519
if( zUuid==0 ){
519520
assert( nBlob==0 );
520
- sha1sum_blob(pBlob, &hash);
521
+ /* First check the auxiliary hash to see if there is already an artifact
522
+ ** that uses the auxiliary hash name */
523
+ hname_hash(pBlob, 1, &hash);
524
+ rid = fast_uuid_to_rid(blob_str(&hash));
525
+ if( rid==0 ){
526
+ /* No existing artifact with the auxiliary hash name. Therefore, use
527
+ ** the primary hash name. */
528
+ blob_reset(&hash);
529
+ hname_hash(pBlob, 0, &hash);
530
+ }
521531
}else{
522532
blob_init(&hash, zUuid, -1);
533
+ }
534
+ if( g.eHashPolicy==HPOLICY_AUTO && blob_size(&hash)>HNAME_LEN_SHA1 ){
535
+ g.eHashPolicy = HPOLICY_SHA3;
536
+ db_set_int("hash-policy", HPOLICY_SHA3, 0);
523537
}
524538
if( nBlob ){
525539
size = nBlob;
526540
}else{
527541
size = blob_size(pBlob);
528542
if( srcId ){
529543
size = delta_output_size(blob_buffer(pBlob), size);
530544
}
531545
}
532
- db_begin_transaction();
533546
534547
/* Check to see if the entry already exists and if it does whether
535548
** or not the entry is a phantom
536549
*/
537550
db_prepare(&s1, "SELECT rid, size FROM blob WHERE uuid=%B", &hash);
@@ -868,11 +881,10 @@
868881
** so forth, reporting any errors found.
869882
*/
870883
void test_integrity(void){
871884
Stmt q;
872885
Blob content;
873
- Blob cksum;
874886
int n1 = 0;
875887
int n2 = 0;
876888
int nErr = 0;
877889
int total;
878890
int nCA = 0;
@@ -905,10 +917,11 @@
905917
db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid");
906918
total = db_int(0, "SELECT max(rid) FROM blob");
907919
while( db_step(&q)==SQLITE_ROW ){
908920
int rid = db_column_int(&q, 0);
909921
const char *zUuid = db_column_text(&q, 1);
922
+ int nUuid = db_column_bytes(&q, 1);
910923
int size = db_column_int(&q, 2);
911924
n1++;
912925
fossil_print(" %d/%d\r", n1, total);
913926
fflush(stdout);
914927
if( size<0 ){
@@ -919,14 +932,12 @@
919932
if( blob_size(&content)!=size ){
920933
fossil_print("size mismatch on artifact %d: wanted %d but got %d\n",
921934
rid, size, blob_size(&content));
922935
nErr++;
923936
}
924
- sha1sum_blob(&content, &cksum);
925
- if( fossil_strcmp(blob_str(&cksum), zUuid)!=0 ){
926
- fossil_print("wrong hash on artifact %d: wanted %s but got %s\n",
927
- rid, zUuid, blob_str(&cksum));
937
+ if( !hname_verify_hash(&content, zUuid, nUuid) ){
938
+ fossil_print("wrong hash on artifact %d\n",rid);
928939
nErr++;
929940
}
930941
if( bParse && looks_like_control_artifact(&content) ){
931942
Blob err;
932943
int i, n;
@@ -941,11 +952,11 @@
941952
memcpy(zFirstLine, z, i);
942953
zFirstLine[i] = 0;
943954
p = manifest_parse(&content, 0, &err);
944955
if( p==0 ){
945956
fossil_print("manifest_parse failed for %s:\n%s\n",
946
- blob_str(&cksum), blob_str(&err));
957
+ zUuid, blob_str(&err));
947958
if( strncmp(blob_str(&err), "line 1:", 7)==0 ){
948959
fossil_print("\"%s\"\n", zFirstLine);
949960
}
950961
}else{
951962
anCA[p->type]++;
@@ -954,11 +965,10 @@
954965
}
955966
blob_reset(&err);
956967
}else{
957968
blob_reset(&content);
958969
}
959
- blob_reset(&cksum);
960970
n2++;
961971
}
962972
db_finalize(&q);
963973
fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
964974
n2, n1, nErr);
@@ -1157,11 +1167,11 @@
11571167
**
11581168
** WARNING: You must run "fossil rebuild" after this command to rebuild
11591169
** the metadata.
11601170
**
11611171
** Note that the arguments are the integer raw RID values from the BLOB table,
1162
-** not SHA1 hashs or labels.
1172
+** not artifact hashs or labels.
11631173
*/
11641174
void test_content_erase(void){
11651175
int i;
11661176
Blob x;
11671177
char c;
11681178
--- src/content.c
+++ src/content.c
@@ -312,11 +312,11 @@
312 /*
313 ** COMMAND: artifact*
314 **
315 ** Usage: %fossil artifact ARTIFACT-ID ?OUTPUT-FILENAME? ?OPTIONS?
316 **
317 ** Extract an artifact by its SHA1 hash and write the results on
318 ** standard output, or if the optional 4th argument is given, in
319 ** the named output file.
320 **
321 ** Options:
322 ** -R|--repository FILE Extract artifacts from repository FILE
@@ -497,11 +497,11 @@
497 ** to be responsible for pBlob. This routine does *not* take over
498 ** responsibility for freeing pBlob.
499 */
500 int content_put_ex(
501 Blob *pBlob, /* Content to add to the repository */
502 const char *zUuid, /* SHA1 hash of reconstructed pBlob */
503 int srcId, /* pBlob is a delta from this entry */
504 int nBlob, /* pBlob is compressed. Original size is this */
505 int isPrivate /* The content should be marked private */
506 ){
507 int size;
@@ -513,25 +513,38 @@
513 int isDephantomize = 0;
514
515 assert( g.repositoryOpen );
516 assert( pBlob!=0 );
517 assert( srcId==0 || zUuid!=0 );
 
518 if( zUuid==0 ){
519 assert( nBlob==0 );
520 sha1sum_blob(pBlob, &hash);
 
 
 
 
 
 
 
 
 
521 }else{
522 blob_init(&hash, zUuid, -1);
 
 
 
 
523 }
524 if( nBlob ){
525 size = nBlob;
526 }else{
527 size = blob_size(pBlob);
528 if( srcId ){
529 size = delta_output_size(blob_buffer(pBlob), size);
530 }
531 }
532 db_begin_transaction();
533
534 /* Check to see if the entry already exists and if it does whether
535 ** or not the entry is a phantom
536 */
537 db_prepare(&s1, "SELECT rid, size FROM blob WHERE uuid=%B", &hash);
@@ -868,11 +881,10 @@
868 ** so forth, reporting any errors found.
869 */
870 void test_integrity(void){
871 Stmt q;
872 Blob content;
873 Blob cksum;
874 int n1 = 0;
875 int n2 = 0;
876 int nErr = 0;
877 int total;
878 int nCA = 0;
@@ -905,10 +917,11 @@
905 db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid");
906 total = db_int(0, "SELECT max(rid) FROM blob");
907 while( db_step(&q)==SQLITE_ROW ){
908 int rid = db_column_int(&q, 0);
909 const char *zUuid = db_column_text(&q, 1);
 
910 int size = db_column_int(&q, 2);
911 n1++;
912 fossil_print(" %d/%d\r", n1, total);
913 fflush(stdout);
914 if( size<0 ){
@@ -919,14 +932,12 @@
919 if( blob_size(&content)!=size ){
920 fossil_print("size mismatch on artifact %d: wanted %d but got %d\n",
921 rid, size, blob_size(&content));
922 nErr++;
923 }
924 sha1sum_blob(&content, &cksum);
925 if( fossil_strcmp(blob_str(&cksum), zUuid)!=0 ){
926 fossil_print("wrong hash on artifact %d: wanted %s but got %s\n",
927 rid, zUuid, blob_str(&cksum));
928 nErr++;
929 }
930 if( bParse && looks_like_control_artifact(&content) ){
931 Blob err;
932 int i, n;
@@ -941,11 +952,11 @@
941 memcpy(zFirstLine, z, i);
942 zFirstLine[i] = 0;
943 p = manifest_parse(&content, 0, &err);
944 if( p==0 ){
945 fossil_print("manifest_parse failed for %s:\n%s\n",
946 blob_str(&cksum), blob_str(&err));
947 if( strncmp(blob_str(&err), "line 1:", 7)==0 ){
948 fossil_print("\"%s\"\n", zFirstLine);
949 }
950 }else{
951 anCA[p->type]++;
@@ -954,11 +965,10 @@
954 }
955 blob_reset(&err);
956 }else{
957 blob_reset(&content);
958 }
959 blob_reset(&cksum);
960 n2++;
961 }
962 db_finalize(&q);
963 fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
964 n2, n1, nErr);
@@ -1157,11 +1167,11 @@
1157 **
1158 ** WARNING: You must run "fossil rebuild" after this command to rebuild
1159 ** the metadata.
1160 **
1161 ** Note that the arguments are the integer raw RID values from the BLOB table,
1162 ** not SHA1 hashs or labels.
1163 */
1164 void test_content_erase(void){
1165 int i;
1166 Blob x;
1167 char c;
1168
--- src/content.c
+++ src/content.c
@@ -312,11 +312,11 @@
312 /*
313 ** COMMAND: artifact*
314 **
315 ** Usage: %fossil artifact ARTIFACT-ID ?OUTPUT-FILENAME? ?OPTIONS?
316 **
317 ** Extract an artifact by its artifact hash and write the results on
318 ** standard output, or if the optional 4th argument is given, in
319 ** the named output file.
320 **
321 ** Options:
322 ** -R|--repository FILE Extract artifacts from repository FILE
@@ -497,11 +497,11 @@
497 ** to be responsible for pBlob. This routine does *not* take over
498 ** responsibility for freeing pBlob.
499 */
500 int content_put_ex(
501 Blob *pBlob, /* Content to add to the repository */
502 const char *zUuid, /* artifact hash of reconstructed pBlob */
503 int srcId, /* pBlob is a delta from this entry */
504 int nBlob, /* pBlob is compressed. Original size is this */
505 int isPrivate /* The content should be marked private */
506 ){
507 int size;
@@ -513,25 +513,38 @@
513 int isDephantomize = 0;
514
515 assert( g.repositoryOpen );
516 assert( pBlob!=0 );
517 assert( srcId==0 || zUuid!=0 );
518 db_begin_transaction();
519 if( zUuid==0 ){
520 assert( nBlob==0 );
521 /* First check the auxiliary hash to see if there is already an artifact
522 ** that uses the auxiliary hash name */
523 hname_hash(pBlob, 1, &hash);
524 rid = fast_uuid_to_rid(blob_str(&hash));
525 if( rid==0 ){
526 /* No existing artifact with the auxiliary hash name. Therefore, use
527 ** the primary hash name. */
528 blob_reset(&hash);
529 hname_hash(pBlob, 0, &hash);
530 }
531 }else{
532 blob_init(&hash, zUuid, -1);
533 }
534 if( g.eHashPolicy==HPOLICY_AUTO && blob_size(&hash)>HNAME_LEN_SHA1 ){
535 g.eHashPolicy = HPOLICY_SHA3;
536 db_set_int("hash-policy", HPOLICY_SHA3, 0);
537 }
538 if( nBlob ){
539 size = nBlob;
540 }else{
541 size = blob_size(pBlob);
542 if( srcId ){
543 size = delta_output_size(blob_buffer(pBlob), size);
544 }
545 }
 
546
547 /* Check to see if the entry already exists and if it does whether
548 ** or not the entry is a phantom
549 */
550 db_prepare(&s1, "SELECT rid, size FROM blob WHERE uuid=%B", &hash);
@@ -868,11 +881,10 @@
881 ** so forth, reporting any errors found.
882 */
883 void test_integrity(void){
884 Stmt q;
885 Blob content;
 
886 int n1 = 0;
887 int n2 = 0;
888 int nErr = 0;
889 int total;
890 int nCA = 0;
@@ -905,10 +917,11 @@
917 db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid");
918 total = db_int(0, "SELECT max(rid) FROM blob");
919 while( db_step(&q)==SQLITE_ROW ){
920 int rid = db_column_int(&q, 0);
921 const char *zUuid = db_column_text(&q, 1);
922 int nUuid = db_column_bytes(&q, 1);
923 int size = db_column_int(&q, 2);
924 n1++;
925 fossil_print(" %d/%d\r", n1, total);
926 fflush(stdout);
927 if( size<0 ){
@@ -919,14 +932,12 @@
932 if( blob_size(&content)!=size ){
933 fossil_print("size mismatch on artifact %d: wanted %d but got %d\n",
934 rid, size, blob_size(&content));
935 nErr++;
936 }
937 if( !hname_verify_hash(&content, zUuid, nUuid) ){
938 fossil_print("wrong hash on artifact %d\n",rid);
 
 
939 nErr++;
940 }
941 if( bParse && looks_like_control_artifact(&content) ){
942 Blob err;
943 int i, n;
@@ -941,11 +952,11 @@
952 memcpy(zFirstLine, z, i);
953 zFirstLine[i] = 0;
954 p = manifest_parse(&content, 0, &err);
955 if( p==0 ){
956 fossil_print("manifest_parse failed for %s:\n%s\n",
957 zUuid, blob_str(&err));
958 if( strncmp(blob_str(&err), "line 1:", 7)==0 ){
959 fossil_print("\"%s\"\n", zFirstLine);
960 }
961 }else{
962 anCA[p->type]++;
@@ -954,11 +965,10 @@
965 }
966 blob_reset(&err);
967 }else{
968 blob_reset(&content);
969 }
 
970 n2++;
971 }
972 db_finalize(&q);
973 fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
974 n2, n1, nErr);
@@ -1157,11 +1167,11 @@
1167 **
1168 ** WARNING: You must run "fossil rebuild" after this command to rebuild
1169 ** the metadata.
1170 **
1171 ** Note that the arguments are the integer raw RID values from the BLOB table,
1172 ** not artifact hashs or labels.
1173 */
1174 void test_content_erase(void){
1175 int i;
1176 Blob x;
1177 char c;
1178
+28 -34
--- src/db.c
+++ src/db.c
@@ -2,11 +2,11 @@
22
** Copyright (c) 2006 D. Richard Hipp
33
**
44
** This program is free software; you can redistribute it and/or
55
** modify it under the terms of the Simplified BSD License (also
66
** known as the "2-Clause License" or "FreeBSD License".)
7
-
7
+**
88
** This program is distributed in the hope that it will be useful,
99
** but without any warranty; without even the implied warranty of
1010
** merchantability or fitness for a particular purpose.
1111
**
1212
** Author contact information:
@@ -1485,35 +1485,20 @@
14851485
g.repositoryOpen = 1;
14861486
/* Cache "allow-symlinks" option, because we'll need it on every stat call */
14871487
g.allowSymlinks = db_get_boolean("allow-symlinks",
14881488
db_allow_symlinks_by_default());
14891489
g.zAuxSchema = db_get("aux-schema","");
1490
-
1491
- /* Verify that the PLINK table has a new column added by the
1492
- ** 2014-11-28 schema change. Create it if necessary. This code
1493
- ** can be removed in the future, once all users have upgraded to the
1494
- ** 2014-11-28 or later schema.
1495
- */
1496
- if( !db_table_has_column("repository","plink","baseid") ){
1497
- db_multi_exec(
1498
- "ALTER TABLE repository.plink ADD COLUMN baseid;"
1499
- );
1500
- }
1501
-
1502
- /* Verify that the MLINK table has the newer columns added by the
1503
- ** 2015-01-24 schema change. Create them if necessary. This code
1504
- ** can be removed in the future, once all users have upgraded to the
1505
- ** 2015-01-24 or later schema.
1506
- */
1507
- if( !db_table_has_column("repository","mlink","isaux") ){
1508
- db_begin_transaction();
1509
- db_multi_exec(
1510
- "ALTER TABLE repository.mlink ADD COLUMN pmid INTEGER DEFAULT 0;"
1511
- "ALTER TABLE repository.mlink ADD COLUMN isaux BOOLEAN DEFAULT 0;"
1512
- );
1513
- db_end_transaction(0);
1514
- }
1490
+ g.eHashPolicy = db_get_int("hash-policy",-1);
1491
+ if( g.eHashPolicy<0 ){
1492
+ g.eHashPolicy = hname_default_policy();
1493
+ db_set_int("hash-policy", g.eHashPolicy, 0);
1494
+ }
1495
+
1496
+ /* If the ALIAS table is not present, then some on-the-fly schema
1497
+ ** updates might be required.
1498
+ */
1499
+ rebuild_schema_update_2_0(); /* Do the Fossil-2.0 schema updates */
15151500
}
15161501
15171502
/*
15181503
** Flags for the db_find_and_open_repository() function.
15191504
*/
@@ -1849,10 +1834,11 @@
18491834
" AND name NOT GLOB 'project-*'"
18501835
" AND name NOT GLOB 'short-project-*';",
18511836
configure_inop_rhs(CONFIGSET_ALL),
18521837
db_setting_inop_rhs()
18531838
);
1839
+ g.eHashPolicy = db_get_int("hash-policy", g.eHashPolicy);
18541840
db_multi_exec(
18551841
"REPLACE INTO reportfmt SELECT * FROM settingSrc.reportfmt;"
18561842
);
18571843
18581844
/*
@@ -1921,13 +1907,14 @@
19211907
** their associated permissions will not be copied; however, the system
19221908
** default users "anonymous", "nobody", "reader", "developer", and their
19231909
** associated permissions will be copied.
19241910
**
19251911
** Options:
1926
-** --template FILE copy settings from repository file
1927
-** --admin-user|-A USERNAME select given USERNAME as admin user
1928
-** --date-override DATETIME use DATETIME as time of the initial check-in
1912
+** --template FILE Copy settings from repository file
1913
+** --admin-user|-A USERNAME Select given USERNAME as admin user
1914
+** --date-override DATETIME Use DATETIME as time of the initial check-in
1915
+** --sha1 Use a initial hash policy of "sha1"
19291916
**
19301917
** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
19311918
** year-month-day form, it may be truncated, the "T" may be replaced by
19321919
** a space, and it may also name a timezone offset from UTC as "-HH:MM"
19331920
** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z"
@@ -1938,14 +1925,17 @@
19381925
void create_repository_cmd(void){
19391926
char *zPassword;
19401927
const char *zTemplate; /* Repository from which to copy settings */
19411928
const char *zDate; /* Date of the initial check-in */
19421929
const char *zDefaultUser; /* Optional name of the default user */
1930
+ int bUseSha1 = 0; /* True to set the hash-policy to sha1 */
1931
+
19431932
19441933
zTemplate = find_option("template",0,1);
19451934
zDate = find_option("date-override",0,1);
19461935
zDefaultUser = find_option("admin-user","A",1);
1936
+ bUseSha1 = find_option("sha1",0,0)!=0;
19471937
/* We should be done with options.. */
19481938
verify_all_options();
19491939
19501940
if( g.argc!=3 ){
19511941
usage("REPOSITORY-NAME");
@@ -1958,10 +1948,14 @@
19581948
db_create_repository(g.argv[2]);
19591949
db_open_repository(g.argv[2]);
19601950
db_open_config(0, 0);
19611951
if( zTemplate ) db_attach(zTemplate, "settingSrc");
19621952
db_begin_transaction();
1953
+ if( bUseSha1 ){
1954
+ g.eHashPolicy = HPOLICY_SHA1;
1955
+ db_set_int("hash-policy", HPOLICY_SHA1, 0);
1956
+ }
19631957
if( zDate==0 ) zDate = "now";
19641958
db_initial_setup(zTemplate, zDate, zDefaultUser);
19651959
db_end_transaction(0);
19661960
if( zTemplate ) db_detach("settingSrc");
19671961
fossil_print("project-id: %s\n", db_get("project-code", 0));
@@ -2083,29 +2077,29 @@
20832077
sqlite3_result_value(context, argv[2-rc]);
20842078
}
20852079
}
20862080
20872081
/*
2088
-** Convert the input string into an SHA1. Make a notation in the
2082
+** Convert the input string into a artifact hash. Make a notation in the
20892083
** CONCEALED table so that the hash can be undo using the db_reveal()
20902084
** function at some later time.
20912085
**
20922086
** The value returned is stored in static space and will be overwritten
20932087
** on subsequent calls.
20942088
**
2095
-** If zContent is already a well-formed SHA1 hash, then return a copy
2089
+** If zContent is already a well-formed artifact hash, then return a copy
20962090
** of that hash, not a hash of the hash.
20972091
**
20982092
** The CONCEALED table is meant to obscure email addresses. Every valid
20992093
** email address will contain a "@" character and "@" is not valid within
2100
-** an SHA1 hash so there is no chance that a valid email address will go
2094
+** a SHA1 hash so there is no chance that a valid email address will go
21012095
** unconcealed.
21022096
*/
21032097
char *db_conceal(const char *zContent, int n){
2104
- static char zHash[42];
2098
+ static char zHash[HNAME_MAX+1];
21052099
Blob out;
2106
- if( n==40 && validate16(zContent, n) ){
2100
+ if( hname_validate(zContent, n) ){
21072101
memcpy(zHash, zContent, n);
21082102
zHash[n] = 0;
21092103
}else{
21102104
sha1sum_step_text(zContent, n);
21112105
sha1sum_finish(&out);
21122106
--- src/db.c
+++ src/db.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -1485,35 +1485,20 @@
1485 g.repositoryOpen = 1;
1486 /* Cache "allow-symlinks" option, because we'll need it on every stat call */
1487 g.allowSymlinks = db_get_boolean("allow-symlinks",
1488 db_allow_symlinks_by_default());
1489 g.zAuxSchema = db_get("aux-schema","");
1490
1491 /* Verify that the PLINK table has a new column added by the
1492 ** 2014-11-28 schema change. Create it if necessary. This code
1493 ** can be removed in the future, once all users have upgraded to the
1494 ** 2014-11-28 or later schema.
1495 */
1496 if( !db_table_has_column("repository","plink","baseid") ){
1497 db_multi_exec(
1498 "ALTER TABLE repository.plink ADD COLUMN baseid;"
1499 );
1500 }
1501
1502 /* Verify that the MLINK table has the newer columns added by the
1503 ** 2015-01-24 schema change. Create them if necessary. This code
1504 ** can be removed in the future, once all users have upgraded to the
1505 ** 2015-01-24 or later schema.
1506 */
1507 if( !db_table_has_column("repository","mlink","isaux") ){
1508 db_begin_transaction();
1509 db_multi_exec(
1510 "ALTER TABLE repository.mlink ADD COLUMN pmid INTEGER DEFAULT 0;"
1511 "ALTER TABLE repository.mlink ADD COLUMN isaux BOOLEAN DEFAULT 0;"
1512 );
1513 db_end_transaction(0);
1514 }
1515 }
1516
1517 /*
1518 ** Flags for the db_find_and_open_repository() function.
1519 */
@@ -1849,10 +1834,11 @@
1849 " AND name NOT GLOB 'project-*'"
1850 " AND name NOT GLOB 'short-project-*';",
1851 configure_inop_rhs(CONFIGSET_ALL),
1852 db_setting_inop_rhs()
1853 );
 
1854 db_multi_exec(
1855 "REPLACE INTO reportfmt SELECT * FROM settingSrc.reportfmt;"
1856 );
1857
1858 /*
@@ -1921,13 +1907,14 @@
1921 ** their associated permissions will not be copied; however, the system
1922 ** default users "anonymous", "nobody", "reader", "developer", and their
1923 ** associated permissions will be copied.
1924 **
1925 ** Options:
1926 ** --template FILE copy settings from repository file
1927 ** --admin-user|-A USERNAME select given USERNAME as admin user
1928 ** --date-override DATETIME use DATETIME as time of the initial check-in
 
1929 **
1930 ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
1931 ** year-month-day form, it may be truncated, the "T" may be replaced by
1932 ** a space, and it may also name a timezone offset from UTC as "-HH:MM"
1933 ** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z"
@@ -1938,14 +1925,17 @@
1938 void create_repository_cmd(void){
1939 char *zPassword;
1940 const char *zTemplate; /* Repository from which to copy settings */
1941 const char *zDate; /* Date of the initial check-in */
1942 const char *zDefaultUser; /* Optional name of the default user */
 
 
1943
1944 zTemplate = find_option("template",0,1);
1945 zDate = find_option("date-override",0,1);
1946 zDefaultUser = find_option("admin-user","A",1);
 
1947 /* We should be done with options.. */
1948 verify_all_options();
1949
1950 if( g.argc!=3 ){
1951 usage("REPOSITORY-NAME");
@@ -1958,10 +1948,14 @@
1958 db_create_repository(g.argv[2]);
1959 db_open_repository(g.argv[2]);
1960 db_open_config(0, 0);
1961 if( zTemplate ) db_attach(zTemplate, "settingSrc");
1962 db_begin_transaction();
 
 
 
 
1963 if( zDate==0 ) zDate = "now";
1964 db_initial_setup(zTemplate, zDate, zDefaultUser);
1965 db_end_transaction(0);
1966 if( zTemplate ) db_detach("settingSrc");
1967 fossil_print("project-id: %s\n", db_get("project-code", 0));
@@ -2083,29 +2077,29 @@
2083 sqlite3_result_value(context, argv[2-rc]);
2084 }
2085 }
2086
2087 /*
2088 ** Convert the input string into an SHA1. Make a notation in the
2089 ** CONCEALED table so that the hash can be undo using the db_reveal()
2090 ** function at some later time.
2091 **
2092 ** The value returned is stored in static space and will be overwritten
2093 ** on subsequent calls.
2094 **
2095 ** If zContent is already a well-formed SHA1 hash, then return a copy
2096 ** of that hash, not a hash of the hash.
2097 **
2098 ** The CONCEALED table is meant to obscure email addresses. Every valid
2099 ** email address will contain a "@" character and "@" is not valid within
2100 ** an SHA1 hash so there is no chance that a valid email address will go
2101 ** unconcealed.
2102 */
2103 char *db_conceal(const char *zContent, int n){
2104 static char zHash[42];
2105 Blob out;
2106 if( n==40 && validate16(zContent, n) ){
2107 memcpy(zHash, zContent, n);
2108 zHash[n] = 0;
2109 }else{
2110 sha1sum_step_text(zContent, n);
2111 sha1sum_finish(&out);
2112
--- src/db.c
+++ src/db.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7 **
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -1485,35 +1485,20 @@
1485 g.repositoryOpen = 1;
1486 /* Cache "allow-symlinks" option, because we'll need it on every stat call */
1487 g.allowSymlinks = db_get_boolean("allow-symlinks",
1488 db_allow_symlinks_by_default());
1489 g.zAuxSchema = db_get("aux-schema","");
1490 g.eHashPolicy = db_get_int("hash-policy",-1);
1491 if( g.eHashPolicy<0 ){
1492 g.eHashPolicy = hname_default_policy();
1493 db_set_int("hash-policy", g.eHashPolicy, 0);
1494 }
1495
1496 /* If the ALIAS table is not present, then some on-the-fly schema
1497 ** updates might be required.
1498 */
1499 rebuild_schema_update_2_0(); /* Do the Fossil-2.0 schema updates */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1500 }
1501
1502 /*
1503 ** Flags for the db_find_and_open_repository() function.
1504 */
@@ -1849,10 +1834,11 @@
1834 " AND name NOT GLOB 'project-*'"
1835 " AND name NOT GLOB 'short-project-*';",
1836 configure_inop_rhs(CONFIGSET_ALL),
1837 db_setting_inop_rhs()
1838 );
1839 g.eHashPolicy = db_get_int("hash-policy", g.eHashPolicy);
1840 db_multi_exec(
1841 "REPLACE INTO reportfmt SELECT * FROM settingSrc.reportfmt;"
1842 );
1843
1844 /*
@@ -1921,13 +1907,14 @@
1907 ** their associated permissions will not be copied; however, the system
1908 ** default users "anonymous", "nobody", "reader", "developer", and their
1909 ** associated permissions will be copied.
1910 **
1911 ** Options:
1912 ** --template FILE Copy settings from repository file
1913 ** --admin-user|-A USERNAME Select given USERNAME as admin user
1914 ** --date-override DATETIME Use DATETIME as time of the initial check-in
1915 ** --sha1 Use a initial hash policy of "sha1"
1916 **
1917 ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
1918 ** year-month-day form, it may be truncated, the "T" may be replaced by
1919 ** a space, and it may also name a timezone offset from UTC as "-HH:MM"
1920 ** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z"
@@ -1938,14 +1925,17 @@
1925 void create_repository_cmd(void){
1926 char *zPassword;
1927 const char *zTemplate; /* Repository from which to copy settings */
1928 const char *zDate; /* Date of the initial check-in */
1929 const char *zDefaultUser; /* Optional name of the default user */
1930 int bUseSha1 = 0; /* True to set the hash-policy to sha1 */
1931
1932
1933 zTemplate = find_option("template",0,1);
1934 zDate = find_option("date-override",0,1);
1935 zDefaultUser = find_option("admin-user","A",1);
1936 bUseSha1 = find_option("sha1",0,0)!=0;
1937 /* We should be done with options.. */
1938 verify_all_options();
1939
1940 if( g.argc!=3 ){
1941 usage("REPOSITORY-NAME");
@@ -1958,10 +1948,14 @@
1948 db_create_repository(g.argv[2]);
1949 db_open_repository(g.argv[2]);
1950 db_open_config(0, 0);
1951 if( zTemplate ) db_attach(zTemplate, "settingSrc");
1952 db_begin_transaction();
1953 if( bUseSha1 ){
1954 g.eHashPolicy = HPOLICY_SHA1;
1955 db_set_int("hash-policy", HPOLICY_SHA1, 0);
1956 }
1957 if( zDate==0 ) zDate = "now";
1958 db_initial_setup(zTemplate, zDate, zDefaultUser);
1959 db_end_transaction(0);
1960 if( zTemplate ) db_detach("settingSrc");
1961 fossil_print("project-id: %s\n", db_get("project-code", 0));
@@ -2083,29 +2077,29 @@
2077 sqlite3_result_value(context, argv[2-rc]);
2078 }
2079 }
2080
2081 /*
2082 ** Convert the input string into a artifact hash. Make a notation in the
2083 ** CONCEALED table so that the hash can be undo using the db_reveal()
2084 ** function at some later time.
2085 **
2086 ** The value returned is stored in static space and will be overwritten
2087 ** on subsequent calls.
2088 **
2089 ** If zContent is already a well-formed artifact hash, then return a copy
2090 ** of that hash, not a hash of the hash.
2091 **
2092 ** The CONCEALED table is meant to obscure email addresses. Every valid
2093 ** email address will contain a "@" character and "@" is not valid within
2094 ** a SHA1 hash so there is no chance that a valid email address will go
2095 ** unconcealed.
2096 */
2097 char *db_conceal(const char *zContent, int n){
2098 static char zHash[HNAME_MAX+1];
2099 Blob out;
2100 if( hname_validate(zContent, n) ){
2101 memcpy(zHash, zContent, n);
2102 zHash[n] = 0;
2103 }else{
2104 sha1sum_step_text(zContent, n);
2105 sha1sum_finish(&out);
2106
+28 -34
--- src/db.c
+++ src/db.c
@@ -2,11 +2,11 @@
22
** Copyright (c) 2006 D. Richard Hipp
33
**
44
** This program is free software; you can redistribute it and/or
55
** modify it under the terms of the Simplified BSD License (also
66
** known as the "2-Clause License" or "FreeBSD License".)
7
-
7
+**
88
** This program is distributed in the hope that it will be useful,
99
** but without any warranty; without even the implied warranty of
1010
** merchantability or fitness for a particular purpose.
1111
**
1212
** Author contact information:
@@ -1485,35 +1485,20 @@
14851485
g.repositoryOpen = 1;
14861486
/* Cache "allow-symlinks" option, because we'll need it on every stat call */
14871487
g.allowSymlinks = db_get_boolean("allow-symlinks",
14881488
db_allow_symlinks_by_default());
14891489
g.zAuxSchema = db_get("aux-schema","");
1490
-
1491
- /* Verify that the PLINK table has a new column added by the
1492
- ** 2014-11-28 schema change. Create it if necessary. This code
1493
- ** can be removed in the future, once all users have upgraded to the
1494
- ** 2014-11-28 or later schema.
1495
- */
1496
- if( !db_table_has_column("repository","plink","baseid") ){
1497
- db_multi_exec(
1498
- "ALTER TABLE repository.plink ADD COLUMN baseid;"
1499
- );
1500
- }
1501
-
1502
- /* Verify that the MLINK table has the newer columns added by the
1503
- ** 2015-01-24 schema change. Create them if necessary. This code
1504
- ** can be removed in the future, once all users have upgraded to the
1505
- ** 2015-01-24 or later schema.
1506
- */
1507
- if( !db_table_has_column("repository","mlink","isaux") ){
1508
- db_begin_transaction();
1509
- db_multi_exec(
1510
- "ALTER TABLE repository.mlink ADD COLUMN pmid INTEGER DEFAULT 0;"
1511
- "ALTER TABLE repository.mlink ADD COLUMN isaux BOOLEAN DEFAULT 0;"
1512
- );
1513
- db_end_transaction(0);
1514
- }
1490
+ g.eHashPolicy = db_get_int("hash-policy",-1);
1491
+ if( g.eHashPolicy<0 ){
1492
+ g.eHashPolicy = hname_default_policy();
1493
+ db_set_int("hash-policy", g.eHashPolicy, 0);
1494
+ }
1495
+
1496
+ /* If the ALIAS table is not present, then some on-the-fly schema
1497
+ ** updates might be required.
1498
+ */
1499
+ rebuild_schema_update_2_0(); /* Do the Fossil-2.0 schema updates */
15151500
}
15161501
15171502
/*
15181503
** Flags for the db_find_and_open_repository() function.
15191504
*/
@@ -1849,10 +1834,11 @@
18491834
" AND name NOT GLOB 'project-*'"
18501835
" AND name NOT GLOB 'short-project-*';",
18511836
configure_inop_rhs(CONFIGSET_ALL),
18521837
db_setting_inop_rhs()
18531838
);
1839
+ g.eHashPolicy = db_get_int("hash-policy", g.eHashPolicy);
18541840
db_multi_exec(
18551841
"REPLACE INTO reportfmt SELECT * FROM settingSrc.reportfmt;"
18561842
);
18571843
18581844
/*
@@ -1921,13 +1907,14 @@
19211907
** their associated permissions will not be copied; however, the system
19221908
** default users "anonymous", "nobody", "reader", "developer", and their
19231909
** associated permissions will be copied.
19241910
**
19251911
** Options:
1926
-** --template FILE copy settings from repository file
1927
-** --admin-user|-A USERNAME select given USERNAME as admin user
1928
-** --date-override DATETIME use DATETIME as time of the initial check-in
1912
+** --template FILE Copy settings from repository file
1913
+** --admin-user|-A USERNAME Select given USERNAME as admin user
1914
+** --date-override DATETIME Use DATETIME as time of the initial check-in
1915
+** --sha1 Use a initial hash policy of "sha1"
19291916
**
19301917
** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
19311918
** year-month-day form, it may be truncated, the "T" may be replaced by
19321919
** a space, and it may also name a timezone offset from UTC as "-HH:MM"
19331920
** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z"
@@ -1938,14 +1925,17 @@
19381925
void create_repository_cmd(void){
19391926
char *zPassword;
19401927
const char *zTemplate; /* Repository from which to copy settings */
19411928
const char *zDate; /* Date of the initial check-in */
19421929
const char *zDefaultUser; /* Optional name of the default user */
1930
+ int bUseSha1 = 0; /* True to set the hash-policy to sha1 */
1931
+
19431932
19441933
zTemplate = find_option("template",0,1);
19451934
zDate = find_option("date-override",0,1);
19461935
zDefaultUser = find_option("admin-user","A",1);
1936
+ bUseSha1 = find_option("sha1",0,0)!=0;
19471937
/* We should be done with options.. */
19481938
verify_all_options();
19491939
19501940
if( g.argc!=3 ){
19511941
usage("REPOSITORY-NAME");
@@ -1958,10 +1948,14 @@
19581948
db_create_repository(g.argv[2]);
19591949
db_open_repository(g.argv[2]);
19601950
db_open_config(0, 0);
19611951
if( zTemplate ) db_attach(zTemplate, "settingSrc");
19621952
db_begin_transaction();
1953
+ if( bUseSha1 ){
1954
+ g.eHashPolicy = HPOLICY_SHA1;
1955
+ db_set_int("hash-policy", HPOLICY_SHA1, 0);
1956
+ }
19631957
if( zDate==0 ) zDate = "now";
19641958
db_initial_setup(zTemplate, zDate, zDefaultUser);
19651959
db_end_transaction(0);
19661960
if( zTemplate ) db_detach("settingSrc");
19671961
fossil_print("project-id: %s\n", db_get("project-code", 0));
@@ -2083,29 +2077,29 @@
20832077
sqlite3_result_value(context, argv[2-rc]);
20842078
}
20852079
}
20862080
20872081
/*
2088
-** Convert the input string into an SHA1. Make a notation in the
2082
+** Convert the input string into a artifact hash. Make a notation in the
20892083
** CONCEALED table so that the hash can be undo using the db_reveal()
20902084
** function at some later time.
20912085
**
20922086
** The value returned is stored in static space and will be overwritten
20932087
** on subsequent calls.
20942088
**
2095
-** If zContent is already a well-formed SHA1 hash, then return a copy
2089
+** If zContent is already a well-formed artifact hash, then return a copy
20962090
** of that hash, not a hash of the hash.
20972091
**
20982092
** The CONCEALED table is meant to obscure email addresses. Every valid
20992093
** email address will contain a "@" character and "@" is not valid within
2100
-** an SHA1 hash so there is no chance that a valid email address will go
2094
+** a SHA1 hash so there is no chance that a valid email address will go
21012095
** unconcealed.
21022096
*/
21032097
char *db_conceal(const char *zContent, int n){
2104
- static char zHash[42];
2098
+ static char zHash[HNAME_MAX+1];
21052099
Blob out;
2106
- if( n==40 && validate16(zContent, n) ){
2100
+ if( hname_validate(zContent, n) ){
21072101
memcpy(zHash, zContent, n);
21082102
zHash[n] = 0;
21092103
}else{
21102104
sha1sum_step_text(zContent, n);
21112105
sha1sum_finish(&out);
21122106
--- src/db.c
+++ src/db.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -1485,35 +1485,20 @@
1485 g.repositoryOpen = 1;
1486 /* Cache "allow-symlinks" option, because we'll need it on every stat call */
1487 g.allowSymlinks = db_get_boolean("allow-symlinks",
1488 db_allow_symlinks_by_default());
1489 g.zAuxSchema = db_get("aux-schema","");
1490
1491 /* Verify that the PLINK table has a new column added by the
1492 ** 2014-11-28 schema change. Create it if necessary. This code
1493 ** can be removed in the future, once all users have upgraded to the
1494 ** 2014-11-28 or later schema.
1495 */
1496 if( !db_table_has_column("repository","plink","baseid") ){
1497 db_multi_exec(
1498 "ALTER TABLE repository.plink ADD COLUMN baseid;"
1499 );
1500 }
1501
1502 /* Verify that the MLINK table has the newer columns added by the
1503 ** 2015-01-24 schema change. Create them if necessary. This code
1504 ** can be removed in the future, once all users have upgraded to the
1505 ** 2015-01-24 or later schema.
1506 */
1507 if( !db_table_has_column("repository","mlink","isaux") ){
1508 db_begin_transaction();
1509 db_multi_exec(
1510 "ALTER TABLE repository.mlink ADD COLUMN pmid INTEGER DEFAULT 0;"
1511 "ALTER TABLE repository.mlink ADD COLUMN isaux BOOLEAN DEFAULT 0;"
1512 );
1513 db_end_transaction(0);
1514 }
1515 }
1516
1517 /*
1518 ** Flags for the db_find_and_open_repository() function.
1519 */
@@ -1849,10 +1834,11 @@
1849 " AND name NOT GLOB 'project-*'"
1850 " AND name NOT GLOB 'short-project-*';",
1851 configure_inop_rhs(CONFIGSET_ALL),
1852 db_setting_inop_rhs()
1853 );
 
1854 db_multi_exec(
1855 "REPLACE INTO reportfmt SELECT * FROM settingSrc.reportfmt;"
1856 );
1857
1858 /*
@@ -1921,13 +1907,14 @@
1921 ** their associated permissions will not be copied; however, the system
1922 ** default users "anonymous", "nobody", "reader", "developer", and their
1923 ** associated permissions will be copied.
1924 **
1925 ** Options:
1926 ** --template FILE copy settings from repository file
1927 ** --admin-user|-A USERNAME select given USERNAME as admin user
1928 ** --date-override DATETIME use DATETIME as time of the initial check-in
 
1929 **
1930 ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
1931 ** year-month-day form, it may be truncated, the "T" may be replaced by
1932 ** a space, and it may also name a timezone offset from UTC as "-HH:MM"
1933 ** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z"
@@ -1938,14 +1925,17 @@
1938 void create_repository_cmd(void){
1939 char *zPassword;
1940 const char *zTemplate; /* Repository from which to copy settings */
1941 const char *zDate; /* Date of the initial check-in */
1942 const char *zDefaultUser; /* Optional name of the default user */
 
 
1943
1944 zTemplate = find_option("template",0,1);
1945 zDate = find_option("date-override",0,1);
1946 zDefaultUser = find_option("admin-user","A",1);
 
1947 /* We should be done with options.. */
1948 verify_all_options();
1949
1950 if( g.argc!=3 ){
1951 usage("REPOSITORY-NAME");
@@ -1958,10 +1948,14 @@
1958 db_create_repository(g.argv[2]);
1959 db_open_repository(g.argv[2]);
1960 db_open_config(0, 0);
1961 if( zTemplate ) db_attach(zTemplate, "settingSrc");
1962 db_begin_transaction();
 
 
 
 
1963 if( zDate==0 ) zDate = "now";
1964 db_initial_setup(zTemplate, zDate, zDefaultUser);
1965 db_end_transaction(0);
1966 if( zTemplate ) db_detach("settingSrc");
1967 fossil_print("project-id: %s\n", db_get("project-code", 0));
@@ -2083,29 +2077,29 @@
2083 sqlite3_result_value(context, argv[2-rc]);
2084 }
2085 }
2086
2087 /*
2088 ** Convert the input string into an SHA1. Make a notation in the
2089 ** CONCEALED table so that the hash can be undo using the db_reveal()
2090 ** function at some later time.
2091 **
2092 ** The value returned is stored in static space and will be overwritten
2093 ** on subsequent calls.
2094 **
2095 ** If zContent is already a well-formed SHA1 hash, then return a copy
2096 ** of that hash, not a hash of the hash.
2097 **
2098 ** The CONCEALED table is meant to obscure email addresses. Every valid
2099 ** email address will contain a "@" character and "@" is not valid within
2100 ** an SHA1 hash so there is no chance that a valid email address will go
2101 ** unconcealed.
2102 */
2103 char *db_conceal(const char *zContent, int n){
2104 static char zHash[42];
2105 Blob out;
2106 if( n==40 && validate16(zContent, n) ){
2107 memcpy(zHash, zContent, n);
2108 zHash[n] = 0;
2109 }else{
2110 sha1sum_step_text(zContent, n);
2111 sha1sum_finish(&out);
2112
--- src/db.c
+++ src/db.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7 **
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -1485,35 +1485,20 @@
1485 g.repositoryOpen = 1;
1486 /* Cache "allow-symlinks" option, because we'll need it on every stat call */
1487 g.allowSymlinks = db_get_boolean("allow-symlinks",
1488 db_allow_symlinks_by_default());
1489 g.zAuxSchema = db_get("aux-schema","");
1490 g.eHashPolicy = db_get_int("hash-policy",-1);
1491 if( g.eHashPolicy<0 ){
1492 g.eHashPolicy = hname_default_policy();
1493 db_set_int("hash-policy", g.eHashPolicy, 0);
1494 }
1495
1496 /* If the ALIAS table is not present, then some on-the-fly schema
1497 ** updates might be required.
1498 */
1499 rebuild_schema_update_2_0(); /* Do the Fossil-2.0 schema updates */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1500 }
1501
1502 /*
1503 ** Flags for the db_find_and_open_repository() function.
1504 */
@@ -1849,10 +1834,11 @@
1834 " AND name NOT GLOB 'project-*'"
1835 " AND name NOT GLOB 'short-project-*';",
1836 configure_inop_rhs(CONFIGSET_ALL),
1837 db_setting_inop_rhs()
1838 );
1839 g.eHashPolicy = db_get_int("hash-policy", g.eHashPolicy);
1840 db_multi_exec(
1841 "REPLACE INTO reportfmt SELECT * FROM settingSrc.reportfmt;"
1842 );
1843
1844 /*
@@ -1921,13 +1907,14 @@
1907 ** their associated permissions will not be copied; however, the system
1908 ** default users "anonymous", "nobody", "reader", "developer", and their
1909 ** associated permissions will be copied.
1910 **
1911 ** Options:
1912 ** --template FILE Copy settings from repository file
1913 ** --admin-user|-A USERNAME Select given USERNAME as admin user
1914 ** --date-override DATETIME Use DATETIME as time of the initial check-in
1915 ** --sha1 Use a initial hash policy of "sha1"
1916 **
1917 ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
1918 ** year-month-day form, it may be truncated, the "T" may be replaced by
1919 ** a space, and it may also name a timezone offset from UTC as "-HH:MM"
1920 ** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z"
@@ -1938,14 +1925,17 @@
1925 void create_repository_cmd(void){
1926 char *zPassword;
1927 const char *zTemplate; /* Repository from which to copy settings */
1928 const char *zDate; /* Date of the initial check-in */
1929 const char *zDefaultUser; /* Optional name of the default user */
1930 int bUseSha1 = 0; /* True to set the hash-policy to sha1 */
1931
1932
1933 zTemplate = find_option("template",0,1);
1934 zDate = find_option("date-override",0,1);
1935 zDefaultUser = find_option("admin-user","A",1);
1936 bUseSha1 = find_option("sha1",0,0)!=0;
1937 /* We should be done with options.. */
1938 verify_all_options();
1939
1940 if( g.argc!=3 ){
1941 usage("REPOSITORY-NAME");
@@ -1958,10 +1948,14 @@
1948 db_create_repository(g.argv[2]);
1949 db_open_repository(g.argv[2]);
1950 db_open_config(0, 0);
1951 if( zTemplate ) db_attach(zTemplate, "settingSrc");
1952 db_begin_transaction();
1953 if( bUseSha1 ){
1954 g.eHashPolicy = HPOLICY_SHA1;
1955 db_set_int("hash-policy", HPOLICY_SHA1, 0);
1956 }
1957 if( zDate==0 ) zDate = "now";
1958 db_initial_setup(zTemplate, zDate, zDefaultUser);
1959 db_end_transaction(0);
1960 if( zTemplate ) db_detach("settingSrc");
1961 fossil_print("project-id: %s\n", db_get("project-code", 0));
@@ -2083,29 +2077,29 @@
2077 sqlite3_result_value(context, argv[2-rc]);
2078 }
2079 }
2080
2081 /*
2082 ** Convert the input string into a artifact hash. Make a notation in the
2083 ** CONCEALED table so that the hash can be undo using the db_reveal()
2084 ** function at some later time.
2085 **
2086 ** The value returned is stored in static space and will be overwritten
2087 ** on subsequent calls.
2088 **
2089 ** If zContent is already a well-formed artifact hash, then return a copy
2090 ** of that hash, not a hash of the hash.
2091 **
2092 ** The CONCEALED table is meant to obscure email addresses. Every valid
2093 ** email address will contain a "@" character and "@" is not valid within
2094 ** a SHA1 hash so there is no chance that a valid email address will go
2095 ** unconcealed.
2096 */
2097 char *db_conceal(const char *zContent, int n){
2098 static char zHash[HNAME_MAX+1];
2099 Blob out;
2100 if( hname_validate(zContent, n) ){
2101 memcpy(zHash, zContent, n);
2102 zHash[n] = 0;
2103 }else{
2104 sha1sum_step_text(zContent, n);
2105 sha1sum_finish(&out);
2106
+1 -1
--- src/diff.c
+++ src/diff.c
@@ -2278,11 +2278,11 @@
22782278
** URL: /annotate?checkin=ID&filename=FILENAME
22792279
** URL: /blame?checkin=ID&filename=FILENAME
22802280
** URL: /praise?checkin=ID&filename=FILENAME
22812281
**
22822282
** Show the most recent change to each line of a text file. /annotate shows
2283
-** the date of the changes and the check-in SHA1 hash (with a link to the
2283
+** the date of the changes and the check-in hash (with a link to the
22842284
** check-in). /blame and /praise also show the user who made the check-in.
22852285
**
22862286
** Query parameters:
22872287
**
22882288
** checkin=ID The manifest ID at which to start the annotation
22892289
--- src/diff.c
+++ src/diff.c
@@ -2278,11 +2278,11 @@
2278 ** URL: /annotate?checkin=ID&filename=FILENAME
2279 ** URL: /blame?checkin=ID&filename=FILENAME
2280 ** URL: /praise?checkin=ID&filename=FILENAME
2281 **
2282 ** Show the most recent change to each line of a text file. /annotate shows
2283 ** the date of the changes and the check-in SHA1 hash (with a link to the
2284 ** check-in). /blame and /praise also show the user who made the check-in.
2285 **
2286 ** Query parameters:
2287 **
2288 ** checkin=ID The manifest ID at which to start the annotation
2289
--- src/diff.c
+++ src/diff.c
@@ -2278,11 +2278,11 @@
2278 ** URL: /annotate?checkin=ID&filename=FILENAME
2279 ** URL: /blame?checkin=ID&filename=FILENAME
2280 ** URL: /praise?checkin=ID&filename=FILENAME
2281 **
2282 ** Show the most recent change to each line of a text file. /annotate shows
2283 ** the date of the changes and the check-in hash (with a link to the
2284 ** check-in). /blame and /praise also show the user who made the check-in.
2285 **
2286 ** Query parameters:
2287 **
2288 ** checkin=ID The manifest ID at which to start the annotation
2289
+22 -8
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -151,10 +151,13 @@
151151
/*
152152
** Show the difference between two files, one in memory and one on disk.
153153
**
154154
** The difference is the set of edits needed to transform pFile1 into
155155
** zFile2. The content of pFile1 is in memory. zFile2 exists on disk.
156
+**
157
+** If fSwapDiff is 1, show the set of edits to transform zFile2 into pFile1
158
+** instead of the opposite.
156159
**
157160
** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the
158161
** command zDiffCmd to do the diffing.
159162
**
160163
** When using an external diff program, zBinGlob contains the GLOB patterns
@@ -167,11 +170,12 @@
167170
const char *zFile2, /* On disk content to compare to */
168171
const char *zName, /* Display name of the file */
169172
const char *zDiffCmd, /* Command for comparison */
170173
const char *zBinGlob, /* Treat file names matching this as binary */
171174
int fIncludeBinary, /* Include binary files for external diff */
172
- u64 diffFlags /* Flags to control the diff */
175
+ u64 diffFlags, /* Flags to control the diff */
176
+ int fSwapDiff /* Diff from Zfile2 to Pfile1 */
173177
){
174178
if( zDiffCmd==0 ){
175179
Blob out; /* Diff output text */
176180
Blob file2; /* Content of zFile2 */
177181
const char *zName2; /* Name of zFile2 for display */
@@ -194,11 +198,15 @@
194198
if( blob_compare(pFile1, &file2) ){
195199
fossil_print("CHANGED %s\n", zName);
196200
}
197201
}else{
198202
blob_zero(&out);
199
- text_diff(pFile1, &file2, &out, 0, diffFlags);
203
+ if( fSwapDiff ){
204
+ text_diff(&file2, pFile1, &out, 0, diffFlags);
205
+ }else{
206
+ text_diff(pFile1, &file2, &out, 0, diffFlags);
207
+ }
200208
if( blob_size(&out) ){
201209
diff_print_filenames(zName, zName2, diffFlags);
202210
fossil_print("%s\n", blob_str(&out));
203211
}
204212
blob_reset(&out);
@@ -252,13 +260,19 @@
252260
blob_write_to_file(pFile1, blob_str(&nameFile1));
253261
254262
/* Construct the external diff command */
255263
blob_zero(&cmd);
256264
blob_appendf(&cmd, "%s ", zDiffCmd);
257
- shell_escape(&cmd, blob_str(&nameFile1));
258
- blob_append(&cmd, " ", 1);
259
- shell_escape(&cmd, zFile2);
265
+ if( fSwapDiff ){
266
+ shell_escape(&cmd, zFile2);
267
+ blob_append(&cmd, " ", 1);
268
+ shell_escape(&cmd, blob_str(&nameFile1));
269
+ }else{
270
+ shell_escape(&cmd, blob_str(&nameFile1));
271
+ blob_append(&cmd, " ", 1);
272
+ shell_escape(&cmd, zFile2);
273
+ }
260274
261275
/* Run the external diff command */
262276
fossil_system(blob_str(&cmd));
263277
264278
/* Delete the temporary file and clean up memory used */
@@ -482,11 +496,11 @@
482496
blob_zero(&content);
483497
}
484498
isBin = fIncludeBinary ? 0 : looks_like_binary(&content);
485499
diff_print_index(zPathname, diffFlags);
486500
diff_file(&content, isBin, zFullName, zPathname, zDiffCmd,
487
- zBinGlob, fIncludeBinary, diffFlags);
501
+ zBinGlob, fIncludeBinary, diffFlags, 0);
488502
blob_reset(&content);
489503
}
490504
blob_reset(&fname);
491505
}
492506
db_finalize(&q);
@@ -519,11 +533,11 @@
519533
const char *zFile = (const char*)db_column_text(&q, 0);
520534
if( !file_dir_match(pFileDir, zFile) ) continue;
521535
zFullName = mprintf("%s%s", g.zLocalRoot, zFile);
522536
db_column_blob(&q, 1, &content);
523537
diff_file(&content, 0, zFullName, zFile,
524
- zDiffCmd, zBinGlob, fIncludeBinary, diffFlags);
538
+ zDiffCmd, zBinGlob, fIncludeBinary, diffFlags, 0);
525539
fossil_free(zFullName);
526540
blob_reset(&content);
527541
}
528542
db_finalize(&q);
529543
}
@@ -750,11 +764,11 @@
750764
** Returns non-zero if files that may be binary should be used with external
751765
** diff programs.
752766
*/
753767
int diff_include_binary_files(void){
754768
const char* zArgIncludeBinary = find_option("diff-binary", 0, 1);
755
-
769
+
756770
/* Command line argument have priority on settings */
757771
if( zArgIncludeBinary ){
758772
return is_truth(zArgIncludeBinary);
759773
}else{
760774
return db_get_boolean("diff-binary", 1);
761775
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -151,10 +151,13 @@
151 /*
152 ** Show the difference between two files, one in memory and one on disk.
153 **
154 ** The difference is the set of edits needed to transform pFile1 into
155 ** zFile2. The content of pFile1 is in memory. zFile2 exists on disk.
 
 
 
156 **
157 ** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the
158 ** command zDiffCmd to do the diffing.
159 **
160 ** When using an external diff program, zBinGlob contains the GLOB patterns
@@ -167,11 +170,12 @@
167 const char *zFile2, /* On disk content to compare to */
168 const char *zName, /* Display name of the file */
169 const char *zDiffCmd, /* Command for comparison */
170 const char *zBinGlob, /* Treat file names matching this as binary */
171 int fIncludeBinary, /* Include binary files for external diff */
172 u64 diffFlags /* Flags to control the diff */
 
173 ){
174 if( zDiffCmd==0 ){
175 Blob out; /* Diff output text */
176 Blob file2; /* Content of zFile2 */
177 const char *zName2; /* Name of zFile2 for display */
@@ -194,11 +198,15 @@
194 if( blob_compare(pFile1, &file2) ){
195 fossil_print("CHANGED %s\n", zName);
196 }
197 }else{
198 blob_zero(&out);
199 text_diff(pFile1, &file2, &out, 0, diffFlags);
 
 
 
 
200 if( blob_size(&out) ){
201 diff_print_filenames(zName, zName2, diffFlags);
202 fossil_print("%s\n", blob_str(&out));
203 }
204 blob_reset(&out);
@@ -252,13 +260,19 @@
252 blob_write_to_file(pFile1, blob_str(&nameFile1));
253
254 /* Construct the external diff command */
255 blob_zero(&cmd);
256 blob_appendf(&cmd, "%s ", zDiffCmd);
257 shell_escape(&cmd, blob_str(&nameFile1));
258 blob_append(&cmd, " ", 1);
259 shell_escape(&cmd, zFile2);
 
 
 
 
 
 
260
261 /* Run the external diff command */
262 fossil_system(blob_str(&cmd));
263
264 /* Delete the temporary file and clean up memory used */
@@ -482,11 +496,11 @@
482 blob_zero(&content);
483 }
484 isBin = fIncludeBinary ? 0 : looks_like_binary(&content);
485 diff_print_index(zPathname, diffFlags);
486 diff_file(&content, isBin, zFullName, zPathname, zDiffCmd,
487 zBinGlob, fIncludeBinary, diffFlags);
488 blob_reset(&content);
489 }
490 blob_reset(&fname);
491 }
492 db_finalize(&q);
@@ -519,11 +533,11 @@
519 const char *zFile = (const char*)db_column_text(&q, 0);
520 if( !file_dir_match(pFileDir, zFile) ) continue;
521 zFullName = mprintf("%s%s", g.zLocalRoot, zFile);
522 db_column_blob(&q, 1, &content);
523 diff_file(&content, 0, zFullName, zFile,
524 zDiffCmd, zBinGlob, fIncludeBinary, diffFlags);
525 fossil_free(zFullName);
526 blob_reset(&content);
527 }
528 db_finalize(&q);
529 }
@@ -750,11 +764,11 @@
750 ** Returns non-zero if files that may be binary should be used with external
751 ** diff programs.
752 */
753 int diff_include_binary_files(void){
754 const char* zArgIncludeBinary = find_option("diff-binary", 0, 1);
755
756 /* Command line argument have priority on settings */
757 if( zArgIncludeBinary ){
758 return is_truth(zArgIncludeBinary);
759 }else{
760 return db_get_boolean("diff-binary", 1);
761
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -151,10 +151,13 @@
151 /*
152 ** Show the difference between two files, one in memory and one on disk.
153 **
154 ** The difference is the set of edits needed to transform pFile1 into
155 ** zFile2. The content of pFile1 is in memory. zFile2 exists on disk.
156 **
157 ** If fSwapDiff is 1, show the set of edits to transform zFile2 into pFile1
158 ** instead of the opposite.
159 **
160 ** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the
161 ** command zDiffCmd to do the diffing.
162 **
163 ** When using an external diff program, zBinGlob contains the GLOB patterns
@@ -167,11 +170,12 @@
170 const char *zFile2, /* On disk content to compare to */
171 const char *zName, /* Display name of the file */
172 const char *zDiffCmd, /* Command for comparison */
173 const char *zBinGlob, /* Treat file names matching this as binary */
174 int fIncludeBinary, /* Include binary files for external diff */
175 u64 diffFlags, /* Flags to control the diff */
176 int fSwapDiff /* Diff from Zfile2 to Pfile1 */
177 ){
178 if( zDiffCmd==0 ){
179 Blob out; /* Diff output text */
180 Blob file2; /* Content of zFile2 */
181 const char *zName2; /* Name of zFile2 for display */
@@ -194,11 +198,15 @@
198 if( blob_compare(pFile1, &file2) ){
199 fossil_print("CHANGED %s\n", zName);
200 }
201 }else{
202 blob_zero(&out);
203 if( fSwapDiff ){
204 text_diff(&file2, pFile1, &out, 0, diffFlags);
205 }else{
206 text_diff(pFile1, &file2, &out, 0, diffFlags);
207 }
208 if( blob_size(&out) ){
209 diff_print_filenames(zName, zName2, diffFlags);
210 fossil_print("%s\n", blob_str(&out));
211 }
212 blob_reset(&out);
@@ -252,13 +260,19 @@
260 blob_write_to_file(pFile1, blob_str(&nameFile1));
261
262 /* Construct the external diff command */
263 blob_zero(&cmd);
264 blob_appendf(&cmd, "%s ", zDiffCmd);
265 if( fSwapDiff ){
266 shell_escape(&cmd, zFile2);
267 blob_append(&cmd, " ", 1);
268 shell_escape(&cmd, blob_str(&nameFile1));
269 }else{
270 shell_escape(&cmd, blob_str(&nameFile1));
271 blob_append(&cmd, " ", 1);
272 shell_escape(&cmd, zFile2);
273 }
274
275 /* Run the external diff command */
276 fossil_system(blob_str(&cmd));
277
278 /* Delete the temporary file and clean up memory used */
@@ -482,11 +496,11 @@
496 blob_zero(&content);
497 }
498 isBin = fIncludeBinary ? 0 : looks_like_binary(&content);
499 diff_print_index(zPathname, diffFlags);
500 diff_file(&content, isBin, zFullName, zPathname, zDiffCmd,
501 zBinGlob, fIncludeBinary, diffFlags, 0);
502 blob_reset(&content);
503 }
504 blob_reset(&fname);
505 }
506 db_finalize(&q);
@@ -519,11 +533,11 @@
533 const char *zFile = (const char*)db_column_text(&q, 0);
534 if( !file_dir_match(pFileDir, zFile) ) continue;
535 zFullName = mprintf("%s%s", g.zLocalRoot, zFile);
536 db_column_blob(&q, 1, &content);
537 diff_file(&content, 0, zFullName, zFile,
538 zDiffCmd, zBinGlob, fIncludeBinary, diffFlags, 0);
539 fossil_free(zFullName);
540 blob_reset(&content);
541 }
542 db_finalize(&q);
543 }
@@ -750,11 +764,11 @@
764 ** Returns non-zero if files that may be binary should be used with external
765 ** diff programs.
766 */
767 int diff_include_binary_files(void){
768 const char* zArgIncludeBinary = find_option("diff-binary", 0, 1);
769
770 /* Command line argument have priority on settings */
771 if( zArgIncludeBinary ){
772 return is_truth(zArgIncludeBinary);
773 }else{
774 return db_get_boolean("diff-binary", 1);
775
+2 -2
--- src/doc.c
+++ src/doc.c
@@ -527,11 +527,11 @@
527527
** WEBPAGE: uv
528528
** WEBPAGE: doc
529529
** URL: /uv/FILE
530530
** URL: /doc/CHECKIN/FILE
531531
**
532
-** CHECKIN can be either tag or SHA1 hash or timestamp identifying a
532
+** CHECKIN can be either tag or hash prefix or timestamp identifying a
533533
** particular check, or the name of a branch (meaning the most recent
534534
** check-in on that branch) or one of various magic words:
535535
**
536536
** "tip" means the most recent check-in
537537
**
@@ -735,11 +735,11 @@
735735
736736
/* Jump here when unable to locate the document */
737737
doc_not_found:
738738
db_end_transaction(0);
739739
if( isUV && P("name")==0 ){
740
- uvstat_page();
740
+ uvlist_page();
741741
return;
742742
}
743743
cgi_set_status(404, "Not Found");
744744
style_header("Not Found");
745745
@ <p>Document %h(zOrigName) not found
746746
--- src/doc.c
+++ src/doc.c
@@ -527,11 +527,11 @@
527 ** WEBPAGE: uv
528 ** WEBPAGE: doc
529 ** URL: /uv/FILE
530 ** URL: /doc/CHECKIN/FILE
531 **
532 ** CHECKIN can be either tag or SHA1 hash or timestamp identifying a
533 ** particular check, or the name of a branch (meaning the most recent
534 ** check-in on that branch) or one of various magic words:
535 **
536 ** "tip" means the most recent check-in
537 **
@@ -735,11 +735,11 @@
735
736 /* Jump here when unable to locate the document */
737 doc_not_found:
738 db_end_transaction(0);
739 if( isUV && P("name")==0 ){
740 uvstat_page();
741 return;
742 }
743 cgi_set_status(404, "Not Found");
744 style_header("Not Found");
745 @ <p>Document %h(zOrigName) not found
746
--- src/doc.c
+++ src/doc.c
@@ -527,11 +527,11 @@
527 ** WEBPAGE: uv
528 ** WEBPAGE: doc
529 ** URL: /uv/FILE
530 ** URL: /doc/CHECKIN/FILE
531 **
532 ** CHECKIN can be either tag or hash prefix or timestamp identifying a
533 ** particular check, or the name of a branch (meaning the most recent
534 ** check-in on that branch) or one of various magic words:
535 **
536 ** "tip" means the most recent check-in
537 **
@@ -735,11 +735,11 @@
735
736 /* Jump here when unable to locate the document */
737 doc_not_found:
738 db_end_transaction(0);
739 if( isUV && P("name")==0 ){
740 uvlist_page();
741 return;
742 }
743 cgi_set_status(404, "Not Found");
744 style_header("Not Found");
745 @ <p>Document %h(zOrigName) not found
746
+90
--- src/encode.c
+++ src/encode.c
@@ -336,10 +336,100 @@
336336
z[j++] = c;
337337
}
338338
if( z[j] ) z[j] = 0;
339339
}
340340
341
+
342
+/*
343
+** The *pz variable points to a UTF8 string. Read the next character
344
+** off of that string and return its codepoint value. Advance *pz to the
345
+** next character
346
+*/
347
+u32 fossil_utf8_read(
348
+ const unsigned char **pz /* Pointer to string from which to read char */
349
+){
350
+ unsigned int c;
351
+
352
+ /*
353
+ ** This lookup table is used to help decode the first byte of
354
+ ** a multi-byte UTF8 character.
355
+ */
356
+ static const unsigned char utf8Trans1[] = {
357
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
358
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
359
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
360
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
361
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
362
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
363
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
364
+ 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
365
+ };
366
+
367
+ c = *((*pz)++);
368
+ if( c>=0xc0 ){
369
+ c = utf8Trans1[c-0xc0];
370
+ while( (*(*pz) & 0xc0)==0x80 ){
371
+ c = (c<<6) + (0x3f & *((*pz)++));
372
+ }
373
+ if( c<0x80
374
+ || (c&0xFFFFF800)==0xD800
375
+ || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; }
376
+ }
377
+ return c;
378
+}
379
+
380
+/*
381
+** Encode a UTF8 string for JSON. All special characters are escaped.
382
+*/
383
+void blob_append_json_string(Blob *pBlob, const char *zStr){
384
+ const unsigned char *z;
385
+ char *zOut;
386
+ u32 c;
387
+ int n, i, j;
388
+ z = (const unsigned char*)zStr;
389
+ n = 0;
390
+ while( (c = fossil_utf8_read(&z))!=0 ){
391
+ if( c=='\\' || c=='"' ){
392
+ n += 2;
393
+ }else if( c<' ' || c>=0x7f ){
394
+ if( c=='\n' || c=='\r' ){
395
+ n += 2;
396
+ }else{
397
+ n += 6;
398
+ }
399
+ }else{
400
+ n++;
401
+ }
402
+ }
403
+ i = blob_size(pBlob);
404
+ blob_resize(pBlob, i+n);
405
+ zOut = blob_buffer(pBlob);
406
+ z = (const unsigned char*)zStr;
407
+ while( (c = fossil_utf8_read(&z))!=0 ){
408
+ if( c=='\\' ){
409
+ zOut[i++] = '\\';
410
+ zOut[i++] = c;
411
+ }else if( c<' ' || c>=0x7f ){
412
+ zOut[i++] = '\\';
413
+ if( c=='\n' ){
414
+ zOut[i++] = 'n';
415
+ }else if( c=='\r' ){
416
+ zOut[i++] = 'r';
417
+ }else{
418
+ zOut[i++] = 'u';
419
+ for(j=3; j>=0; j--){
420
+ zOut[i+j] = "0123456789abcdef"[c&0xf];
421
+ c >>= 4;
422
+ }
423
+ i += 4;
424
+ }
425
+ }else{
426
+ zOut[i++] = c;
427
+ }
428
+ }
429
+ zOut[i] = 0;
430
+}
341431
342432
/*
343433
** The characters used for HTTP base64 encoding.
344434
*/
345435
static unsigned char zBase[] =
346436
--- src/encode.c
+++ src/encode.c
@@ -336,10 +336,100 @@
336 z[j++] = c;
337 }
338 if( z[j] ) z[j] = 0;
339 }
340
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
342 /*
343 ** The characters used for HTTP base64 encoding.
344 */
345 static unsigned char zBase[] =
346
--- src/encode.c
+++ src/encode.c
@@ -336,10 +336,100 @@
336 z[j++] = c;
337 }
338 if( z[j] ) z[j] = 0;
339 }
340
341
342 /*
343 ** The *pz variable points to a UTF8 string. Read the next character
344 ** off of that string and return its codepoint value. Advance *pz to the
345 ** next character
346 */
347 u32 fossil_utf8_read(
348 const unsigned char **pz /* Pointer to string from which to read char */
349 ){
350 unsigned int c;
351
352 /*
353 ** This lookup table is used to help decode the first byte of
354 ** a multi-byte UTF8 character.
355 */
356 static const unsigned char utf8Trans1[] = {
357 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
358 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
359 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
360 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
361 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
362 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
363 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
364 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
365 };
366
367 c = *((*pz)++);
368 if( c>=0xc0 ){
369 c = utf8Trans1[c-0xc0];
370 while( (*(*pz) & 0xc0)==0x80 ){
371 c = (c<<6) + (0x3f & *((*pz)++));
372 }
373 if( c<0x80
374 || (c&0xFFFFF800)==0xD800
375 || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; }
376 }
377 return c;
378 }
379
380 /*
381 ** Encode a UTF8 string for JSON. All special characters are escaped.
382 */
383 void blob_append_json_string(Blob *pBlob, const char *zStr){
384 const unsigned char *z;
385 char *zOut;
386 u32 c;
387 int n, i, j;
388 z = (const unsigned char*)zStr;
389 n = 0;
390 while( (c = fossil_utf8_read(&z))!=0 ){
391 if( c=='\\' || c=='"' ){
392 n += 2;
393 }else if( c<' ' || c>=0x7f ){
394 if( c=='\n' || c=='\r' ){
395 n += 2;
396 }else{
397 n += 6;
398 }
399 }else{
400 n++;
401 }
402 }
403 i = blob_size(pBlob);
404 blob_resize(pBlob, i+n);
405 zOut = blob_buffer(pBlob);
406 z = (const unsigned char*)zStr;
407 while( (c = fossil_utf8_read(&z))!=0 ){
408 if( c=='\\' ){
409 zOut[i++] = '\\';
410 zOut[i++] = c;
411 }else if( c<' ' || c>=0x7f ){
412 zOut[i++] = '\\';
413 if( c=='\n' ){
414 zOut[i++] = 'n';
415 }else if( c=='\r' ){
416 zOut[i++] = 'r';
417 }else{
418 zOut[i++] = 'u';
419 for(j=3; j>=0; j--){
420 zOut[i+j] = "0123456789abcdef"[c&0xf];
421 c >>= 4;
422 }
423 i += 4;
424 }
425 }else{
426 zOut[i++] = c;
427 }
428 }
429 zOut[i] = 0;
430 }
431
432 /*
433 ** The characters used for HTTP base64 encoding.
434 */
435 static unsigned char zBase[] =
436
+1 -1
--- src/event.c
+++ src/event.c
@@ -384,11 +384,11 @@
384384
rid = db_int(0,
385385
"SELECT rid FROM tagxref"
386386
" WHERE tagid=(SELECT tagid FROM tag WHERE tagname GLOB '%q*')"
387387
" ORDER BY mtime DESC", zTag
388388
);
389
- if( rid && strlen(zId)<40 ){
389
+ if( rid && strlen(zId)<HNAME_MIN ){
390390
zId = db_text(0,
391391
"SELECT substr(tagname,7) FROM tag WHERE tagname GLOB '%q*'",
392392
zTag
393393
);
394394
}
395395
--- src/event.c
+++ src/event.c
@@ -384,11 +384,11 @@
384 rid = db_int(0,
385 "SELECT rid FROM tagxref"
386 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname GLOB '%q*')"
387 " ORDER BY mtime DESC", zTag
388 );
389 if( rid && strlen(zId)<40 ){
390 zId = db_text(0,
391 "SELECT substr(tagname,7) FROM tag WHERE tagname GLOB '%q*'",
392 zTag
393 );
394 }
395
--- src/event.c
+++ src/event.c
@@ -384,11 +384,11 @@
384 rid = db_int(0,
385 "SELECT rid FROM tagxref"
386 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname GLOB '%q*')"
387 " ORDER BY mtime DESC", zTag
388 );
389 if( rid && strlen(zId)<HNAME_MIN ){
390 zId = db_text(0,
391 "SELECT substr(tagname,7) FROM tag WHERE tagname GLOB '%q*'",
392 zTag
393 );
394 }
395
+1 -1
--- src/export.c
+++ src/export.c
@@ -261,11 +261,11 @@
261261
cur_tok = strtok(NULL, " \t");
262262
if( !cur_tok ){
263263
/* This mark was generated by an older version of Fossil and doesn't
264264
** include the mark name and uuid. create_mark() will name the new mark
265265
** exactly as it was when exported to git, so that we should have a
266
- ** valid mapping from git sha1<->mark name<->fossil sha1. */
266
+ ** valid mapping from git hash<->mark name<->fossil hash. */
267267
unsigned int mid;
268268
if( type_=='c' ){
269269
mid = COMMITMARK(mark->rid);
270270
}
271271
else{
272272
--- src/export.c
+++ src/export.c
@@ -261,11 +261,11 @@
261 cur_tok = strtok(NULL, " \t");
262 if( !cur_tok ){
263 /* This mark was generated by an older version of Fossil and doesn't
264 ** include the mark name and uuid. create_mark() will name the new mark
265 ** exactly as it was when exported to git, so that we should have a
266 ** valid mapping from git sha1<->mark name<->fossil sha1. */
267 unsigned int mid;
268 if( type_=='c' ){
269 mid = COMMITMARK(mark->rid);
270 }
271 else{
272
--- src/export.c
+++ src/export.c
@@ -261,11 +261,11 @@
261 cur_tok = strtok(NULL, " \t");
262 if( !cur_tok ){
263 /* This mark was generated by an older version of Fossil and doesn't
264 ** include the mark name and uuid. create_mark() will name the new mark
265 ** exactly as it was when exported to git, so that we should have a
266 ** valid mapping from git hash<->mark name<->fossil hash. */
267 unsigned int mid;
268 if( type_=='c' ){
269 mid = COMMITMARK(mark->rid);
270 }
271 else{
272
+2 -2
--- src/foci.c
+++ src/foci.c
@@ -28,11 +28,11 @@
2828
** The "schema" for the temp.foci table is:
2929
**
3030
** CREATE TABLE files_of_checkin(
3131
** checkinID INTEGER, -- RID for the check-in manifest
3232
** filename TEXT, -- Name of a file
33
-** uuid TEXT, -- SHA1 hash of the file
33
+** uuid TEXT, -- hash of the file
3434
** previousName TEXT, -- Name of the file in previous check-in
3535
** perm TEXT, -- Permissions on the file
3636
** symname TEXT HIDDEN -- Symbolic name of the check-in.
3737
** );
3838
**
@@ -54,11 +54,11 @@
5454
*/
5555
static const char zFociSchema[] =
5656
@ CREATE TABLE files_of_checkin(
5757
@ checkinID INTEGER, -- RID for the check-in manifest
5858
@ filename TEXT, -- Name of a file
59
-@ uuid TEXT, -- SHA1 hash of the file
59
+@ uuid TEXT, -- hash of the file
6060
@ previousName TEXT, -- Name of the file in previous check-in
6161
@ perm TEXT, -- Permissions on the file
6262
@ symname TEXT HIDDEN -- Symbolic name of the check-in
6363
@ );
6464
;
6565
--- src/foci.c
+++ src/foci.c
@@ -28,11 +28,11 @@
28 ** The "schema" for the temp.foci table is:
29 **
30 ** CREATE TABLE files_of_checkin(
31 ** checkinID INTEGER, -- RID for the check-in manifest
32 ** filename TEXT, -- Name of a file
33 ** uuid TEXT, -- SHA1 hash of the file
34 ** previousName TEXT, -- Name of the file in previous check-in
35 ** perm TEXT, -- Permissions on the file
36 ** symname TEXT HIDDEN -- Symbolic name of the check-in.
37 ** );
38 **
@@ -54,11 +54,11 @@
54 */
55 static const char zFociSchema[] =
56 @ CREATE TABLE files_of_checkin(
57 @ checkinID INTEGER, -- RID for the check-in manifest
58 @ filename TEXT, -- Name of a file
59 @ uuid TEXT, -- SHA1 hash of the file
60 @ previousName TEXT, -- Name of the file in previous check-in
61 @ perm TEXT, -- Permissions on the file
62 @ symname TEXT HIDDEN -- Symbolic name of the check-in
63 @ );
64 ;
65
--- src/foci.c
+++ src/foci.c
@@ -28,11 +28,11 @@
28 ** The "schema" for the temp.foci table is:
29 **
30 ** CREATE TABLE files_of_checkin(
31 ** checkinID INTEGER, -- RID for the check-in manifest
32 ** filename TEXT, -- Name of a file
33 ** uuid TEXT, -- hash of the file
34 ** previousName TEXT, -- Name of the file in previous check-in
35 ** perm TEXT, -- Permissions on the file
36 ** symname TEXT HIDDEN -- Symbolic name of the check-in.
37 ** );
38 **
@@ -54,11 +54,11 @@
54 */
55 static const char zFociSchema[] =
56 @ CREATE TABLE files_of_checkin(
57 @ checkinID INTEGER, -- RID for the check-in manifest
58 @ filename TEXT, -- Name of a file
59 @ uuid TEXT, -- hash of the file
60 @ previousName TEXT, -- Name of the file in previous check-in
61 @ perm TEXT, -- Permissions on the file
62 @ symname TEXT HIDDEN -- Symbolic name of the check-in
63 @ );
64 ;
65
+1 -1
--- src/fusefs.c
+++ src/fusefs.c
@@ -294,11 +294,11 @@
294294
** This command uses the Fuse Filesystem (FuseFS) to mount a directory
295295
** at DIRECTORY that contains the content of all check-ins in the
296296
** repository. The names of files are DIRECTORY/checkins/VERSION/PATH
297297
** where DIRECTORY is the root of the mount, VERSION is any valid
298298
** check-in name (examples: "trunk" or "tip" or a tag or any unique
299
-** prefix of a SHA1 hash, etc) and PATH is the pathname of the file in
299
+** prefix of an artifact hash, etc) and PATH is the pathname of the file in
300300
** the check-in. If DIRECTORY does not exist, then an attempt is made
301301
** to create it.
302302
**
303303
** The DIRECTORY/checkins directory is not searchable so one cannot
304304
** do "ls DIRECTORY/checkins" to get a listing of all possible check-in
305305
--- src/fusefs.c
+++ src/fusefs.c
@@ -294,11 +294,11 @@
294 ** This command uses the Fuse Filesystem (FuseFS) to mount a directory
295 ** at DIRECTORY that contains the content of all check-ins in the
296 ** repository. The names of files are DIRECTORY/checkins/VERSION/PATH
297 ** where DIRECTORY is the root of the mount, VERSION is any valid
298 ** check-in name (examples: "trunk" or "tip" or a tag or any unique
299 ** prefix of a SHA1 hash, etc) and PATH is the pathname of the file in
300 ** the check-in. If DIRECTORY does not exist, then an attempt is made
301 ** to create it.
302 **
303 ** The DIRECTORY/checkins directory is not searchable so one cannot
304 ** do "ls DIRECTORY/checkins" to get a listing of all possible check-in
305
--- src/fusefs.c
+++ src/fusefs.c
@@ -294,11 +294,11 @@
294 ** This command uses the Fuse Filesystem (FuseFS) to mount a directory
295 ** at DIRECTORY that contains the content of all check-ins in the
296 ** repository. The names of files are DIRECTORY/checkins/VERSION/PATH
297 ** where DIRECTORY is the root of the mount, VERSION is any valid
298 ** check-in name (examples: "trunk" or "tip" or a tag or any unique
299 ** prefix of an artifact hash, etc) and PATH is the pathname of the file in
300 ** the check-in. If DIRECTORY does not exist, then an attempt is made
301 ** to create it.
302 **
303 ** The DIRECTORY/checkins directory is not searchable so one cannot
304 ** do "ls DIRECTORY/checkins" to get a listing of all possible check-in
305
+1 -1
--- src/graph.c
+++ src/graph.c
@@ -179,11 +179,11 @@
179179
int rid, /* RID for the check-in */
180180
int nParent, /* Number of parents */
181181
int *aParent, /* Array of parents */
182182
const char *zBranch, /* Branch for this check-in */
183183
const char *zBgClr, /* Background color. NULL or "" for white. */
184
- const char *zUuid, /* SHA1 hash of the object being graphed */
184
+ const char *zUuid, /* hash name of the object being graphed */
185185
int isLeaf /* True if this row is a leaf */
186186
){
187187
GraphRow *pRow;
188188
int nByte;
189189
190190
191191
ADDED src/hname.c
--- src/graph.c
+++ src/graph.c
@@ -179,11 +179,11 @@
179 int rid, /* RID for the check-in */
180 int nParent, /* Number of parents */
181 int *aParent, /* Array of parents */
182 const char *zBranch, /* Branch for this check-in */
183 const char *zBgClr, /* Background color. NULL or "" for white. */
184 const char *zUuid, /* SHA1 hash of the object being graphed */
185 int isLeaf /* True if this row is a leaf */
186 ){
187 GraphRow *pRow;
188 int nByte;
189
190
191 DDED src/hname.c
--- src/graph.c
+++ src/graph.c
@@ -179,11 +179,11 @@
179 int rid, /* RID for the check-in */
180 int nParent, /* Number of parents */
181 int *aParent, /* Array of parents */
182 const char *zBranch, /* Branch for this check-in */
183 const char *zBgClr, /* Background color. NULL or "" for white. */
184 const char *zUuid, /* hash name of the object being graphed */
185 int isLeaf /* True if this row is a leaf */
186 ){
187 GraphRow *pRow;
188 int nByte;
189
190
191 DDED src/hname.c
+11
--- a/src/hname.c
+++ b/src/hname.c
@@ -0,0 +1,11 @@
1
+/*
2
+** Copyright (c) 2017 D. Richard Hipp
3
+**
4
+** This program is free software; you can redistribute it and/or
5
+** modify it under the termoftware; you can redistribute it and/or
6
+** modify it under the term/*
7
+** Copyright (c) 2017 D. Richard Hipp
8
+**
9
+** This program is free software; you can redistribute it and/or
10
+** modify it under the termsha1sum_file(zFileBlob hash;
11
+ re
--- a/src/hname.c
+++ b/src/hname.c
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
--- a/src/hname.c
+++ b/src/hname.c
@@ -0,0 +1,11 @@
1 /*
2 ** Copyright (c) 2017 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the termoftware; you can redistribute it and/or
6 ** modify it under the term/*
7 ** Copyright (c) 2017 D. Richard Hipp
8 **
9 ** This program is free software; you can redistribute it and/or
10 ** modify it under the termsha1sum_file(zFileBlob hash;
11 re
+2 -2
--- src/import.c
+++ src/import.c
@@ -149,18 +149,18 @@
149149
** UUID in gg.zPrevCheckin.
150150
*/
151151
static int fast_insert_content(
152152
Blob *pContent, /* Content to insert */
153153
const char *zMark, /* Label using this mark, if not NULL */
154
- int saveUuid, /* Save SHA1 hash in gg.zPrevCheckin */
154
+ int saveUuid, /* Save artifact hash in gg.zPrevCheckin */
155155
int doParse /* Invoke manifest_crosslink() */
156156
){
157157
Blob hash;
158158
Blob cmpr;
159159
int rid;
160160
161
- sha1sum_blob(pContent, &hash);
161
+ hname_hash(pContent, 0, &hash);
162162
rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &hash);
163163
if( rid==0 ){
164164
static Stmt ins;
165165
db_static_prepare(&ins,
166166
"INSERT INTO blob(uuid, size, content) VALUES(:uuid, :size, :content)"
167167
--- src/import.c
+++ src/import.c
@@ -149,18 +149,18 @@
149 ** UUID in gg.zPrevCheckin.
150 */
151 static int fast_insert_content(
152 Blob *pContent, /* Content to insert */
153 const char *zMark, /* Label using this mark, if not NULL */
154 int saveUuid, /* Save SHA1 hash in gg.zPrevCheckin */
155 int doParse /* Invoke manifest_crosslink() */
156 ){
157 Blob hash;
158 Blob cmpr;
159 int rid;
160
161 sha1sum_blob(pContent, &hash);
162 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &hash);
163 if( rid==0 ){
164 static Stmt ins;
165 db_static_prepare(&ins,
166 "INSERT INTO blob(uuid, size, content) VALUES(:uuid, :size, :content)"
167
--- src/import.c
+++ src/import.c
@@ -149,18 +149,18 @@
149 ** UUID in gg.zPrevCheckin.
150 */
151 static int fast_insert_content(
152 Blob *pContent, /* Content to insert */
153 const char *zMark, /* Label using this mark, if not NULL */
154 int saveUuid, /* Save artifact hash in gg.zPrevCheckin */
155 int doParse /* Invoke manifest_crosslink() */
156 ){
157 Blob hash;
158 Blob cmpr;
159 int rid;
160
161 hname_hash(pContent, 0, &hash);
162 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &hash);
163 if( rid==0 ){
164 static Stmt ins;
165 db_static_prepare(&ins,
166 "INSERT INTO blob(uuid, size, content) VALUES(:uuid, :size, :content)"
167
+7 -5
--- src/info.c
+++ src/info.c
@@ -68,11 +68,11 @@
6868
zDate = db_text(0,
6969
"SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
7070
rid
7171
);
7272
/* 01234567890123 */
73
- fossil_print("%-13s %s %s\n", zUuidName, zUuid, zDate ? zDate : "");
73
+ fossil_print("%-13s %.40s %s\n", zUuidName, zUuid, zDate ? zDate : "");
7474
free(zDate);
7575
if( showComment ){
7676
zComment = db_text(0,
7777
"SELECT coalesce(ecomment,comment) || "
7878
" ' (user: ' || coalesce(euser,user,'?') || ')' "
@@ -91,11 +91,11 @@
9191
const char *zType = db_column_int(&q, 2) ? "parent:" : "merged-from:";
9292
zDate = db_text("",
9393
"SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
9494
db_column_int(&q, 1)
9595
);
96
- fossil_print("%-13s %s %s\n", zType, zUuid, zDate);
96
+ fossil_print("%-13s %.40s %s\n", zType, zUuid, zDate);
9797
free(zDate);
9898
}
9999
db_finalize(&q);
100100
db_prepare(&q, "SELECT uuid, cid, isprim FROM plink JOIN blob ON cid=rid "
101101
" WHERE pid=%d"
@@ -105,11 +105,11 @@
105105
const char *zType = db_column_int(&q, 2) ? "child:" : "merged-into:";
106106
zDate = db_text("",
107107
"SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
108108
db_column_int(&q, 1)
109109
);
110
- fossil_print("%-13s %s %s\n", zType, zUuid, zDate);
110
+ fossil_print("%-13s %.40s %s\n", zType, zUuid, zDate);
111111
free(zDate);
112112
}
113113
db_finalize(&q);
114114
}
115115
zTags = info_tags_of_checkin(rid, 0);
@@ -572,10 +572,11 @@
572572
rid, rid
573573
);
574574
sideBySide = !is_false(PD("sbs","1"));
575575
if( db_step(&q1)==SQLITE_ROW ){
576576
const char *zUuid = db_column_text(&q1, 0);
577
+ int nUuid = db_column_bytes(&q1, 0);
577578
char *zEUser, *zEComment;
578579
const char *zUser;
579580
const char *zComment;
580581
const char *zDate;
581582
const char *zOrigDate;
@@ -593,11 +594,11 @@
593594
zComment = db_column_text(&q1, 3);
594595
zDate = db_column_text(&q1,1);
595596
zOrigDate = db_column_text(&q1, 4);
596597
@ <div class="section">Overview</div>
597598
@ <table class="label-value">
598
- @ <tr><th>SHA1&nbsp;Hash:</th><td>%s(zUuid)
599
+ @ <tr><th>%s(hname_alg(nUuid)):</th><td>%s(zUuid)
599600
if( g.perm.Setup ){
600601
@ (Record ID: %d(rid))
601602
}
602603
@ </td></tr>
603604
@ <tr><th>Date:</th><td>
@@ -1385,10 +1386,11 @@
13851386
" ORDER BY mtime DESC /*sort*/",
13861387
rid
13871388
);
13881389
while( db_step(&q)==SQLITE_ROW ){
13891390
const char *zTarget = db_column_text(&q, 0);
1391
+ int nTarget = db_column_bytes(&q, 0);
13901392
const char *zFilename = db_column_text(&q, 1);
13911393
const char *zDate = db_column_text(&q, 2);
13921394
const char *zUser = db_column_text(&q, 3);
13931395
/* const char *zSrc = db_column_text(&q, 4); */
13941396
if( cnt>0 ){
@@ -1395,11 +1397,11 @@
13951397
@ Also attachment "%h(zFilename)" to
13961398
}else{
13971399
@ Attachment "%h(zFilename)" to
13981400
}
13991401
objType |= OBJTYPE_ATTACHMENT;
1400
- if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
1402
+ if( nTarget==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
14011403
if ( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
14021404
zTarget)
14031405
){
14041406
if( g.perm.Hyperlink && g.anon.RdTkt ){
14051407
@ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>]
14061408
--- src/info.c
+++ src/info.c
@@ -68,11 +68,11 @@
68 zDate = db_text(0,
69 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
70 rid
71 );
72 /* 01234567890123 */
73 fossil_print("%-13s %s %s\n", zUuidName, zUuid, zDate ? zDate : "");
74 free(zDate);
75 if( showComment ){
76 zComment = db_text(0,
77 "SELECT coalesce(ecomment,comment) || "
78 " ' (user: ' || coalesce(euser,user,'?') || ')' "
@@ -91,11 +91,11 @@
91 const char *zType = db_column_int(&q, 2) ? "parent:" : "merged-from:";
92 zDate = db_text("",
93 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
94 db_column_int(&q, 1)
95 );
96 fossil_print("%-13s %s %s\n", zType, zUuid, zDate);
97 free(zDate);
98 }
99 db_finalize(&q);
100 db_prepare(&q, "SELECT uuid, cid, isprim FROM plink JOIN blob ON cid=rid "
101 " WHERE pid=%d"
@@ -105,11 +105,11 @@
105 const char *zType = db_column_int(&q, 2) ? "child:" : "merged-into:";
106 zDate = db_text("",
107 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
108 db_column_int(&q, 1)
109 );
110 fossil_print("%-13s %s %s\n", zType, zUuid, zDate);
111 free(zDate);
112 }
113 db_finalize(&q);
114 }
115 zTags = info_tags_of_checkin(rid, 0);
@@ -572,10 +572,11 @@
572 rid, rid
573 );
574 sideBySide = !is_false(PD("sbs","1"));
575 if( db_step(&q1)==SQLITE_ROW ){
576 const char *zUuid = db_column_text(&q1, 0);
 
577 char *zEUser, *zEComment;
578 const char *zUser;
579 const char *zComment;
580 const char *zDate;
581 const char *zOrigDate;
@@ -593,11 +594,11 @@
593 zComment = db_column_text(&q1, 3);
594 zDate = db_column_text(&q1,1);
595 zOrigDate = db_column_text(&q1, 4);
596 @ <div class="section">Overview</div>
597 @ <table class="label-value">
598 @ <tr><th>SHA1&nbsp;Hash:</th><td>%s(zUuid)
599 if( g.perm.Setup ){
600 @ (Record ID: %d(rid))
601 }
602 @ </td></tr>
603 @ <tr><th>Date:</th><td>
@@ -1385,10 +1386,11 @@
1385 " ORDER BY mtime DESC /*sort*/",
1386 rid
1387 );
1388 while( db_step(&q)==SQLITE_ROW ){
1389 const char *zTarget = db_column_text(&q, 0);
 
1390 const char *zFilename = db_column_text(&q, 1);
1391 const char *zDate = db_column_text(&q, 2);
1392 const char *zUser = db_column_text(&q, 3);
1393 /* const char *zSrc = db_column_text(&q, 4); */
1394 if( cnt>0 ){
@@ -1395,11 +1397,11 @@
1395 @ Also attachment "%h(zFilename)" to
1396 }else{
1397 @ Attachment "%h(zFilename)" to
1398 }
1399 objType |= OBJTYPE_ATTACHMENT;
1400 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
1401 if ( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
1402 zTarget)
1403 ){
1404 if( g.perm.Hyperlink && g.anon.RdTkt ){
1405 @ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>]
1406
--- src/info.c
+++ src/info.c
@@ -68,11 +68,11 @@
68 zDate = db_text(0,
69 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
70 rid
71 );
72 /* 01234567890123 */
73 fossil_print("%-13s %.40s %s\n", zUuidName, zUuid, zDate ? zDate : "");
74 free(zDate);
75 if( showComment ){
76 zComment = db_text(0,
77 "SELECT coalesce(ecomment,comment) || "
78 " ' (user: ' || coalesce(euser,user,'?') || ')' "
@@ -91,11 +91,11 @@
91 const char *zType = db_column_int(&q, 2) ? "parent:" : "merged-from:";
92 zDate = db_text("",
93 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
94 db_column_int(&q, 1)
95 );
96 fossil_print("%-13s %.40s %s\n", zType, zUuid, zDate);
97 free(zDate);
98 }
99 db_finalize(&q);
100 db_prepare(&q, "SELECT uuid, cid, isprim FROM plink JOIN blob ON cid=rid "
101 " WHERE pid=%d"
@@ -105,11 +105,11 @@
105 const char *zType = db_column_int(&q, 2) ? "child:" : "merged-into:";
106 zDate = db_text("",
107 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
108 db_column_int(&q, 1)
109 );
110 fossil_print("%-13s %.40s %s\n", zType, zUuid, zDate);
111 free(zDate);
112 }
113 db_finalize(&q);
114 }
115 zTags = info_tags_of_checkin(rid, 0);
@@ -572,10 +572,11 @@
572 rid, rid
573 );
574 sideBySide = !is_false(PD("sbs","1"));
575 if( db_step(&q1)==SQLITE_ROW ){
576 const char *zUuid = db_column_text(&q1, 0);
577 int nUuid = db_column_bytes(&q1, 0);
578 char *zEUser, *zEComment;
579 const char *zUser;
580 const char *zComment;
581 const char *zDate;
582 const char *zOrigDate;
@@ -593,11 +594,11 @@
594 zComment = db_column_text(&q1, 3);
595 zDate = db_column_text(&q1,1);
596 zOrigDate = db_column_text(&q1, 4);
597 @ <div class="section">Overview</div>
598 @ <table class="label-value">
599 @ <tr><th>%s(hname_alg(nUuid)):</th><td>%s(zUuid)
600 if( g.perm.Setup ){
601 @ (Record ID: %d(rid))
602 }
603 @ </td></tr>
604 @ <tr><th>Date:</th><td>
@@ -1385,10 +1386,11 @@
1386 " ORDER BY mtime DESC /*sort*/",
1387 rid
1388 );
1389 while( db_step(&q)==SQLITE_ROW ){
1390 const char *zTarget = db_column_text(&q, 0);
1391 int nTarget = db_column_bytes(&q, 0);
1392 const char *zFilename = db_column_text(&q, 1);
1393 const char *zDate = db_column_text(&q, 2);
1394 const char *zUser = db_column_text(&q, 3);
1395 /* const char *zSrc = db_column_text(&q, 4); */
1396 if( cnt>0 ){
@@ -1395,11 +1397,11 @@
1397 @ Also attachment "%h(zFilename)" to
1398 }else{
1399 @ Attachment "%h(zFilename)" to
1400 }
1401 objType |= OBJTYPE_ATTACHMENT;
1402 if( nTarget==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
1403 if ( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
1404 zTarget)
1405 ){
1406 if( g.perm.Hyperlink && g.anon.RdTkt ){
1407 @ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>]
1408
+13 -2
--- src/main.c
+++ src/main.c
@@ -50,11 +50,16 @@
5050
# include "cson_amalgamation.h" /* JSON API. */
5151
# include "json_detail.h"
5252
#endif
5353
5454
/*
55
-** Size of a UUID in characters
55
+** Size of a UUID in characters. A UUID is a randomly generated
56
+** lower-case hexadecimal number used to identify tickets.
57
+**
58
+** In Fossil 1.x, UUID also referred to a SHA1 artifact hash. But that
59
+** usage is now obsolete. The term UUID should now mean only a very large
60
+** random number used as a unique identifier for tickets or other objects.
5661
*/
5762
#define UUID_SIZE 40
5863
5964
/*
6065
** Maximum number of auxiliary parameters on reports
@@ -135,10 +140,11 @@
135140
char *zLocalDbName; /* Name of the local database file */
136141
char *zOpenRevision; /* Check-in version to use during database open */
137142
int localOpen; /* True if the local database is open */
138143
char *zLocalRoot; /* The directory holding the local database */
139144
int minPrefix; /* Number of digits needed for a distinct UUID */
145
+ int eHashPolicy; /* Current hash policy. One of HPOLICY_* */
140146
int fNoDirSymlinks; /* True if --no-dir-symlinks flag is present */
141147
int fSqlTrace; /* True if --sqltrace flag is present */
142148
int fSqlStats; /* True if --sqltrace or --sqlstats are present */
143149
int fSqlPrint; /* True if -sqlprint flag is present */
144150
int fQuiet; /* True if -quiet flag is present */
@@ -930,10 +936,13 @@
930936
#if defined(FOSSIL_ENABLE_MINIZ)
931937
blob_appendf(pOut, "miniz %s, loaded %s\n", MZ_VERSION, mz_version());
932938
#else
933939
blob_appendf(pOut, "zlib %s, loaded %s\n", ZLIB_VERSION, zlibVersion());
934940
#endif
941
+#if FOSSIL_HARDENED_SHA1
942
+ blob_appendf(pOut, "hardened-SHA1 by Marc Stevens and Dan Shumow\n");
943
+#endif
935944
#if defined(FOSSIL_ENABLE_SSL)
936945
blob_appendf(pOut, "SSL (%s)\n", SSLeay_version(SSLEAY_VERSION));
937946
#endif
938947
#if defined(FOSSIL_HAVE_FUSEFS)
939948
blob_appendf(pOut, "libfuse %s, loaded %s\n", fusefs_inc_version(),
@@ -1997,11 +2006,11 @@
19972006
** the name of that directory and the specific repository will be
19982007
** opened later by process_one_web_page() based on the content of
19992008
** the PATH_INFO variable.
20002009
**
20012010
** If the fCreate flag is set, then create the repository if it
2002
-** does not already exist.
2011
+** does not already exist. Always use "auto" hash-policy in this case.
20032012
*/
20042013
static void find_server_repository(int arg, int fCreate){
20052014
if( g.argc<=arg ){
20062015
db_must_be_within_tree();
20072016
}else{
@@ -2014,10 +2023,12 @@
20142023
if( isDir==0 && fCreate ){
20152024
const char *zPassword;
20162025
db_create_repository(zRepo);
20172026
db_open_repository(zRepo);
20182027
db_begin_transaction();
2028
+ g.eHashPolicy = HPOLICY_AUTO;
2029
+ db_set_int("hash-policy", HPOLICY_AUTO, 0);
20192030
db_initial_setup(0, "now", g.zLogin);
20202031
db_end_transaction(0);
20212032
fossil_print("project-id: %s\n", db_get("project-code", 0));
20222033
fossil_print("server-id: %s\n", db_get("server-code", 0));
20232034
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
20242035
--- src/main.c
+++ src/main.c
@@ -50,11 +50,16 @@
50 # include "cson_amalgamation.h" /* JSON API. */
51 # include "json_detail.h"
52 #endif
53
54 /*
55 ** Size of a UUID in characters
 
 
 
 
 
56 */
57 #define UUID_SIZE 40
58
59 /*
60 ** Maximum number of auxiliary parameters on reports
@@ -135,10 +140,11 @@
135 char *zLocalDbName; /* Name of the local database file */
136 char *zOpenRevision; /* Check-in version to use during database open */
137 int localOpen; /* True if the local database is open */
138 char *zLocalRoot; /* The directory holding the local database */
139 int minPrefix; /* Number of digits needed for a distinct UUID */
 
140 int fNoDirSymlinks; /* True if --no-dir-symlinks flag is present */
141 int fSqlTrace; /* True if --sqltrace flag is present */
142 int fSqlStats; /* True if --sqltrace or --sqlstats are present */
143 int fSqlPrint; /* True if -sqlprint flag is present */
144 int fQuiet; /* True if -quiet flag is present */
@@ -930,10 +936,13 @@
930 #if defined(FOSSIL_ENABLE_MINIZ)
931 blob_appendf(pOut, "miniz %s, loaded %s\n", MZ_VERSION, mz_version());
932 #else
933 blob_appendf(pOut, "zlib %s, loaded %s\n", ZLIB_VERSION, zlibVersion());
934 #endif
 
 
 
935 #if defined(FOSSIL_ENABLE_SSL)
936 blob_appendf(pOut, "SSL (%s)\n", SSLeay_version(SSLEAY_VERSION));
937 #endif
938 #if defined(FOSSIL_HAVE_FUSEFS)
939 blob_appendf(pOut, "libfuse %s, loaded %s\n", fusefs_inc_version(),
@@ -1997,11 +2006,11 @@
1997 ** the name of that directory and the specific repository will be
1998 ** opened later by process_one_web_page() based on the content of
1999 ** the PATH_INFO variable.
2000 **
2001 ** If the fCreate flag is set, then create the repository if it
2002 ** does not already exist.
2003 */
2004 static void find_server_repository(int arg, int fCreate){
2005 if( g.argc<=arg ){
2006 db_must_be_within_tree();
2007 }else{
@@ -2014,10 +2023,12 @@
2014 if( isDir==0 && fCreate ){
2015 const char *zPassword;
2016 db_create_repository(zRepo);
2017 db_open_repository(zRepo);
2018 db_begin_transaction();
 
 
2019 db_initial_setup(0, "now", g.zLogin);
2020 db_end_transaction(0);
2021 fossil_print("project-id: %s\n", db_get("project-code", 0));
2022 fossil_print("server-id: %s\n", db_get("server-code", 0));
2023 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
2024
--- src/main.c
+++ src/main.c
@@ -50,11 +50,16 @@
50 # include "cson_amalgamation.h" /* JSON API. */
51 # include "json_detail.h"
52 #endif
53
54 /*
55 ** Size of a UUID in characters. A UUID is a randomly generated
56 ** lower-case hexadecimal number used to identify tickets.
57 **
58 ** In Fossil 1.x, UUID also referred to a SHA1 artifact hash. But that
59 ** usage is now obsolete. The term UUID should now mean only a very large
60 ** random number used as a unique identifier for tickets or other objects.
61 */
62 #define UUID_SIZE 40
63
64 /*
65 ** Maximum number of auxiliary parameters on reports
@@ -135,10 +140,11 @@
140 char *zLocalDbName; /* Name of the local database file */
141 char *zOpenRevision; /* Check-in version to use during database open */
142 int localOpen; /* True if the local database is open */
143 char *zLocalRoot; /* The directory holding the local database */
144 int minPrefix; /* Number of digits needed for a distinct UUID */
145 int eHashPolicy; /* Current hash policy. One of HPOLICY_* */
146 int fNoDirSymlinks; /* True if --no-dir-symlinks flag is present */
147 int fSqlTrace; /* True if --sqltrace flag is present */
148 int fSqlStats; /* True if --sqltrace or --sqlstats are present */
149 int fSqlPrint; /* True if -sqlprint flag is present */
150 int fQuiet; /* True if -quiet flag is present */
@@ -930,10 +936,13 @@
936 #if defined(FOSSIL_ENABLE_MINIZ)
937 blob_appendf(pOut, "miniz %s, loaded %s\n", MZ_VERSION, mz_version());
938 #else
939 blob_appendf(pOut, "zlib %s, loaded %s\n", ZLIB_VERSION, zlibVersion());
940 #endif
941 #if FOSSIL_HARDENED_SHA1
942 blob_appendf(pOut, "hardened-SHA1 by Marc Stevens and Dan Shumow\n");
943 #endif
944 #if defined(FOSSIL_ENABLE_SSL)
945 blob_appendf(pOut, "SSL (%s)\n", SSLeay_version(SSLEAY_VERSION));
946 #endif
947 #if defined(FOSSIL_HAVE_FUSEFS)
948 blob_appendf(pOut, "libfuse %s, loaded %s\n", fusefs_inc_version(),
@@ -1997,11 +2006,11 @@
2006 ** the name of that directory and the specific repository will be
2007 ** opened later by process_one_web_page() based on the content of
2008 ** the PATH_INFO variable.
2009 **
2010 ** If the fCreate flag is set, then create the repository if it
2011 ** does not already exist. Always use "auto" hash-policy in this case.
2012 */
2013 static void find_server_repository(int arg, int fCreate){
2014 if( g.argc<=arg ){
2015 db_must_be_within_tree();
2016 }else{
@@ -2014,10 +2023,12 @@
2023 if( isDir==0 && fCreate ){
2024 const char *zPassword;
2025 db_create_repository(zRepo);
2026 db_open_repository(zRepo);
2027 db_begin_transaction();
2028 g.eHashPolicy = HPOLICY_AUTO;
2029 db_set_int("hash-policy", HPOLICY_AUTO, 0);
2030 db_initial_setup(0, "now", g.zLogin);
2031 db_end_transaction(0);
2032 fossil_print("project-id: %s\n", db_get("project-code", 0));
2033 fossil_print("server-id: %s\n", db_get("server-code", 0));
2034 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
2035
+36
--- src/main.mk
+++ src/main.mk
@@ -52,10 +52,11 @@
5252
$(SRCDIR)/fshell.c \
5353
$(SRCDIR)/fusefs.c \
5454
$(SRCDIR)/glob.c \
5555
$(SRCDIR)/graph.c \
5656
$(SRCDIR)/gzip.c \
57
+ $(SRCDIR)/hname.c \
5758
$(SRCDIR)/http.c \
5859
$(SRCDIR)/http_socket.c \
5960
$(SRCDIR)/http_ssl.c \
6061
$(SRCDIR)/http_transport.c \
6162
$(SRCDIR)/import.c \
@@ -102,10 +103,12 @@
102103
$(SRCDIR)/rss.c \
103104
$(SRCDIR)/schema.c \
104105
$(SRCDIR)/search.c \
105106
$(SRCDIR)/setup.c \
106107
$(SRCDIR)/sha1.c \
108
+ $(SRCDIR)/sha1hard.c \
109
+ $(SRCDIR)/sha3.c \
107110
$(SRCDIR)/shun.c \
108111
$(SRCDIR)/sitemap.c \
109112
$(SRCDIR)/skins.c \
110113
$(SRCDIR)/sqlcmd.c \
111114
$(SRCDIR)/stash.c \
@@ -227,10 +230,11 @@
227230
$(OBJDIR)/fshell_.c \
228231
$(OBJDIR)/fusefs_.c \
229232
$(OBJDIR)/glob_.c \
230233
$(OBJDIR)/graph_.c \
231234
$(OBJDIR)/gzip_.c \
235
+ $(OBJDIR)/hname_.c \
232236
$(OBJDIR)/http_.c \
233237
$(OBJDIR)/http_socket_.c \
234238
$(OBJDIR)/http_ssl_.c \
235239
$(OBJDIR)/http_transport_.c \
236240
$(OBJDIR)/import_.c \
@@ -277,10 +281,12 @@
277281
$(OBJDIR)/rss_.c \
278282
$(OBJDIR)/schema_.c \
279283
$(OBJDIR)/search_.c \
280284
$(OBJDIR)/setup_.c \
281285
$(OBJDIR)/sha1_.c \
286
+ $(OBJDIR)/sha1hard_.c \
287
+ $(OBJDIR)/sha3_.c \
282288
$(OBJDIR)/shun_.c \
283289
$(OBJDIR)/sitemap_.c \
284290
$(OBJDIR)/skins_.c \
285291
$(OBJDIR)/sqlcmd_.c \
286292
$(OBJDIR)/stash_.c \
@@ -351,10 +357,11 @@
351357
$(OBJDIR)/fshell.o \
352358
$(OBJDIR)/fusefs.o \
353359
$(OBJDIR)/glob.o \
354360
$(OBJDIR)/graph.o \
355361
$(OBJDIR)/gzip.o \
362
+ $(OBJDIR)/hname.o \
356363
$(OBJDIR)/http.o \
357364
$(OBJDIR)/http_socket.o \
358365
$(OBJDIR)/http_ssl.o \
359366
$(OBJDIR)/http_transport.o \
360367
$(OBJDIR)/import.o \
@@ -401,10 +408,12 @@
401408
$(OBJDIR)/rss.o \
402409
$(OBJDIR)/schema.o \
403410
$(OBJDIR)/search.o \
404411
$(OBJDIR)/setup.o \
405412
$(OBJDIR)/sha1.o \
413
+ $(OBJDIR)/sha1hard.o \
414
+ $(OBJDIR)/sha3.o \
406415
$(OBJDIR)/shun.o \
407416
$(OBJDIR)/sitemap.o \
408417
$(OBJDIR)/skins.o \
409418
$(OBJDIR)/sqlcmd.o \
410419
$(OBJDIR)/stash.o \
@@ -636,10 +645,11 @@
636645
$(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
637646
$(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
638647
$(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \
639648
$(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \
640649
$(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \
650
+ $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \
641651
$(OBJDIR)/http_.c:$(OBJDIR)/http.h \
642652
$(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \
643653
$(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \
644654
$(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \
645655
$(OBJDIR)/import_.c:$(OBJDIR)/import.h \
@@ -686,10 +696,12 @@
686696
$(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
687697
$(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
688698
$(OBJDIR)/search_.c:$(OBJDIR)/search.h \
689699
$(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
690700
$(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
701
+ $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \
702
+ $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \
691703
$(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
692704
$(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
693705
$(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
694706
$(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
695707
$(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
@@ -1037,10 +1049,18 @@
10371049
10381050
$(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h
10391051
$(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c
10401052
10411053
$(OBJDIR)/gzip.h: $(OBJDIR)/headers
1054
+
1055
+$(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(OBJDIR)/translate
1056
+ $(OBJDIR)/translate $(SRCDIR)/hname.c >$@
1057
+
1058
+$(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h
1059
+ $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c
1060
+
1061
+$(OBJDIR)/hname.h: $(OBJDIR)/headers
10421062
10431063
$(OBJDIR)/http_.c: $(SRCDIR)/http.c $(OBJDIR)/translate
10441064
$(OBJDIR)/translate $(SRCDIR)/http.c >$@
10451065
10461066
$(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h
@@ -1437,10 +1457,26 @@
14371457
14381458
$(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h
14391459
$(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c
14401460
14411461
$(OBJDIR)/sha1.h: $(OBJDIR)/headers
1462
+
1463
+$(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(OBJDIR)/translate
1464
+ $(OBJDIR)/translate $(SRCDIR)/sha1hard.c >$@
1465
+
1466
+$(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h
1467
+ $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c
1468
+
1469
+$(OBJDIR)/sha1hard.h: $(OBJDIR)/headers
1470
+
1471
+$(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(OBJDIR)/translate
1472
+ $(OBJDIR)/translate $(SRCDIR)/sha3.c >$@
1473
+
1474
+$(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h
1475
+ $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c
1476
+
1477
+$(OBJDIR)/sha3.h: $(OBJDIR)/headers
14421478
14431479
$(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(OBJDIR)/translate
14441480
$(OBJDIR)/translate $(SRCDIR)/shun.c >$@
14451481
14461482
$(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
14471483
--- src/main.mk
+++ src/main.mk
@@ -52,10 +52,11 @@
52 $(SRCDIR)/fshell.c \
53 $(SRCDIR)/fusefs.c \
54 $(SRCDIR)/glob.c \
55 $(SRCDIR)/graph.c \
56 $(SRCDIR)/gzip.c \
 
57 $(SRCDIR)/http.c \
58 $(SRCDIR)/http_socket.c \
59 $(SRCDIR)/http_ssl.c \
60 $(SRCDIR)/http_transport.c \
61 $(SRCDIR)/import.c \
@@ -102,10 +103,12 @@
102 $(SRCDIR)/rss.c \
103 $(SRCDIR)/schema.c \
104 $(SRCDIR)/search.c \
105 $(SRCDIR)/setup.c \
106 $(SRCDIR)/sha1.c \
 
 
107 $(SRCDIR)/shun.c \
108 $(SRCDIR)/sitemap.c \
109 $(SRCDIR)/skins.c \
110 $(SRCDIR)/sqlcmd.c \
111 $(SRCDIR)/stash.c \
@@ -227,10 +230,11 @@
227 $(OBJDIR)/fshell_.c \
228 $(OBJDIR)/fusefs_.c \
229 $(OBJDIR)/glob_.c \
230 $(OBJDIR)/graph_.c \
231 $(OBJDIR)/gzip_.c \
 
232 $(OBJDIR)/http_.c \
233 $(OBJDIR)/http_socket_.c \
234 $(OBJDIR)/http_ssl_.c \
235 $(OBJDIR)/http_transport_.c \
236 $(OBJDIR)/import_.c \
@@ -277,10 +281,12 @@
277 $(OBJDIR)/rss_.c \
278 $(OBJDIR)/schema_.c \
279 $(OBJDIR)/search_.c \
280 $(OBJDIR)/setup_.c \
281 $(OBJDIR)/sha1_.c \
 
 
282 $(OBJDIR)/shun_.c \
283 $(OBJDIR)/sitemap_.c \
284 $(OBJDIR)/skins_.c \
285 $(OBJDIR)/sqlcmd_.c \
286 $(OBJDIR)/stash_.c \
@@ -351,10 +357,11 @@
351 $(OBJDIR)/fshell.o \
352 $(OBJDIR)/fusefs.o \
353 $(OBJDIR)/glob.o \
354 $(OBJDIR)/graph.o \
355 $(OBJDIR)/gzip.o \
 
356 $(OBJDIR)/http.o \
357 $(OBJDIR)/http_socket.o \
358 $(OBJDIR)/http_ssl.o \
359 $(OBJDIR)/http_transport.o \
360 $(OBJDIR)/import.o \
@@ -401,10 +408,12 @@
401 $(OBJDIR)/rss.o \
402 $(OBJDIR)/schema.o \
403 $(OBJDIR)/search.o \
404 $(OBJDIR)/setup.o \
405 $(OBJDIR)/sha1.o \
 
 
406 $(OBJDIR)/shun.o \
407 $(OBJDIR)/sitemap.o \
408 $(OBJDIR)/skins.o \
409 $(OBJDIR)/sqlcmd.o \
410 $(OBJDIR)/stash.o \
@@ -636,10 +645,11 @@
636 $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
637 $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
638 $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \
639 $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \
640 $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \
 
641 $(OBJDIR)/http_.c:$(OBJDIR)/http.h \
642 $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \
643 $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \
644 $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \
645 $(OBJDIR)/import_.c:$(OBJDIR)/import.h \
@@ -686,10 +696,12 @@
686 $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
687 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
688 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
689 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
690 $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
 
 
691 $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
692 $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
693 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
694 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
695 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
@@ -1037,10 +1049,18 @@
1037
1038 $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h
1039 $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c
1040
1041 $(OBJDIR)/gzip.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1042
1043 $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(OBJDIR)/translate
1044 $(OBJDIR)/translate $(SRCDIR)/http.c >$@
1045
1046 $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h
@@ -1437,10 +1457,26 @@
1437
1438 $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h
1439 $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c
1440
1441 $(OBJDIR)/sha1.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1442
1443 $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(OBJDIR)/translate
1444 $(OBJDIR)/translate $(SRCDIR)/shun.c >$@
1445
1446 $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
1447
--- src/main.mk
+++ src/main.mk
@@ -52,10 +52,11 @@
52 $(SRCDIR)/fshell.c \
53 $(SRCDIR)/fusefs.c \
54 $(SRCDIR)/glob.c \
55 $(SRCDIR)/graph.c \
56 $(SRCDIR)/gzip.c \
57 $(SRCDIR)/hname.c \
58 $(SRCDIR)/http.c \
59 $(SRCDIR)/http_socket.c \
60 $(SRCDIR)/http_ssl.c \
61 $(SRCDIR)/http_transport.c \
62 $(SRCDIR)/import.c \
@@ -102,10 +103,12 @@
103 $(SRCDIR)/rss.c \
104 $(SRCDIR)/schema.c \
105 $(SRCDIR)/search.c \
106 $(SRCDIR)/setup.c \
107 $(SRCDIR)/sha1.c \
108 $(SRCDIR)/sha1hard.c \
109 $(SRCDIR)/sha3.c \
110 $(SRCDIR)/shun.c \
111 $(SRCDIR)/sitemap.c \
112 $(SRCDIR)/skins.c \
113 $(SRCDIR)/sqlcmd.c \
114 $(SRCDIR)/stash.c \
@@ -227,10 +230,11 @@
230 $(OBJDIR)/fshell_.c \
231 $(OBJDIR)/fusefs_.c \
232 $(OBJDIR)/glob_.c \
233 $(OBJDIR)/graph_.c \
234 $(OBJDIR)/gzip_.c \
235 $(OBJDIR)/hname_.c \
236 $(OBJDIR)/http_.c \
237 $(OBJDIR)/http_socket_.c \
238 $(OBJDIR)/http_ssl_.c \
239 $(OBJDIR)/http_transport_.c \
240 $(OBJDIR)/import_.c \
@@ -277,10 +281,12 @@
281 $(OBJDIR)/rss_.c \
282 $(OBJDIR)/schema_.c \
283 $(OBJDIR)/search_.c \
284 $(OBJDIR)/setup_.c \
285 $(OBJDIR)/sha1_.c \
286 $(OBJDIR)/sha1hard_.c \
287 $(OBJDIR)/sha3_.c \
288 $(OBJDIR)/shun_.c \
289 $(OBJDIR)/sitemap_.c \
290 $(OBJDIR)/skins_.c \
291 $(OBJDIR)/sqlcmd_.c \
292 $(OBJDIR)/stash_.c \
@@ -351,10 +357,11 @@
357 $(OBJDIR)/fshell.o \
358 $(OBJDIR)/fusefs.o \
359 $(OBJDIR)/glob.o \
360 $(OBJDIR)/graph.o \
361 $(OBJDIR)/gzip.o \
362 $(OBJDIR)/hname.o \
363 $(OBJDIR)/http.o \
364 $(OBJDIR)/http_socket.o \
365 $(OBJDIR)/http_ssl.o \
366 $(OBJDIR)/http_transport.o \
367 $(OBJDIR)/import.o \
@@ -401,10 +408,12 @@
408 $(OBJDIR)/rss.o \
409 $(OBJDIR)/schema.o \
410 $(OBJDIR)/search.o \
411 $(OBJDIR)/setup.o \
412 $(OBJDIR)/sha1.o \
413 $(OBJDIR)/sha1hard.o \
414 $(OBJDIR)/sha3.o \
415 $(OBJDIR)/shun.o \
416 $(OBJDIR)/sitemap.o \
417 $(OBJDIR)/skins.o \
418 $(OBJDIR)/sqlcmd.o \
419 $(OBJDIR)/stash.o \
@@ -636,10 +645,11 @@
645 $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
646 $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
647 $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \
648 $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \
649 $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \
650 $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \
651 $(OBJDIR)/http_.c:$(OBJDIR)/http.h \
652 $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \
653 $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \
654 $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \
655 $(OBJDIR)/import_.c:$(OBJDIR)/import.h \
@@ -686,10 +696,12 @@
696 $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
697 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
698 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
699 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
700 $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
701 $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \
702 $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \
703 $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
704 $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
705 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
706 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
707 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
@@ -1037,10 +1049,18 @@
1049
1050 $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h
1051 $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c
1052
1053 $(OBJDIR)/gzip.h: $(OBJDIR)/headers
1054
1055 $(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(OBJDIR)/translate
1056 $(OBJDIR)/translate $(SRCDIR)/hname.c >$@
1057
1058 $(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h
1059 $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c
1060
1061 $(OBJDIR)/hname.h: $(OBJDIR)/headers
1062
1063 $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(OBJDIR)/translate
1064 $(OBJDIR)/translate $(SRCDIR)/http.c >$@
1065
1066 $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h
@@ -1437,10 +1457,26 @@
1457
1458 $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h
1459 $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c
1460
1461 $(OBJDIR)/sha1.h: $(OBJDIR)/headers
1462
1463 $(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(OBJDIR)/translate
1464 $(OBJDIR)/translate $(SRCDIR)/sha1hard.c >$@
1465
1466 $(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h
1467 $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c
1468
1469 $(OBJDIR)/sha1hard.h: $(OBJDIR)/headers
1470
1471 $(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(OBJDIR)/translate
1472 $(OBJDIR)/translate $(SRCDIR)/sha3.c >$@
1473
1474 $(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h
1475 $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c
1476
1477 $(OBJDIR)/sha3.h: $(OBJDIR)/headers
1478
1479 $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(OBJDIR)/translate
1480 $(OBJDIR)/translate $(SRCDIR)/shun.c >$@
1481
1482 $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
1483
--- src/makeheaders.c
+++ src/makeheaders.c
@@ -1017,11 +1017,14 @@
10171017
/* printf("%04d: Type=%d nIf=%d [%.*s]\n",
10181018
pToken->nLine,pToken->eType,nIf,pToken->nText,
10191019
pToken->eType!=TT_Space ? pToken->zText : "<space>"); */
10201020
pToken->pComment = blockComment;
10211021
switch( pToken->eType ){
1022
- case TT_Comment:
1022
+ case TT_Comment: /*0123456789 12345678 */
1023
+ if( strncmp(pToken->zText, "/*MAKEHEADERS-STOP", 18)==0 ) return nErr;
1024
+ break;
1025
+
10231026
case TT_Space:
10241027
break;
10251028
10261029
case TT_BlockComment:
10271030
if( doc_flag ){
@@ -2181,10 +2184,12 @@
21812184
if( nArg==9 && strncmp(zArg,"INTERFACE",9)==0 ){
21822185
PushIfMacro(0,0,0,pToken->nLine,PS_Interface);
21832186
}else if( nArg==16 && strncmp(zArg,"EXPORT_INTERFACE",16)==0 ){
21842187
PushIfMacro(0,0,0,pToken->nLine,PS_Export);
21852188
}else if( nArg==15 && strncmp(zArg,"LOCAL_INTERFACE",15)==0 ){
2189
+ PushIfMacro(0,0,0,pToken->nLine,PS_Local);
2190
+ }else if( nArg==15 && strncmp(zArg,"MAKEHEADERS_STOPLOCAL_INTERFACE",15)==0 ){
21862191
PushIfMacro(0,0,0,pToken->nLine,PS_Local);
21872192
}else{
21882193
PushIfMacro(0,zArg,nArg,pToken->nLine,0);
21892194
}
21902195
}else if( nCmd==5 && strncmp(zCmd,"ifdef",5)==0 ){
21912196
--- src/makeheaders.c
+++ src/makeheaders.c
@@ -1017,11 +1017,14 @@
1017 /* printf("%04d: Type=%d nIf=%d [%.*s]\n",
1018 pToken->nLine,pToken->eType,nIf,pToken->nText,
1019 pToken->eType!=TT_Space ? pToken->zText : "<space>"); */
1020 pToken->pComment = blockComment;
1021 switch( pToken->eType ){
1022 case TT_Comment:
 
 
 
1023 case TT_Space:
1024 break;
1025
1026 case TT_BlockComment:
1027 if( doc_flag ){
@@ -2181,10 +2184,12 @@
2181 if( nArg==9 && strncmp(zArg,"INTERFACE",9)==0 ){
2182 PushIfMacro(0,0,0,pToken->nLine,PS_Interface);
2183 }else if( nArg==16 && strncmp(zArg,"EXPORT_INTERFACE",16)==0 ){
2184 PushIfMacro(0,0,0,pToken->nLine,PS_Export);
2185 }else if( nArg==15 && strncmp(zArg,"LOCAL_INTERFACE",15)==0 ){
 
 
2186 PushIfMacro(0,0,0,pToken->nLine,PS_Local);
2187 }else{
2188 PushIfMacro(0,zArg,nArg,pToken->nLine,0);
2189 }
2190 }else if( nCmd==5 && strncmp(zCmd,"ifdef",5)==0 ){
2191
--- src/makeheaders.c
+++ src/makeheaders.c
@@ -1017,11 +1017,14 @@
1017 /* printf("%04d: Type=%d nIf=%d [%.*s]\n",
1018 pToken->nLine,pToken->eType,nIf,pToken->nText,
1019 pToken->eType!=TT_Space ? pToken->zText : "<space>"); */
1020 pToken->pComment = blockComment;
1021 switch( pToken->eType ){
1022 case TT_Comment: /*0123456789 12345678 */
1023 if( strncmp(pToken->zText, "/*MAKEHEADERS-STOP", 18)==0 ) return nErr;
1024 break;
1025
1026 case TT_Space:
1027 break;
1028
1029 case TT_BlockComment:
1030 if( doc_flag ){
@@ -2181,10 +2184,12 @@
2184 if( nArg==9 && strncmp(zArg,"INTERFACE",9)==0 ){
2185 PushIfMacro(0,0,0,pToken->nLine,PS_Interface);
2186 }else if( nArg==16 && strncmp(zArg,"EXPORT_INTERFACE",16)==0 ){
2187 PushIfMacro(0,0,0,pToken->nLine,PS_Export);
2188 }else if( nArg==15 && strncmp(zArg,"LOCAL_INTERFACE",15)==0 ){
2189 PushIfMacro(0,0,0,pToken->nLine,PS_Local);
2190 }else if( nArg==15 && strncmp(zArg,"MAKEHEADERS_STOPLOCAL_INTERFACE",15)==0 ){
2191 PushIfMacro(0,0,0,pToken->nLine,PS_Local);
2192 }else{
2193 PushIfMacro(0,zArg,nArg,pToken->nLine,0);
2194 }
2195 }else if( nCmd==5 && strncmp(zCmd,"ifdef",5)==0 ){
2196
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -58,10 +58,11 @@
5858
fshell
5959
fusefs
6060
glob
6161
graph
6262
gzip
63
+ hname
6364
http
6465
http_socket
6566
http_transport
6667
import
6768
info
@@ -107,10 +108,12 @@
107108
rss
108109
schema
109110
search
110111
setup
111112
sha1
113
+ sha1hard
114
+ sha3
112115
shun
113116
sitemap
114117
skins
115118
sqlcmd
116119
stash
117120
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -58,10 +58,11 @@
58 fshell
59 fusefs
60 glob
61 graph
62 gzip
 
63 http
64 http_socket
65 http_transport
66 import
67 info
@@ -107,10 +108,12 @@
107 rss
108 schema
109 search
110 setup
111 sha1
 
 
112 shun
113 sitemap
114 skins
115 sqlcmd
116 stash
117
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -58,10 +58,11 @@
58 fshell
59 fusefs
60 glob
61 graph
62 gzip
63 hname
64 http
65 http_socket
66 http_transport
67 import
68 info
@@ -107,10 +108,12 @@
108 rss
109 schema
110 search
111 setup
112 sha1
113 sha1hard
114 sha3
115 shun
116 sitemap
117 skins
118 sqlcmd
119 stash
120
+80 -80
--- src/manifest.c
+++ src/manifest.c
@@ -54,11 +54,11 @@
5454
/*
5555
** A single F-card within a manifest
5656
*/
5757
struct ManifestFile {
5858
char *zName; /* Name of a file */
59
- char *zUuid; /* UUID of the file */
59
+ char *zUuid; /* Artifact hash for the file */
6060
char *zPerm; /* File permissions */
6161
char *zPrior; /* Prior name if the name was changed */
6262
};
6363
6464
@@ -77,35 +77,35 @@
7777
char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */
7878
char *zWiki; /* Text of the wiki page. W card. */
7979
char *zWikiTitle; /* Name of the wiki page. L card. */
8080
char *zMimetype; /* Mime type of wiki or comment text. N card. */
8181
double rEventDate; /* Date of an event. E card. */
82
- char *zEventId; /* UUID for an event. E card. */
82
+ char *zEventId; /* Artifact hash for an event. E card. */
8383
char *zTicketUuid; /* UUID for a ticket. K card. */
8484
char *zAttachName; /* Filename of an attachment. A card. */
85
- char *zAttachSrc; /* UUID of document being attached. A card. */
85
+ char *zAttachSrc; /* Artifact hash for document being attached. A card. */
8686
char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */
8787
int nFile; /* Number of F cards */
8888
int nFileAlloc; /* Slots allocated in aFile[] */
8989
int iFile; /* Index of current file in iterator */
9090
ManifestFile *aFile; /* One entry for each F-card */
9191
int nParent; /* Number of parents. */
9292
int nParentAlloc; /* Slots allocated in azParent[] */
93
- char **azParent; /* UUIDs of parents. One for each P card argument */
93
+ char **azParent; /* Hashes of parents. One for each P card argument */
9494
int nCherrypick; /* Number of entries in aCherrypick[] */
9595
struct {
96
- char *zCPTarget; /* UUID of cherry-picked version w/ +|- prefix */
97
- char *zCPBase; /* UUID of cherry-pick baseline. NULL for singletons */
96
+ char *zCPTarget; /* Hash for cherry-picked version w/ +|- prefix */
97
+ char *zCPBase; /* Hash for cherry-pick baseline. NULL for singletons */
9898
} *aCherrypick;
9999
int nCChild; /* Number of cluster children */
100100
int nCChildAlloc; /* Number of closts allocated in azCChild[] */
101
- char **azCChild; /* UUIDs of referenced objects in a cluster. M cards */
101
+ char **azCChild; /* Hashes of referenced objects in a cluster. M cards */
102102
int nTag; /* Number of T Cards */
103103
int nTagAlloc; /* Slots allocated in aTag[] */
104104
struct TagType {
105105
char *zName; /* Name of the tag */
106
- char *zUuid; /* UUID that the tag is applied to */
106
+ char *zUuid; /* Hash of artifact that the tag is applied to */
107107
char *zValue; /* Value if the tag is really a property */
108108
} *aTag; /* One for each T card */
109109
int nField; /* Number of J cards */
110110
int nFieldAlloc; /* Slots allocated in aField[] */
111111
struct {
@@ -327,26 +327,27 @@
327327
** takes over the input blob and will free it when the
328328
** Manifest object is freed. Zeros are inserted into the blob
329329
** as string terminators so that blob should not be used again.
330330
**
331331
** Return a pointer to an allocated Manifest object if the content
332
-** really is a control file of some kind. This object needs to be
333
-** freed by a subsequent call to manifest_destroy(). Return NULL
334
-** if there are syntax errors.
332
+** really is a structural artifact of some kind. The returned Manifest
333
+** object needs to be freed by a subsequent call to manifest_destroy().
334
+** Return NULL if there are syntax errors or if the input blob does
335
+** not describe a valid structural artifact.
335336
**
336
-** This routine is strict about the format of a control file.
337
+** This routine is strict about the format of a structural artifacts.
337338
** The format must match exactly or else it is rejected. This
338
-** rule minimizes the risk that a content file will be mistaken
339
-** for a control file simply because they look the same.
339
+** rule minimizes the risk that a content artifact will be mistaken
340
+** for a structural artifact simply because they look the same.
340341
**
341342
** The pContent is reset. If a pointer is returned, then pContent will
342343
** be reset when the Manifest object is cleared. If NULL is
343344
** returned then the Manifest object is cleared automatically
344345
** and pContent is reset before the return.
345346
**
346
-** The entire file can be PGP clear-signed. The signature is ignored.
347
-** The file consists of zero or more cards, one card per line.
347
+** The entire input blob can be PGP clear-signed. The signature is ignored.
348
+** The artifact consists of zero or more cards, one card per line.
348349
** (Except: the content of the W card can extend of multiple lines.)
349350
** Each card is divided into tokens by a single space character.
350351
** The first token is a single upper-case letter which is the card type.
351352
** The card type determines the other parameters to the card.
352353
** Cards must occur in lexicographical order.
@@ -361,11 +362,10 @@
361362
char *z;
362363
int n;
363364
char *zUuid;
364365
int sz = 0;
365366
int isRepeat, hasSelfRefTag = 0;
366
- Blob bUuid = BLOB_INITIALIZER;
367367
static Bag seen;
368368
const char *zErr = 0;
369369
370370
if( rid==0 ){
371371
isRepeat = 1;
@@ -374,11 +374,11 @@
374374
}else{
375375
isRepeat = 0;
376376
bag_insert(&seen, rid);
377377
}
378378
379
- /* Every control artifact ends with a '\n' character. Exit early
379
+ /* Every structural artifact ends with a '\n' character. Exit early
380380
** if that is not the case for this artifact.
381381
*/
382382
if( !isRepeat ) g.parseCnt[0]++;
383383
z = blob_materialize(pContent);
384384
n = blob_size(pContent);
@@ -406,15 +406,10 @@
406406
blob_reset(pContent);
407407
blob_appendf(pErr, "incorrect Z-card cksum");
408408
return 0;
409409
}
410410
411
- /* Store the UUID (before modifying the blob) only for error
412
- ** reporting purposes.
413
- */
414
- sha1sum_blob(pContent, &bUuid);
415
-
416411
/* Allocate a Manifest object to hold the parsed control artifact.
417412
*/
418413
p = fossil_malloc( sizeof(*p) );
419414
memset(p, 0, sizeof(*p));
420415
memcpy(&p->content, pContent, sizeof(p->content));
@@ -449,15 +444,15 @@
449444
defossilize(zName);
450445
if( !file_is_simple_pathname(zName, 0) ){
451446
SYNTAX("invalid filename on A-card");
452447
}
453448
defossilize(zTarget);
454
- if( (nTarget!=UUID_SIZE || !validate16(zTarget, UUID_SIZE))
449
+ if( !hname_validate(zTarget,nTarget)
455450
&& !wiki_name_is_wellformed((const unsigned char *)zTarget) ){
456451
SYNTAX("invalid target on A-card");
457452
}
458
- if( zSrc && (nSrc!=UUID_SIZE || !validate16(zSrc, UUID_SIZE)) ){
453
+ if( zSrc && !hname_validate(zSrc,nSrc) ){
459454
SYNTAX("invalid source on A-card");
460455
}
461456
p->zAttachName = (char*)file_tail(zName);
462457
p->zAttachSrc = zSrc;
463458
p->zAttachTarget = zTarget;
@@ -465,18 +460,18 @@
465460
}
466461
467462
/*
468463
** B <uuid>
469464
**
470
- ** A B-line gives the UUID for the baseline of a delta-manifest.
465
+ ** A B-line gives the artifact hash for the baseline of a delta-manifest.
471466
*/
472467
case 'B': {
473468
if( p->zBaseline ) SYNTAX("more than one B-card");
474469
p->zBaseline = next_token(&x, &sz);
475
- if( p->zBaseline==0 ) SYNTAX("missing UUID on B-card");
476
- if( sz!=UUID_SIZE || !validate16(p->zBaseline, UUID_SIZE) ){
477
- SYNTAX("invalid UUID on B-card");
470
+ if( p->zBaseline==0 ) SYNTAX("missing hash on B-card");
471
+ if( !hname_validate(p->zBaseline,sz) ){
472
+ SYNTAX("invalid hash on B-card");
478473
}
479474
break;
480475
}
481476
482477
@@ -522,12 +517,12 @@
522517
case 'E': {
523518
if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
524519
p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
525520
if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
526521
p->zEventId = next_token(&x, &sz);
527
- if( sz!=UUID_SIZE || !validate16(p->zEventId, UUID_SIZE) ){
528
- SYNTAX("malformed UUID on E-card");
522
+ if( !hname_validate(p->zEventId, sz) ){
523
+ SYNTAX("malformed hash on E-card");
529524
}
530525
break;
531526
}
532527
533528
/*
@@ -545,12 +540,13 @@
545540
if( !file_is_simple_pathname(zName, 0) ){
546541
SYNTAX("F-card filename is not a simple path");
547542
}
548543
zUuid = next_token(&x, &sz);
549544
if( p->zBaseline==0 || zUuid!=0 ){
550
- if( sz!=UUID_SIZE ) SYNTAX("F-card UUID is the wrong size");
551
- if( !validate16(zUuid, UUID_SIZE) ) SYNTAX("F-card UUID invalid");
545
+ if( !hname_validate(zUuid,sz) ){
546
+ SYNTAX("F-card hash invalid");
547
+ }
552548
}
553549
zPerm = next_token(&x,0);
554550
zPriorName = next_token(&x,0);
555551
if( zPriorName ){
556552
defossilize(zPriorName);
@@ -636,20 +632,21 @@
636632
}
637633
break;
638634
}
639635
640636
/*
641
- ** M <uuid>
637
+ ** M <hash>
642638
**
643
- ** An M-line identifies another artifact by its UUID. M-lines
639
+ ** An M-line identifies another artifact by its hash. M-lines
644640
** occur in clusters only.
645641
*/
646642
case 'M': {
647643
zUuid = next_token(&x, &sz);
648
- if( zUuid==0 ) SYNTAX("missing UUID on M-card");
649
- if( sz!=UUID_SIZE ) SYNTAX("wrong size for UUID on M-card");
650
- if( !validate16(zUuid, UUID_SIZE) ) SYNTAX("UUID invalid on M-card");
644
+ if( zUuid==0 ) SYNTAX("missing hash on M-card");
645
+ if( !hname_validate(zUuid,sz) ){
646
+ SYNTAX("Invalid hash on M-card");
647
+ }
651648
if( p->nCChild>=p->nCChildAlloc ){
652649
p->nCChildAlloc = p->nCChildAlloc*2 + 10;
653650
p->azCChild = fossil_realloc(p->azCChild
654651
, p->nCChildAlloc*sizeof(p->azCChild[0]) );
655652
}
@@ -683,12 +680,13 @@
683680
** check-in historically has an empty P-card, so empty P-cards
684681
** must be accepted.
685682
*/
686683
case 'P': {
687684
while( (zUuid = next_token(&x, &sz))!=0 ){
688
- if( sz!=UUID_SIZE ) SYNTAX("wrong size UUID on P-card");
689
- if( !validate16(zUuid, UUID_SIZE) )SYNTAX("invalid UUID on P-card");
685
+ if( !hname_validate(zUuid, sz) ){
686
+ SYNTAX("invalid hash on P-card");
687
+ }
690688
if( p->nParent>=p->nParentAlloc ){
691689
p->nParentAlloc = p->nParentAlloc*2 + 5;
692690
p->azParent = fossil_realloc(p->azParent,
693691
p->nParentAlloc*sizeof(char*));
694692
}
@@ -703,29 +701,25 @@
703701
**
704702
** Specify one or a range of check-ins that are cherrypicked into
705703
** this check-in ("+") or backed out of this check-in ("-").
706704
*/
707705
case 'Q': {
708
- if( (zUuid=next_token(&x, &sz))==0 ) SYNTAX("missing UUID on Q-card");
709
- if( sz!=UUID_SIZE+1 ) SYNTAX("wrong size UUID on Q-card");
706
+ if( (zUuid=next_token(&x, &sz))==0 ) SYNTAX("missing hash on Q-card");
710707
if( zUuid[0]!='+' && zUuid[0]!='-' ){
711708
SYNTAX("Q-card does not begin with '+' or '-'");
712709
}
713
- if( !validate16(&zUuid[1], UUID_SIZE) ){
714
- SYNTAX("invalid UUID on Q-card");
710
+ if( !hname_validate(&zUuid[1], sz-1) ){
711
+ SYNTAX("invalid hash on Q-card");
715712
}
716713
n = p->nCherrypick;
717714
p->nCherrypick++;
718715
p->aCherrypick = fossil_realloc(p->aCherrypick,
719716
p->nCherrypick*sizeof(p->aCherrypick[0]));
720717
p->aCherrypick[n].zCPTarget = zUuid;
721718
p->aCherrypick[n].zCPBase = zUuid = next_token(&x, &sz);
722
- if( zUuid ){
723
- if( sz!=UUID_SIZE ) SYNTAX("wrong size second UUID in Q-card");
724
- if( !validate16(zUuid, UUID_SIZE) ){
725
- SYNTAX("invalid second UUID on Q-card");
726
- }
719
+ if( zUuid && !hname_validate(zUuid,sz) ){
720
+ SYNTAX("invalid second hash on Q-card");
727721
}
728722
break;
729723
}
730724
731725
/*
@@ -760,32 +754,32 @@
760754
case 'T': {
761755
char *zName, *zValue;
762756
zName = next_token(&x, 0);
763757
if( zName==0 ) SYNTAX("missing name on T-card");
764758
zUuid = next_token(&x, &sz);
765
- if( zUuid==0 ) SYNTAX("missing UUID on T-card");
759
+ if( zUuid==0 ) SYNTAX("missing artifact hash on T-card");
766760
zValue = next_token(&x, 0);
767761
if( zValue ) defossilize(zValue);
768
- if( sz==UUID_SIZE && validate16(zUuid, UUID_SIZE) ){
769
- /* A valid uuid */
762
+ if( hname_validate(zUuid, sz) ){
763
+ /* A valid artifact hash */
770764
if( p->zEventId ) SYNTAX("non-self-referential T-card in event");
771765
}else if( sz==1 && zUuid[0]=='*' ){
772766
zUuid = 0;
773767
hasSelfRefTag = 1;
774768
if( p->zEventId && zName[0]!='+' ){
775769
SYNTAX("propagating T-card in event");
776770
}
777771
}else{
778
- SYNTAX("malformed UUID on T-card");
772
+ SYNTAX("malformed artifact hash on T-card");
779773
}
780774
defossilize(zName);
781775
if( zName[0]!='-' && zName[0]!='+' && zName[0]!='*' ){
782776
SYNTAX("T-card name does not begin with '-', '+', or '*'");
783777
}
784778
if( validate16(&zName[1], strlen(&zName[1])) ){
785
- /* Do not allow tags whose names look like UUIDs */
786
- SYNTAX("T-card name looks like a UUID");
779
+ /* Do not allow tags whose names look like a hash */
780
+ SYNTAX("T-card name looks like a hexadecimal hash");
787781
}
788782
if( p->nTag>=p->nTagAlloc ){
789783
p->nTagAlloc = p->nTagAlloc*2 + 10;
790784
p->aTag = fossil_realloc(p->aTag, p->nTagAlloc*sizeof(p->aTag[0]) );
791785
}
@@ -951,17 +945,19 @@
951945
if( !seenZ ) SYNTAX("missing Z-card on control");
952946
p->type = CFTYPE_CONTROL;
953947
}
954948
md5sum_init();
955949
if( !isRepeat ) g.parseCnt[p->type]++;
956
- blob_reset(&bUuid);
957950
return p;
958951
959952
manifest_syntax_error:
960
- if(bUuid.nUsed){
961
- blob_appendf(pErr, "manifest [%.40s] ", blob_str(&bUuid));
962
- blob_reset(&bUuid);
953
+ {
954
+ char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
955
+ if( zUuid ){
956
+ blob_appendf(pErr, "manifest [%s] ", zUuid);
957
+ fossil_free(zUuid);
958
+ }
963959
}
964960
if( zErr ){
965961
blob_appendf(pErr, "line %d: %s", lineNo, zErr);
966962
}else{
967963
blob_appendf(pErr, "unknown error on line %d", lineNo);
@@ -1193,13 +1189,13 @@
11931189
** then the mlink entry is only created if there is already an mlink
11941190
** from primary parent for the same file.
11951191
*/
11961192
static void add_one_mlink(
11971193
int pmid, /* The parent manifest */
1198
- const char *zFromUuid, /* UUID for content in parent */
1194
+ const char *zFromUuid, /* Artifact hash for content in parent */
11991195
int mid, /* The record ID of the manifest */
1200
- const char *zToUuid, /* UUID for content in child */
1196
+ const char *zToUuid, /* artifact hash for content in child */
12011197
const char *zFilename, /* Filename */
12021198
const char *zPrior, /* Previous filename. NULL if unchanged */
12031199
int isPublic, /* True if mid is not a private manifest */
12041200
int isPrimary, /* pmid is the primary parent of mid */
12051201
int mperm /* 1: exec, 2: symlink */
@@ -1545,22 +1541,22 @@
15451541
}
15461542
}
15471543
15481544
/*
15491545
** For a check-in with RID "rid" that has nParent parent check-ins given
1550
-** by the UUIDs in azParent[], create all appropriate plink and mlink table
1546
+** by the hashes in azParent[], create all appropriate plink and mlink table
15511547
** entries.
15521548
**
1553
-** The primary parent is the first UUID on the azParent[] list.
1549
+** The primary parent is the first hash on the azParent[] list.
15541550
**
15551551
** Return the RID of the primary parent.
15561552
*/
15571553
static int manifest_add_checkin_linkages(
15581554
int rid, /* The RID of the check-in */
15591555
Manifest *p, /* Manifest for this check-in */
15601556
int nParent, /* Number of parents for this check-in */
1561
- char **azParent /* UUIDs for each parent */
1557
+ char **azParent /* hashes for each parent */
15621558
){
15631559
int i;
15641560
int parentid = 0;
15651561
char zBaseId[30]; /* Baseline manifest RID for deltas. "NULL" otherwise */
15661562
Stmt q;
@@ -1611,33 +1607,36 @@
16111607
return parentid;
16121608
}
16131609
16141610
/*
16151611
** There exists a "parent" tag against checkin rid that has value zValue.
1616
-** If value is well-formed (meaning that it is a list of UUIDs), then use
1612
+** If value is well-formed (meaning that it is a list of hashes), then use
16171613
** zValue to reparent check-in rid.
16181614
*/
16191615
void manifest_reparent_checkin(int rid, const char *zValue){
1620
- int nParent;
1616
+ int nParent = 0;
16211617
char *zCopy = 0;
16221618
char **azParent = 0;
16231619
Manifest *p = 0;
1624
- int i;
1620
+ int i, j;
16251621
int n = (int)strlen(zValue);
1626
- nParent = (n+1)/(UUID_SIZE+1);
1627
- if( nParent*(UUID_SIZE+1) - 1 !=n ) return;
1628
- if( nParent<1 ) return;
1622
+ int mxParent = (n+1)/(HNAME_MIN+1);
1623
+
1624
+ if( mxParent<1 ) return;
16291625
zCopy = fossil_strdup(zValue);
1630
- azParent = fossil_malloc( sizeof(azParent[0])*nParent );
1631
- for(i=0; i<nParent; i++){
1632
- azParent[i] = &zCopy[i*(UUID_SIZE+1)];
1633
- if( i<nParent-1 && azParent[i][UUID_SIZE]!=' ' ) break;
1634
- azParent[i][UUID_SIZE] = 0;
1635
- if( !validate16(azParent[i],UUID_SIZE) ) break;
1636
- }
1637
- if( i==nParent
1638
- && !db_exists("SELECT 1 FROM plink WHERE cid=%d AND pid=%d",
1626
+ azParent = fossil_malloc( sizeof(azParent[0])*mxParent );
1627
+ for(nParent=0, i=0; zCopy[i]; i++){
1628
+ char *z = &zCopy[i];
1629
+ azParent[nParent++] = z;
1630
+ if( nParent>mxParent ) goto reparent_abort;
1631
+ for(j=HNAME_MIN; z[j]>' '; j++){}
1632
+ if( !hname_validate(z, j) ) goto reparent_abort;
1633
+ if( z[j]==0 ) break;
1634
+ z[j] = 0;
1635
+ i += j;
1636
+ }
1637
+ if( !db_exists("SELECT 1 FROM plink WHERE cid=%d AND pid=%d",
16391638
rid, uuid_to_rid(azParent[0],0))
16401639
){
16411640
p = manifest_get(rid, CFTYPE_MANIFEST, 0);
16421641
}
16431642
if( p!=0 ){
@@ -1647,10 +1646,11 @@
16471646
rid, rid
16481647
);
16491648
manifest_add_checkin_linkages(rid,p,nParent,azParent);
16501649
}
16511650
manifest_destroy(p);
1651
+reparent_abort:
16521652
fossil_free(azParent);
16531653
fossil_free(zCopy);
16541654
}
16551655
16561656
/*
@@ -2280,11 +2280,11 @@
22802280
int branchMove = 0;
22812281
blob_zero(&comment);
22822282
if( p->zComment ){
22832283
blob_appendf(&comment, " %s.", p->zComment);
22842284
}
2285
- /* Next loop expects tags to be sorted on UUID, so sort it. */
2285
+ /* Next loop expects tags to be sorted on hash, so sort it. */
22862286
qsort(p->aTag, p->nTag, sizeof(p->aTag[0]), tag_compare);
22872287
for(i=0; i<p->nTag; i++){
22882288
zTagUuid = p->aTag[i].zUuid;
22892289
if( !zTagUuid ) continue;
22902290
if( i==0 || fossil_strcmp(zTagUuid, p->aTag[i-1].zUuid)!=0 ){
22912291
--- src/manifest.c
+++ src/manifest.c
@@ -54,11 +54,11 @@
54 /*
55 ** A single F-card within a manifest
56 */
57 struct ManifestFile {
58 char *zName; /* Name of a file */
59 char *zUuid; /* UUID of the file */
60 char *zPerm; /* File permissions */
61 char *zPrior; /* Prior name if the name was changed */
62 };
63
64
@@ -77,35 +77,35 @@
77 char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */
78 char *zWiki; /* Text of the wiki page. W card. */
79 char *zWikiTitle; /* Name of the wiki page. L card. */
80 char *zMimetype; /* Mime type of wiki or comment text. N card. */
81 double rEventDate; /* Date of an event. E card. */
82 char *zEventId; /* UUID for an event. E card. */
83 char *zTicketUuid; /* UUID for a ticket. K card. */
84 char *zAttachName; /* Filename of an attachment. A card. */
85 char *zAttachSrc; /* UUID of document being attached. A card. */
86 char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */
87 int nFile; /* Number of F cards */
88 int nFileAlloc; /* Slots allocated in aFile[] */
89 int iFile; /* Index of current file in iterator */
90 ManifestFile *aFile; /* One entry for each F-card */
91 int nParent; /* Number of parents. */
92 int nParentAlloc; /* Slots allocated in azParent[] */
93 char **azParent; /* UUIDs of parents. One for each P card argument */
94 int nCherrypick; /* Number of entries in aCherrypick[] */
95 struct {
96 char *zCPTarget; /* UUID of cherry-picked version w/ +|- prefix */
97 char *zCPBase; /* UUID of cherry-pick baseline. NULL for singletons */
98 } *aCherrypick;
99 int nCChild; /* Number of cluster children */
100 int nCChildAlloc; /* Number of closts allocated in azCChild[] */
101 char **azCChild; /* UUIDs of referenced objects in a cluster. M cards */
102 int nTag; /* Number of T Cards */
103 int nTagAlloc; /* Slots allocated in aTag[] */
104 struct TagType {
105 char *zName; /* Name of the tag */
106 char *zUuid; /* UUID that the tag is applied to */
107 char *zValue; /* Value if the tag is really a property */
108 } *aTag; /* One for each T card */
109 int nField; /* Number of J cards */
110 int nFieldAlloc; /* Slots allocated in aField[] */
111 struct {
@@ -327,26 +327,27 @@
327 ** takes over the input blob and will free it when the
328 ** Manifest object is freed. Zeros are inserted into the blob
329 ** as string terminators so that blob should not be used again.
330 **
331 ** Return a pointer to an allocated Manifest object if the content
332 ** really is a control file of some kind. This object needs to be
333 ** freed by a subsequent call to manifest_destroy(). Return NULL
334 ** if there are syntax errors.
 
335 **
336 ** This routine is strict about the format of a control file.
337 ** The format must match exactly or else it is rejected. This
338 ** rule minimizes the risk that a content file will be mistaken
339 ** for a control file simply because they look the same.
340 **
341 ** The pContent is reset. If a pointer is returned, then pContent will
342 ** be reset when the Manifest object is cleared. If NULL is
343 ** returned then the Manifest object is cleared automatically
344 ** and pContent is reset before the return.
345 **
346 ** The entire file can be PGP clear-signed. The signature is ignored.
347 ** The file consists of zero or more cards, one card per line.
348 ** (Except: the content of the W card can extend of multiple lines.)
349 ** Each card is divided into tokens by a single space character.
350 ** The first token is a single upper-case letter which is the card type.
351 ** The card type determines the other parameters to the card.
352 ** Cards must occur in lexicographical order.
@@ -361,11 +362,10 @@
361 char *z;
362 int n;
363 char *zUuid;
364 int sz = 0;
365 int isRepeat, hasSelfRefTag = 0;
366 Blob bUuid = BLOB_INITIALIZER;
367 static Bag seen;
368 const char *zErr = 0;
369
370 if( rid==0 ){
371 isRepeat = 1;
@@ -374,11 +374,11 @@
374 }else{
375 isRepeat = 0;
376 bag_insert(&seen, rid);
377 }
378
379 /* Every control artifact ends with a '\n' character. Exit early
380 ** if that is not the case for this artifact.
381 */
382 if( !isRepeat ) g.parseCnt[0]++;
383 z = blob_materialize(pContent);
384 n = blob_size(pContent);
@@ -406,15 +406,10 @@
406 blob_reset(pContent);
407 blob_appendf(pErr, "incorrect Z-card cksum");
408 return 0;
409 }
410
411 /* Store the UUID (before modifying the blob) only for error
412 ** reporting purposes.
413 */
414 sha1sum_blob(pContent, &bUuid);
415
416 /* Allocate a Manifest object to hold the parsed control artifact.
417 */
418 p = fossil_malloc( sizeof(*p) );
419 memset(p, 0, sizeof(*p));
420 memcpy(&p->content, pContent, sizeof(p->content));
@@ -449,15 +444,15 @@
449 defossilize(zName);
450 if( !file_is_simple_pathname(zName, 0) ){
451 SYNTAX("invalid filename on A-card");
452 }
453 defossilize(zTarget);
454 if( (nTarget!=UUID_SIZE || !validate16(zTarget, UUID_SIZE))
455 && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){
456 SYNTAX("invalid target on A-card");
457 }
458 if( zSrc && (nSrc!=UUID_SIZE || !validate16(zSrc, UUID_SIZE)) ){
459 SYNTAX("invalid source on A-card");
460 }
461 p->zAttachName = (char*)file_tail(zName);
462 p->zAttachSrc = zSrc;
463 p->zAttachTarget = zTarget;
@@ -465,18 +460,18 @@
465 }
466
467 /*
468 ** B <uuid>
469 **
470 ** A B-line gives the UUID for the baseline of a delta-manifest.
471 */
472 case 'B': {
473 if( p->zBaseline ) SYNTAX("more than one B-card");
474 p->zBaseline = next_token(&x, &sz);
475 if( p->zBaseline==0 ) SYNTAX("missing UUID on B-card");
476 if( sz!=UUID_SIZE || !validate16(p->zBaseline, UUID_SIZE) ){
477 SYNTAX("invalid UUID on B-card");
478 }
479 break;
480 }
481
482
@@ -522,12 +517,12 @@
522 case 'E': {
523 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
524 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
525 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
526 p->zEventId = next_token(&x, &sz);
527 if( sz!=UUID_SIZE || !validate16(p->zEventId, UUID_SIZE) ){
528 SYNTAX("malformed UUID on E-card");
529 }
530 break;
531 }
532
533 /*
@@ -545,12 +540,13 @@
545 if( !file_is_simple_pathname(zName, 0) ){
546 SYNTAX("F-card filename is not a simple path");
547 }
548 zUuid = next_token(&x, &sz);
549 if( p->zBaseline==0 || zUuid!=0 ){
550 if( sz!=UUID_SIZE ) SYNTAX("F-card UUID is the wrong size");
551 if( !validate16(zUuid, UUID_SIZE) ) SYNTAX("F-card UUID invalid");
 
552 }
553 zPerm = next_token(&x,0);
554 zPriorName = next_token(&x,0);
555 if( zPriorName ){
556 defossilize(zPriorName);
@@ -636,20 +632,21 @@
636 }
637 break;
638 }
639
640 /*
641 ** M <uuid>
642 **
643 ** An M-line identifies another artifact by its UUID. M-lines
644 ** occur in clusters only.
645 */
646 case 'M': {
647 zUuid = next_token(&x, &sz);
648 if( zUuid==0 ) SYNTAX("missing UUID on M-card");
649 if( sz!=UUID_SIZE ) SYNTAX("wrong size for UUID on M-card");
650 if( !validate16(zUuid, UUID_SIZE) ) SYNTAX("UUID invalid on M-card");
 
651 if( p->nCChild>=p->nCChildAlloc ){
652 p->nCChildAlloc = p->nCChildAlloc*2 + 10;
653 p->azCChild = fossil_realloc(p->azCChild
654 , p->nCChildAlloc*sizeof(p->azCChild[0]) );
655 }
@@ -683,12 +680,13 @@
683 ** check-in historically has an empty P-card, so empty P-cards
684 ** must be accepted.
685 */
686 case 'P': {
687 while( (zUuid = next_token(&x, &sz))!=0 ){
688 if( sz!=UUID_SIZE ) SYNTAX("wrong size UUID on P-card");
689 if( !validate16(zUuid, UUID_SIZE) )SYNTAX("invalid UUID on P-card");
 
690 if( p->nParent>=p->nParentAlloc ){
691 p->nParentAlloc = p->nParentAlloc*2 + 5;
692 p->azParent = fossil_realloc(p->azParent,
693 p->nParentAlloc*sizeof(char*));
694 }
@@ -703,29 +701,25 @@
703 **
704 ** Specify one or a range of check-ins that are cherrypicked into
705 ** this check-in ("+") or backed out of this check-in ("-").
706 */
707 case 'Q': {
708 if( (zUuid=next_token(&x, &sz))==0 ) SYNTAX("missing UUID on Q-card");
709 if( sz!=UUID_SIZE+1 ) SYNTAX("wrong size UUID on Q-card");
710 if( zUuid[0]!='+' && zUuid[0]!='-' ){
711 SYNTAX("Q-card does not begin with '+' or '-'");
712 }
713 if( !validate16(&zUuid[1], UUID_SIZE) ){
714 SYNTAX("invalid UUID on Q-card");
715 }
716 n = p->nCherrypick;
717 p->nCherrypick++;
718 p->aCherrypick = fossil_realloc(p->aCherrypick,
719 p->nCherrypick*sizeof(p->aCherrypick[0]));
720 p->aCherrypick[n].zCPTarget = zUuid;
721 p->aCherrypick[n].zCPBase = zUuid = next_token(&x, &sz);
722 if( zUuid ){
723 if( sz!=UUID_SIZE ) SYNTAX("wrong size second UUID in Q-card");
724 if( !validate16(zUuid, UUID_SIZE) ){
725 SYNTAX("invalid second UUID on Q-card");
726 }
727 }
728 break;
729 }
730
731 /*
@@ -760,32 +754,32 @@
760 case 'T': {
761 char *zName, *zValue;
762 zName = next_token(&x, 0);
763 if( zName==0 ) SYNTAX("missing name on T-card");
764 zUuid = next_token(&x, &sz);
765 if( zUuid==0 ) SYNTAX("missing UUID on T-card");
766 zValue = next_token(&x, 0);
767 if( zValue ) defossilize(zValue);
768 if( sz==UUID_SIZE && validate16(zUuid, UUID_SIZE) ){
769 /* A valid uuid */
770 if( p->zEventId ) SYNTAX("non-self-referential T-card in event");
771 }else if( sz==1 && zUuid[0]=='*' ){
772 zUuid = 0;
773 hasSelfRefTag = 1;
774 if( p->zEventId && zName[0]!='+' ){
775 SYNTAX("propagating T-card in event");
776 }
777 }else{
778 SYNTAX("malformed UUID on T-card");
779 }
780 defossilize(zName);
781 if( zName[0]!='-' && zName[0]!='+' && zName[0]!='*' ){
782 SYNTAX("T-card name does not begin with '-', '+', or '*'");
783 }
784 if( validate16(&zName[1], strlen(&zName[1])) ){
785 /* Do not allow tags whose names look like UUIDs */
786 SYNTAX("T-card name looks like a UUID");
787 }
788 if( p->nTag>=p->nTagAlloc ){
789 p->nTagAlloc = p->nTagAlloc*2 + 10;
790 p->aTag = fossil_realloc(p->aTag, p->nTagAlloc*sizeof(p->aTag[0]) );
791 }
@@ -951,17 +945,19 @@
951 if( !seenZ ) SYNTAX("missing Z-card on control");
952 p->type = CFTYPE_CONTROL;
953 }
954 md5sum_init();
955 if( !isRepeat ) g.parseCnt[p->type]++;
956 blob_reset(&bUuid);
957 return p;
958
959 manifest_syntax_error:
960 if(bUuid.nUsed){
961 blob_appendf(pErr, "manifest [%.40s] ", blob_str(&bUuid));
962 blob_reset(&bUuid);
 
 
 
963 }
964 if( zErr ){
965 blob_appendf(pErr, "line %d: %s", lineNo, zErr);
966 }else{
967 blob_appendf(pErr, "unknown error on line %d", lineNo);
@@ -1193,13 +1189,13 @@
1193 ** then the mlink entry is only created if there is already an mlink
1194 ** from primary parent for the same file.
1195 */
1196 static void add_one_mlink(
1197 int pmid, /* The parent manifest */
1198 const char *zFromUuid, /* UUID for content in parent */
1199 int mid, /* The record ID of the manifest */
1200 const char *zToUuid, /* UUID for content in child */
1201 const char *zFilename, /* Filename */
1202 const char *zPrior, /* Previous filename. NULL if unchanged */
1203 int isPublic, /* True if mid is not a private manifest */
1204 int isPrimary, /* pmid is the primary parent of mid */
1205 int mperm /* 1: exec, 2: symlink */
@@ -1545,22 +1541,22 @@
1545 }
1546 }
1547
1548 /*
1549 ** For a check-in with RID "rid" that has nParent parent check-ins given
1550 ** by the UUIDs in azParent[], create all appropriate plink and mlink table
1551 ** entries.
1552 **
1553 ** The primary parent is the first UUID on the azParent[] list.
1554 **
1555 ** Return the RID of the primary parent.
1556 */
1557 static int manifest_add_checkin_linkages(
1558 int rid, /* The RID of the check-in */
1559 Manifest *p, /* Manifest for this check-in */
1560 int nParent, /* Number of parents for this check-in */
1561 char **azParent /* UUIDs for each parent */
1562 ){
1563 int i;
1564 int parentid = 0;
1565 char zBaseId[30]; /* Baseline manifest RID for deltas. "NULL" otherwise */
1566 Stmt q;
@@ -1611,33 +1607,36 @@
1611 return parentid;
1612 }
1613
1614 /*
1615 ** There exists a "parent" tag against checkin rid that has value zValue.
1616 ** If value is well-formed (meaning that it is a list of UUIDs), then use
1617 ** zValue to reparent check-in rid.
1618 */
1619 void manifest_reparent_checkin(int rid, const char *zValue){
1620 int nParent;
1621 char *zCopy = 0;
1622 char **azParent = 0;
1623 Manifest *p = 0;
1624 int i;
1625 int n = (int)strlen(zValue);
1626 nParent = (n+1)/(UUID_SIZE+1);
1627 if( nParent*(UUID_SIZE+1) - 1 !=n ) return;
1628 if( nParent<1 ) return;
1629 zCopy = fossil_strdup(zValue);
1630 azParent = fossil_malloc( sizeof(azParent[0])*nParent );
1631 for(i=0; i<nParent; i++){
1632 azParent[i] = &zCopy[i*(UUID_SIZE+1)];
1633 if( i<nParent-1 && azParent[i][UUID_SIZE]!=' ' ) break;
1634 azParent[i][UUID_SIZE] = 0;
1635 if( !validate16(azParent[i],UUID_SIZE) ) break;
1636 }
1637 if( i==nParent
1638 && !db_exists("SELECT 1 FROM plink WHERE cid=%d AND pid=%d",
 
 
 
1639 rid, uuid_to_rid(azParent[0],0))
1640 ){
1641 p = manifest_get(rid, CFTYPE_MANIFEST, 0);
1642 }
1643 if( p!=0 ){
@@ -1647,10 +1646,11 @@
1647 rid, rid
1648 );
1649 manifest_add_checkin_linkages(rid,p,nParent,azParent);
1650 }
1651 manifest_destroy(p);
 
1652 fossil_free(azParent);
1653 fossil_free(zCopy);
1654 }
1655
1656 /*
@@ -2280,11 +2280,11 @@
2280 int branchMove = 0;
2281 blob_zero(&comment);
2282 if( p->zComment ){
2283 blob_appendf(&comment, " %s.", p->zComment);
2284 }
2285 /* Next loop expects tags to be sorted on UUID, so sort it. */
2286 qsort(p->aTag, p->nTag, sizeof(p->aTag[0]), tag_compare);
2287 for(i=0; i<p->nTag; i++){
2288 zTagUuid = p->aTag[i].zUuid;
2289 if( !zTagUuid ) continue;
2290 if( i==0 || fossil_strcmp(zTagUuid, p->aTag[i-1].zUuid)!=0 ){
2291
--- src/manifest.c
+++ src/manifest.c
@@ -54,11 +54,11 @@
54 /*
55 ** A single F-card within a manifest
56 */
57 struct ManifestFile {
58 char *zName; /* Name of a file */
59 char *zUuid; /* Artifact hash for the file */
60 char *zPerm; /* File permissions */
61 char *zPrior; /* Prior name if the name was changed */
62 };
63
64
@@ -77,35 +77,35 @@
77 char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */
78 char *zWiki; /* Text of the wiki page. W card. */
79 char *zWikiTitle; /* Name of the wiki page. L card. */
80 char *zMimetype; /* Mime type of wiki or comment text. N card. */
81 double rEventDate; /* Date of an event. E card. */
82 char *zEventId; /* Artifact hash for an event. E card. */
83 char *zTicketUuid; /* UUID for a ticket. K card. */
84 char *zAttachName; /* Filename of an attachment. A card. */
85 char *zAttachSrc; /* Artifact hash for document being attached. A card. */
86 char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */
87 int nFile; /* Number of F cards */
88 int nFileAlloc; /* Slots allocated in aFile[] */
89 int iFile; /* Index of current file in iterator */
90 ManifestFile *aFile; /* One entry for each F-card */
91 int nParent; /* Number of parents. */
92 int nParentAlloc; /* Slots allocated in azParent[] */
93 char **azParent; /* Hashes of parents. One for each P card argument */
94 int nCherrypick; /* Number of entries in aCherrypick[] */
95 struct {
96 char *zCPTarget; /* Hash for cherry-picked version w/ +|- prefix */
97 char *zCPBase; /* Hash for cherry-pick baseline. NULL for singletons */
98 } *aCherrypick;
99 int nCChild; /* Number of cluster children */
100 int nCChildAlloc; /* Number of closts allocated in azCChild[] */
101 char **azCChild; /* Hashes of referenced objects in a cluster. M cards */
102 int nTag; /* Number of T Cards */
103 int nTagAlloc; /* Slots allocated in aTag[] */
104 struct TagType {
105 char *zName; /* Name of the tag */
106 char *zUuid; /* Hash of artifact that the tag is applied to */
107 char *zValue; /* Value if the tag is really a property */
108 } *aTag; /* One for each T card */
109 int nField; /* Number of J cards */
110 int nFieldAlloc; /* Slots allocated in aField[] */
111 struct {
@@ -327,26 +327,27 @@
327 ** takes over the input blob and will free it when the
328 ** Manifest object is freed. Zeros are inserted into the blob
329 ** as string terminators so that blob should not be used again.
330 **
331 ** Return a pointer to an allocated Manifest object if the content
332 ** really is a structural artifact of some kind. The returned Manifest
333 ** object needs to be freed by a subsequent call to manifest_destroy().
334 ** Return NULL if there are syntax errors or if the input blob does
335 ** not describe a valid structural artifact.
336 **
337 ** This routine is strict about the format of a structural artifacts.
338 ** The format must match exactly or else it is rejected. This
339 ** rule minimizes the risk that a content artifact will be mistaken
340 ** for a structural artifact simply because they look the same.
341 **
342 ** The pContent is reset. If a pointer is returned, then pContent will
343 ** be reset when the Manifest object is cleared. If NULL is
344 ** returned then the Manifest object is cleared automatically
345 ** and pContent is reset before the return.
346 **
347 ** The entire input blob can be PGP clear-signed. The signature is ignored.
348 ** The artifact consists of zero or more cards, one card per line.
349 ** (Except: the content of the W card can extend of multiple lines.)
350 ** Each card is divided into tokens by a single space character.
351 ** The first token is a single upper-case letter which is the card type.
352 ** The card type determines the other parameters to the card.
353 ** Cards must occur in lexicographical order.
@@ -361,11 +362,10 @@
362 char *z;
363 int n;
364 char *zUuid;
365 int sz = 0;
366 int isRepeat, hasSelfRefTag = 0;
 
367 static Bag seen;
368 const char *zErr = 0;
369
370 if( rid==0 ){
371 isRepeat = 1;
@@ -374,11 +374,11 @@
374 }else{
375 isRepeat = 0;
376 bag_insert(&seen, rid);
377 }
378
379 /* Every structural artifact ends with a '\n' character. Exit early
380 ** if that is not the case for this artifact.
381 */
382 if( !isRepeat ) g.parseCnt[0]++;
383 z = blob_materialize(pContent);
384 n = blob_size(pContent);
@@ -406,15 +406,10 @@
406 blob_reset(pContent);
407 blob_appendf(pErr, "incorrect Z-card cksum");
408 return 0;
409 }
410
 
 
 
 
 
411 /* Allocate a Manifest object to hold the parsed control artifact.
412 */
413 p = fossil_malloc( sizeof(*p) );
414 memset(p, 0, sizeof(*p));
415 memcpy(&p->content, pContent, sizeof(p->content));
@@ -449,15 +444,15 @@
444 defossilize(zName);
445 if( !file_is_simple_pathname(zName, 0) ){
446 SYNTAX("invalid filename on A-card");
447 }
448 defossilize(zTarget);
449 if( !hname_validate(zTarget,nTarget)
450 && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){
451 SYNTAX("invalid target on A-card");
452 }
453 if( zSrc && !hname_validate(zSrc,nSrc) ){
454 SYNTAX("invalid source on A-card");
455 }
456 p->zAttachName = (char*)file_tail(zName);
457 p->zAttachSrc = zSrc;
458 p->zAttachTarget = zTarget;
@@ -465,18 +460,18 @@
460 }
461
462 /*
463 ** B <uuid>
464 **
465 ** A B-line gives the artifact hash for the baseline of a delta-manifest.
466 */
467 case 'B': {
468 if( p->zBaseline ) SYNTAX("more than one B-card");
469 p->zBaseline = next_token(&x, &sz);
470 if( p->zBaseline==0 ) SYNTAX("missing hash on B-card");
471 if( !hname_validate(p->zBaseline,sz) ){
472 SYNTAX("invalid hash on B-card");
473 }
474 break;
475 }
476
477
@@ -522,12 +517,12 @@
517 case 'E': {
518 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
519 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
520 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
521 p->zEventId = next_token(&x, &sz);
522 if( !hname_validate(p->zEventId, sz) ){
523 SYNTAX("malformed hash on E-card");
524 }
525 break;
526 }
527
528 /*
@@ -545,12 +540,13 @@
540 if( !file_is_simple_pathname(zName, 0) ){
541 SYNTAX("F-card filename is not a simple path");
542 }
543 zUuid = next_token(&x, &sz);
544 if( p->zBaseline==0 || zUuid!=0 ){
545 if( !hname_validate(zUuid,sz) ){
546 SYNTAX("F-card hash invalid");
547 }
548 }
549 zPerm = next_token(&x,0);
550 zPriorName = next_token(&x,0);
551 if( zPriorName ){
552 defossilize(zPriorName);
@@ -636,20 +632,21 @@
632 }
633 break;
634 }
635
636 /*
637 ** M <hash>
638 **
639 ** An M-line identifies another artifact by its hash. M-lines
640 ** occur in clusters only.
641 */
642 case 'M': {
643 zUuid = next_token(&x, &sz);
644 if( zUuid==0 ) SYNTAX("missing hash on M-card");
645 if( !hname_validate(zUuid,sz) ){
646 SYNTAX("Invalid hash on M-card");
647 }
648 if( p->nCChild>=p->nCChildAlloc ){
649 p->nCChildAlloc = p->nCChildAlloc*2 + 10;
650 p->azCChild = fossil_realloc(p->azCChild
651 , p->nCChildAlloc*sizeof(p->azCChild[0]) );
652 }
@@ -683,12 +680,13 @@
680 ** check-in historically has an empty P-card, so empty P-cards
681 ** must be accepted.
682 */
683 case 'P': {
684 while( (zUuid = next_token(&x, &sz))!=0 ){
685 if( !hname_validate(zUuid, sz) ){
686 SYNTAX("invalid hash on P-card");
687 }
688 if( p->nParent>=p->nParentAlloc ){
689 p->nParentAlloc = p->nParentAlloc*2 + 5;
690 p->azParent = fossil_realloc(p->azParent,
691 p->nParentAlloc*sizeof(char*));
692 }
@@ -703,29 +701,25 @@
701 **
702 ** Specify one or a range of check-ins that are cherrypicked into
703 ** this check-in ("+") or backed out of this check-in ("-").
704 */
705 case 'Q': {
706 if( (zUuid=next_token(&x, &sz))==0 ) SYNTAX("missing hash on Q-card");
 
707 if( zUuid[0]!='+' && zUuid[0]!='-' ){
708 SYNTAX("Q-card does not begin with '+' or '-'");
709 }
710 if( !hname_validate(&zUuid[1], sz-1) ){
711 SYNTAX("invalid hash on Q-card");
712 }
713 n = p->nCherrypick;
714 p->nCherrypick++;
715 p->aCherrypick = fossil_realloc(p->aCherrypick,
716 p->nCherrypick*sizeof(p->aCherrypick[0]));
717 p->aCherrypick[n].zCPTarget = zUuid;
718 p->aCherrypick[n].zCPBase = zUuid = next_token(&x, &sz);
719 if( zUuid && !hname_validate(zUuid,sz) ){
720 SYNTAX("invalid second hash on Q-card");
 
 
 
721 }
722 break;
723 }
724
725 /*
@@ -760,32 +754,32 @@
754 case 'T': {
755 char *zName, *zValue;
756 zName = next_token(&x, 0);
757 if( zName==0 ) SYNTAX("missing name on T-card");
758 zUuid = next_token(&x, &sz);
759 if( zUuid==0 ) SYNTAX("missing artifact hash on T-card");
760 zValue = next_token(&x, 0);
761 if( zValue ) defossilize(zValue);
762 if( hname_validate(zUuid, sz) ){
763 /* A valid artifact hash */
764 if( p->zEventId ) SYNTAX("non-self-referential T-card in event");
765 }else if( sz==1 && zUuid[0]=='*' ){
766 zUuid = 0;
767 hasSelfRefTag = 1;
768 if( p->zEventId && zName[0]!='+' ){
769 SYNTAX("propagating T-card in event");
770 }
771 }else{
772 SYNTAX("malformed artifact hash on T-card");
773 }
774 defossilize(zName);
775 if( zName[0]!='-' && zName[0]!='+' && zName[0]!='*' ){
776 SYNTAX("T-card name does not begin with '-', '+', or '*'");
777 }
778 if( validate16(&zName[1], strlen(&zName[1])) ){
779 /* Do not allow tags whose names look like a hash */
780 SYNTAX("T-card name looks like a hexadecimal hash");
781 }
782 if( p->nTag>=p->nTagAlloc ){
783 p->nTagAlloc = p->nTagAlloc*2 + 10;
784 p->aTag = fossil_realloc(p->aTag, p->nTagAlloc*sizeof(p->aTag[0]) );
785 }
@@ -951,17 +945,19 @@
945 if( !seenZ ) SYNTAX("missing Z-card on control");
946 p->type = CFTYPE_CONTROL;
947 }
948 md5sum_init();
949 if( !isRepeat ) g.parseCnt[p->type]++;
 
950 return p;
951
952 manifest_syntax_error:
953 {
954 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
955 if( zUuid ){
956 blob_appendf(pErr, "manifest [%s] ", zUuid);
957 fossil_free(zUuid);
958 }
959 }
960 if( zErr ){
961 blob_appendf(pErr, "line %d: %s", lineNo, zErr);
962 }else{
963 blob_appendf(pErr, "unknown error on line %d", lineNo);
@@ -1193,13 +1189,13 @@
1189 ** then the mlink entry is only created if there is already an mlink
1190 ** from primary parent for the same file.
1191 */
1192 static void add_one_mlink(
1193 int pmid, /* The parent manifest */
1194 const char *zFromUuid, /* Artifact hash for content in parent */
1195 int mid, /* The record ID of the manifest */
1196 const char *zToUuid, /* artifact hash for content in child */
1197 const char *zFilename, /* Filename */
1198 const char *zPrior, /* Previous filename. NULL if unchanged */
1199 int isPublic, /* True if mid is not a private manifest */
1200 int isPrimary, /* pmid is the primary parent of mid */
1201 int mperm /* 1: exec, 2: symlink */
@@ -1545,22 +1541,22 @@
1541 }
1542 }
1543
1544 /*
1545 ** For a check-in with RID "rid" that has nParent parent check-ins given
1546 ** by the hashes in azParent[], create all appropriate plink and mlink table
1547 ** entries.
1548 **
1549 ** The primary parent is the first hash on the azParent[] list.
1550 **
1551 ** Return the RID of the primary parent.
1552 */
1553 static int manifest_add_checkin_linkages(
1554 int rid, /* The RID of the check-in */
1555 Manifest *p, /* Manifest for this check-in */
1556 int nParent, /* Number of parents for this check-in */
1557 char **azParent /* hashes for each parent */
1558 ){
1559 int i;
1560 int parentid = 0;
1561 char zBaseId[30]; /* Baseline manifest RID for deltas. "NULL" otherwise */
1562 Stmt q;
@@ -1611,33 +1607,36 @@
1607 return parentid;
1608 }
1609
1610 /*
1611 ** There exists a "parent" tag against checkin rid that has value zValue.
1612 ** If value is well-formed (meaning that it is a list of hashes), then use
1613 ** zValue to reparent check-in rid.
1614 */
1615 void manifest_reparent_checkin(int rid, const char *zValue){
1616 int nParent = 0;
1617 char *zCopy = 0;
1618 char **azParent = 0;
1619 Manifest *p = 0;
1620 int i, j;
1621 int n = (int)strlen(zValue);
1622 int mxParent = (n+1)/(HNAME_MIN+1);
1623
1624 if( mxParent<1 ) return;
1625 zCopy = fossil_strdup(zValue);
1626 azParent = fossil_malloc( sizeof(azParent[0])*mxParent );
1627 for(nParent=0, i=0; zCopy[i]; i++){
1628 char *z = &zCopy[i];
1629 azParent[nParent++] = z;
1630 if( nParent>mxParent ) goto reparent_abort;
1631 for(j=HNAME_MIN; z[j]>' '; j++){}
1632 if( !hname_validate(z, j) ) goto reparent_abort;
1633 if( z[j]==0 ) break;
1634 z[j] = 0;
1635 i += j;
1636 }
1637 if( !db_exists("SELECT 1 FROM plink WHERE cid=%d AND pid=%d",
1638 rid, uuid_to_rid(azParent[0],0))
1639 ){
1640 p = manifest_get(rid, CFTYPE_MANIFEST, 0);
1641 }
1642 if( p!=0 ){
@@ -1647,10 +1646,11 @@
1646 rid, rid
1647 );
1648 manifest_add_checkin_linkages(rid,p,nParent,azParent);
1649 }
1650 manifest_destroy(p);
1651 reparent_abort:
1652 fossil_free(azParent);
1653 fossil_free(zCopy);
1654 }
1655
1656 /*
@@ -2280,11 +2280,11 @@
2280 int branchMove = 0;
2281 blob_zero(&comment);
2282 if( p->zComment ){
2283 blob_appendf(&comment, " %s.", p->zComment);
2284 }
2285 /* Next loop expects tags to be sorted on hash, so sort it. */
2286 qsort(p->aTag, p->nTag, sizeof(p->aTag[0]), tag_compare);
2287 for(i=0; i<p->nTag; i++){
2288 zTagUuid = p->aTag[i].zUuid;
2289 if( !zTagUuid ) continue;
2290 if( i==0 || fossil_strcmp(zTagUuid, p->aTag[i-1].zUuid)!=0 ){
2291
+15 -1
--- src/md5.c
+++ src/md5.c
@@ -22,10 +22,20 @@
2222
#include <string.h>
2323
#include <stdio.h>
2424
#include <sqlite3.h>
2525
#include "md5.h"
2626
27
+#ifdef FOSSIL_ENABLE_SSL
28
+
29
+# include <openssl/md5.h>
30
+# define MD5Context MD5_CTX
31
+# define MD5Init MD5_Init
32
+# define MD5Update MD5_Update
33
+# define MD5Final MD5_Final
34
+
35
+#else
36
+
2737
/*
2838
* If compiled on a machine that doesn't have a 32-bit integer,
2939
* you just set "uint32" to the appropriate datatype for an
3040
* unsigned 32-bit integer. For example:
3141
*
@@ -42,11 +52,14 @@
4252
uint32 bits[2];
4353
unsigned char in[64];
4454
};
4555
typedef struct Context MD5Context;
4656
47
-#if defined(__i386__) || defined(__x86_64__) || defined(_WIN32)
57
+#if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
58
+ defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
59
+ defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
60
+ defined(__arm__) || defined(_WIN32)
4861
# define byteReverse(A,B)
4962
#else
5063
/*
5164
* Convert an array of integers to little-endian.
5265
* Note: this code is a no-op on little-endian machines.
@@ -266,10 +279,11 @@
266279
MD5Transform(ctx->buf, (uint32 *)ctx->in);
267280
byteReverse((unsigned char *)ctx->buf, 4);
268281
memcpy(digest, ctx->buf, 16);
269282
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
270283
}
284
+#endif
271285
272286
/*
273287
** Convert a digest into base-16. digest should be declared as
274288
** "unsigned char digest[16]" in the calling function. The MD5
275289
** digest is stored in the first 16 bytes. zBuf should
276290
--- src/md5.c
+++ src/md5.c
@@ -22,10 +22,20 @@
22 #include <string.h>
23 #include <stdio.h>
24 #include <sqlite3.h>
25 #include "md5.h"
26
 
 
 
 
 
 
 
 
 
 
27 /*
28 * If compiled on a machine that doesn't have a 32-bit integer,
29 * you just set "uint32" to the appropriate datatype for an
30 * unsigned 32-bit integer. For example:
31 *
@@ -42,11 +52,14 @@
42 uint32 bits[2];
43 unsigned char in[64];
44 };
45 typedef struct Context MD5Context;
46
47 #if defined(__i386__) || defined(__x86_64__) || defined(_WIN32)
 
 
 
48 # define byteReverse(A,B)
49 #else
50 /*
51 * Convert an array of integers to little-endian.
52 * Note: this code is a no-op on little-endian machines.
@@ -266,10 +279,11 @@
266 MD5Transform(ctx->buf, (uint32 *)ctx->in);
267 byteReverse((unsigned char *)ctx->buf, 4);
268 memcpy(digest, ctx->buf, 16);
269 memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
270 }
 
271
272 /*
273 ** Convert a digest into base-16. digest should be declared as
274 ** "unsigned char digest[16]" in the calling function. The MD5
275 ** digest is stored in the first 16 bytes. zBuf should
276
--- src/md5.c
+++ src/md5.c
@@ -22,10 +22,20 @@
22 #include <string.h>
23 #include <stdio.h>
24 #include <sqlite3.h>
25 #include "md5.h"
26
27 #ifdef FOSSIL_ENABLE_SSL
28
29 # include <openssl/md5.h>
30 # define MD5Context MD5_CTX
31 # define MD5Init MD5_Init
32 # define MD5Update MD5_Update
33 # define MD5Final MD5_Final
34
35 #else
36
37 /*
38 * If compiled on a machine that doesn't have a 32-bit integer,
39 * you just set "uint32" to the appropriate datatype for an
40 * unsigned 32-bit integer. For example:
41 *
@@ -42,11 +52,14 @@
52 uint32 bits[2];
53 unsigned char in[64];
54 };
55 typedef struct Context MD5Context;
56
57 #if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
58 defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
59 defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
60 defined(__arm__) || defined(_WIN32)
61 # define byteReverse(A,B)
62 #else
63 /*
64 * Convert an array of integers to little-endian.
65 * Note: this code is a no-op on little-endian machines.
@@ -266,10 +279,11 @@
279 MD5Transform(ctx->buf, (uint32 *)ctx->in);
280 byteReverse((unsigned char *)ctx->buf, 4);
281 memcpy(digest, ctx->buf, 16);
282 memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
283 }
284 #endif
285
286 /*
287 ** Convert a digest into base-16. digest should be declared as
288 ** "unsigned char digest[16]" in the calling function. The MD5
289 ** digest is stored in the first 16 bytes. zBuf should
290
+6 -5
--- src/mkversion.c
+++ src/mkversion.c
@@ -12,11 +12,12 @@
1212
#include <stdlib.h>
1313
1414
int main(int argc, char *argv[]){
1515
FILE *m,*u,*v;
1616
char *z;
17
- int i, x, d;
17
+ int i, j, x, d;
18
+ int vn[3];
1819
char b[1000];
1920
char vx[1000];
2021
memset(b,0,sizeof(b));
2122
memset(vx,0,sizeof(vx));
2223
u = fopen(argv[1],"r");
@@ -45,25 +46,25 @@
4546
fclose(v);
4647
for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){}
4748
*z = 0;
4849
printf("#define RELEASE_VERSION \"%s\"\n", b);
4950
x=0;
50
- i=0;
51
+ i=j=0;
5152
z=b;
53
+ vn[0] = vn[1] = vn[2] = 0;
5254
while(1){
5355
if( z[0]>='0' && z[0]<='9' ){
5456
x = x*10 + z[0] - '0';
5557
}else{
56
- sprintf(&vx[i],"%02d",x);
57
- i += 2;
58
+ if( j<3 ) vn[j++] = x;
5859
x = 0;
5960
if( z[0]==0 ) break;
6061
}
6162
z++;
6263
}
6364
for(z=vx; z[0]=='0'; z++){}
64
- printf("#define RELEASE_VERSION_NUMBER %s\n", z);
65
+ printf("#define RELEASE_VERSION_NUMBER %d%02d%02d\n", vn[0], vn[1], vn[2]);
6566
memset(vx,0,sizeof(vx));
6667
strcpy(vx,b);
6768
d = 0;
6869
for(z=vx; z[0]; z++){
6970
if( z[0]=='-' ){
7071
--- src/mkversion.c
+++ src/mkversion.c
@@ -12,11 +12,12 @@
12 #include <stdlib.h>
13
14 int main(int argc, char *argv[]){
15 FILE *m,*u,*v;
16 char *z;
17 int i, x, d;
 
18 char b[1000];
19 char vx[1000];
20 memset(b,0,sizeof(b));
21 memset(vx,0,sizeof(vx));
22 u = fopen(argv[1],"r");
@@ -45,25 +46,25 @@
45 fclose(v);
46 for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){}
47 *z = 0;
48 printf("#define RELEASE_VERSION \"%s\"\n", b);
49 x=0;
50 i=0;
51 z=b;
 
52 while(1){
53 if( z[0]>='0' && z[0]<='9' ){
54 x = x*10 + z[0] - '0';
55 }else{
56 sprintf(&vx[i],"%02d",x);
57 i += 2;
58 x = 0;
59 if( z[0]==0 ) break;
60 }
61 z++;
62 }
63 for(z=vx; z[0]=='0'; z++){}
64 printf("#define RELEASE_VERSION_NUMBER %s\n", z);
65 memset(vx,0,sizeof(vx));
66 strcpy(vx,b);
67 d = 0;
68 for(z=vx; z[0]; z++){
69 if( z[0]=='-' ){
70
--- src/mkversion.c
+++ src/mkversion.c
@@ -12,11 +12,12 @@
12 #include <stdlib.h>
13
14 int main(int argc, char *argv[]){
15 FILE *m,*u,*v;
16 char *z;
17 int i, j, x, d;
18 int vn[3];
19 char b[1000];
20 char vx[1000];
21 memset(b,0,sizeof(b));
22 memset(vx,0,sizeof(vx));
23 u = fopen(argv[1],"r");
@@ -45,25 +46,25 @@
46 fclose(v);
47 for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){}
48 *z = 0;
49 printf("#define RELEASE_VERSION \"%s\"\n", b);
50 x=0;
51 i=j=0;
52 z=b;
53 vn[0] = vn[1] = vn[2] = 0;
54 while(1){
55 if( z[0]>='0' && z[0]<='9' ){
56 x = x*10 + z[0] - '0';
57 }else{
58 if( j<3 ) vn[j++] = x;
 
59 x = 0;
60 if( z[0]==0 ) break;
61 }
62 z++;
63 }
64 for(z=vx; z[0]=='0'; z++){}
65 printf("#define RELEASE_VERSION_NUMBER %d%02d%02d\n", vn[0], vn[1], vn[2]);
66 memset(vx,0,sizeof(vx));
67 strcpy(vx,b);
68 d = 0;
69 for(z=vx; z[0]; z++){
70 if( z[0]=='-' ){
71
+24 -28
--- src/name.c
+++ src/name.c
@@ -2,11 +2,11 @@
22
** Copyright (c) 2006 D. Richard Hipp
33
**
44
** This program is free software; you can redistribute it and/or
55
** modify it under the terms of the Simplified BSD License (also
66
** known as the "2-Clause License" or "FreeBSD License".)
7
-
7
+**
88
** This program is distributed in the hope that it will be useful,
99
** but without any warranty; without even the implied warranty of
1010
** merchantability or fitness for a particular purpose.
1111
**
1212
** Author contact information:
@@ -13,15 +13,11 @@
1313
** [email protected]
1414
** http://www.hwaci.com/drh/
1515
**
1616
*******************************************************************************
1717
**
18
-** This file contains code used to convert user-supplied object names into
19
-** canonical UUIDs.
20
-**
21
-** A user-supplied object name is any unique prefix of a valid UUID but
22
-** not necessarily in canonical form.
18
+** This file contains code used to resolved user-supplied object names.
2319
*/
2420
#include "config.h"
2521
#include "name.h"
2622
#include <assert.h>
2723
@@ -80,12 +76,12 @@
8076
}
8177
8278
/*
8379
** Convert a symbolic name into a RID. Acceptable forms:
8480
**
85
-** * SHA1 hash
86
-** * SHA1 hash prefix of at least 4 characters
81
+** * artifact hash
82
+** * 4-character or larger prefix of a artifact
8783
** * Symbolic Name
8884
** * "tag:" + symbolic name
8985
** * Date or date-time
9086
** * "date:" + Date or date-time
9187
** * symbolic-name ":" date-time
@@ -105,11 +101,11 @@
105101
** If zType is "br" then find the first check-in of the named branch
106102
** rather than the last.
107103
** zType is "ci" in most use cases since we are usually searching for
108104
** a check-in.
109105
**
110
-** Note that the input zTag for types "t" and "e" is the SHA1 hash of
106
+** Note that the input zTag for types "t" and "e" is the artifact hash of
111107
** the ticket-change or event-change artifact, not the randomly generated
112108
** hexadecimal identifier assigned to tickets and events. Those identifiers
113109
** live in a separate namespace.
114110
*/
115111
int symbolic_name_to_rid(const char *zTag, const char *zType){
@@ -232,14 +228,14 @@
232228
zTagBase, zDate, zType
233229
);
234230
return rid;
235231
}
236232
237
- /* SHA1 hash or prefix */
238
- if( nTag>=4 && nTag<=UUID_SIZE && validate16(zTag, nTag) ){
233
+ /* artifact hash or prefix */
234
+ if( nTag>=4 && nTag<=HNAME_MAX && validate16(zTag, nTag) ){
239235
Stmt q;
240
- char zUuid[UUID_SIZE+1];
236
+ char zUuid[HNAME_MAX+1];
241237
memcpy(zUuid, zTag, nTag+1);
242238
canonical16(zUuid, nTag);
243239
rid = 0;
244240
if( zType[0]=='*' ){
245241
db_prepare(&q, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUuid);
@@ -354,11 +350,11 @@
354350
*/
355351
int name_collisions(const char *zName){
356352
int c = 0; /* count of collisions for zName */
357353
int nLen; /* length of zName */
358354
nLen = strlen(zName);
359
- if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){
355
+ if( nLen>=4 && nLen<=HNAME_MAX && validate16(zName, nLen) ){
360356
c = db_int(0,
361357
"SELECT"
362358
" (SELECT count(*) FROM ticket"
363359
" WHERE tkt_uuid GLOB '%q*') +"
364360
" (SELECT count(*) FROM tag"
@@ -396,11 +392,11 @@
396392
397393
/*
398394
** Convert a name to a rid. If the name can be any of the various forms
399395
** accepted:
400396
**
401
-** * SHA1 hash or prefix thereof
397
+** * artifact hash or prefix thereof
402398
** * symbolic name
403399
** * date
404400
** * label:date
405401
** * prev, previous
406402
** * next
@@ -425,13 +421,13 @@
425421
return name_to_typed_rid(zName, "*");
426422
}
427423
428424
/*
429425
** WEBPAGE: ambiguous
430
-** URL: /ambiguous?name=UUID&src=WEBPAGE
426
+** URL: /ambiguous?name=NAME&src=WEBPAGE
431427
**
432
-** The UUID given by the name parameter is ambiguous. Display a page
428
+** The NAME given by the name parameter is ambiguous. Display a page
433429
** that shows all possible choices and let the user select between them.
434430
*/
435431
void ambiguous_page(void){
436432
Stmt q;
437433
const char *zName = P("name");
@@ -668,11 +664,11 @@
668664
/*
669665
** COMMAND: whatis*
670666
**
671667
** Usage: %fossil whatis NAME
672668
**
673
-** Resolve the symbol NAME into its canonical 40-character SHA1-hash
669
+** Resolve the symbol NAME into its canonical artifact hash
674670
** artifact name and provide a description of what role that artifact
675671
** plays.
676672
**
677673
** Options:
678674
**
@@ -744,11 +740,11 @@
744740
/*
745741
** COMMAND: test-ambiguous
746742
**
747743
** Usage: %fossil test-ambiguous [--minsize N]
748744
**
749
-** Show a list of ambiguous SHA1-hash abbreviations of N characters or
745
+** Show a list of ambiguous artifact hash abbreviations of N characters or
750746
** more where N defaults to 4. Change N to a different value using
751747
** the "--minsize N" command-line option.
752748
*/
753749
void test_ambiguous_cmd(void){
754750
Stmt q, ins;
@@ -794,11 +790,11 @@
794790
** Schema for the description table
795791
*/
796792
static const char zDescTab[] =
797793
@ CREATE TEMP TABLE IF NOT EXISTS description(
798794
@ rid INTEGER PRIMARY KEY, -- RID of the object
799
-@ uuid TEXT, -- SHA1 hash of the object
795
+@ uuid TEXT, -- hash of the object
800796
@ ctime DATETIME, -- Time of creation
801797
@ isPrivate BOOLEAN DEFAULT 0, -- True for unpublished artifacts
802798
@ type TEXT, -- file, checkin, wiki, ticket, etc.
803799
@ summary TEXT, -- Summary comment for the object
804800
@ detail TEXT -- File name, check-in comment, etc
@@ -1084,11 +1080,11 @@
10841080
" WHERE description.rid=blob.rid"
10851081
" ORDER BY length(content) DESC"
10861082
);
10871083
@ <table cellpadding="2" cellspacing="0" border="1" id="bigblobtab">
10881084
@ <thead><tr><th align="right">Size<th align="right">RID
1089
- @ <th align="right">Delta From<th>SHA1<th>Description<th>Date</tr></thead>
1085
+ @ <th align="right">Delta From<th>Hash<th>Description<th>Date</tr></thead>
10901086
@ <tbody>
10911087
while( db_step(&q)==SQLITE_ROW ){
10921088
int rid = db_column_int(&q,0);
10931089
const char *zUuid = db_column_text(&q, 1);
10941090
const char *zDesc = db_column_text(&q, 2);
@@ -1147,33 +1143,33 @@
11471143
11481144
/* Maximum number of collision examples to remember */
11491145
#define MAX_COLLIDE 25
11501146
11511147
/*
1152
-** Generate a report on the number of collisions in SHA1 hashes
1148
+** Generate a report on the number of collisions in artifact hashes
11531149
** generated by the SQL given in the argument.
11541150
*/
11551151
static void collision_report(const char *zSql){
11561152
int i, j, kk;
11571153
int nHash = 0;
11581154
Stmt q;
1159
- char zPrev[UUID_SIZE+1];
1155
+ char zPrev[HNAME_MAX+1];
11601156
struct {
11611157
int cnt;
11621158
char *azHit[MAX_COLLIDE];
1163
- char z[UUID_SIZE+1];
1164
- } aCollide[UUID_SIZE+1];
1159
+ char z[HNAME_MAX+1];
1160
+ } aCollide[HNAME_MAX+1];
11651161
memset(aCollide, 0, sizeof(aCollide));
11661162
memset(zPrev, 0, sizeof(zPrev));
11671163
db_prepare(&q,"%s",zSql/*safe-for-%s*/);
11681164
while( db_step(&q)==SQLITE_ROW ){
11691165
const char *zUuid = db_column_text(&q,0);
11701166
int n = db_column_bytes(&q,0);
11711167
int i;
11721168
nHash++;
11731169
for(i=0; zPrev[i] && zPrev[i]==zUuid[i]; i++){}
1174
- if( i>0 && i<=UUID_SIZE ){
1170
+ if( i>0 && i<=HNAME_MAX ){
11751171
if( i>=4 && aCollide[i].cnt<MAX_COLLIDE ){
11761172
aCollide[i].azHit[aCollide[i].cnt] = mprintf("%.*s", i, zPrev);
11771173
}
11781174
aCollide[i].cnt++;
11791175
if( aCollide[i].z[0]==0 ) memcpy(aCollide[i].z, zPrev, n+1);
@@ -1182,18 +1178,18 @@
11821178
}
11831179
db_finalize(&q);
11841180
@ <table border=1><thead>
11851181
@ <tr><th>Length<th>Instances<th>First Instance</tr>
11861182
@ </thead><tbody>
1187
- for(i=1; i<=UUID_SIZE; i++){
1183
+ for(i=1; i<=HNAME_MAX; i++){
11881184
if( aCollide[i].cnt==0 ) continue;
11891185
@ <tr><td>%d(i)<td>%d(aCollide[i].cnt)<td>%h(aCollide[i].z)</tr>
11901186
}
11911187
@ </tbody></table>
11921188
@ <p>Total number of hashes: %d(nHash)</p>
11931189
kk = 0;
1194
- for(i=UUID_SIZE; i>=4; i--){
1190
+ for(i=HNAME_MAX; i>=4; i--){
11951191
if( aCollide[i].cnt==0 ) continue;
11961192
if( aCollide[i].cnt>200 ) break;
11971193
kk += aCollide[i].cnt;
11981194
if( aCollide[i].cnt<25 ){
11991195
@ <p>Collisions of length %d(i):
@@ -1219,11 +1215,11 @@
12191215
** Show the number of hash collisions for hash prefixes of various lengths.
12201216
*/
12211217
void hash_collisions_webpage(void){
12221218
login_check_credentials();
12231219
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1224
- style_header("SHA1 Prefix Collisions");
1220
+ style_header("Hash Prefix Collisions");
12251221
style_submenu_element("Activity Reports", "reports");
12261222
style_submenu_element("Stats", "stat");
12271223
@ <h1>Hash Prefix Collisions on Check-ins</h1>
12281224
collision_report("SELECT (SELECT uuid FROM blob WHERE rid=objid)"
12291225
" FROM event WHERE event.type='ci'"
12301226
--- src/name.c
+++ src/name.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -13,15 +13,11 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains code used to convert user-supplied object names into
19 ** canonical UUIDs.
20 **
21 ** A user-supplied object name is any unique prefix of a valid UUID but
22 ** not necessarily in canonical form.
23 */
24 #include "config.h"
25 #include "name.h"
26 #include <assert.h>
27
@@ -80,12 +76,12 @@
80 }
81
82 /*
83 ** Convert a symbolic name into a RID. Acceptable forms:
84 **
85 ** * SHA1 hash
86 ** * SHA1 hash prefix of at least 4 characters
87 ** * Symbolic Name
88 ** * "tag:" + symbolic name
89 ** * Date or date-time
90 ** * "date:" + Date or date-time
91 ** * symbolic-name ":" date-time
@@ -105,11 +101,11 @@
105 ** If zType is "br" then find the first check-in of the named branch
106 ** rather than the last.
107 ** zType is "ci" in most use cases since we are usually searching for
108 ** a check-in.
109 **
110 ** Note that the input zTag for types "t" and "e" is the SHA1 hash of
111 ** the ticket-change or event-change artifact, not the randomly generated
112 ** hexadecimal identifier assigned to tickets and events. Those identifiers
113 ** live in a separate namespace.
114 */
115 int symbolic_name_to_rid(const char *zTag, const char *zType){
@@ -232,14 +228,14 @@
232 zTagBase, zDate, zType
233 );
234 return rid;
235 }
236
237 /* SHA1 hash or prefix */
238 if( nTag>=4 && nTag<=UUID_SIZE && validate16(zTag, nTag) ){
239 Stmt q;
240 char zUuid[UUID_SIZE+1];
241 memcpy(zUuid, zTag, nTag+1);
242 canonical16(zUuid, nTag);
243 rid = 0;
244 if( zType[0]=='*' ){
245 db_prepare(&q, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUuid);
@@ -354,11 +350,11 @@
354 */
355 int name_collisions(const char *zName){
356 int c = 0; /* count of collisions for zName */
357 int nLen; /* length of zName */
358 nLen = strlen(zName);
359 if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){
360 c = db_int(0,
361 "SELECT"
362 " (SELECT count(*) FROM ticket"
363 " WHERE tkt_uuid GLOB '%q*') +"
364 " (SELECT count(*) FROM tag"
@@ -396,11 +392,11 @@
396
397 /*
398 ** Convert a name to a rid. If the name can be any of the various forms
399 ** accepted:
400 **
401 ** * SHA1 hash or prefix thereof
402 ** * symbolic name
403 ** * date
404 ** * label:date
405 ** * prev, previous
406 ** * next
@@ -425,13 +421,13 @@
425 return name_to_typed_rid(zName, "*");
426 }
427
428 /*
429 ** WEBPAGE: ambiguous
430 ** URL: /ambiguous?name=UUID&src=WEBPAGE
431 **
432 ** The UUID given by the name parameter is ambiguous. Display a page
433 ** that shows all possible choices and let the user select between them.
434 */
435 void ambiguous_page(void){
436 Stmt q;
437 const char *zName = P("name");
@@ -668,11 +664,11 @@
668 /*
669 ** COMMAND: whatis*
670 **
671 ** Usage: %fossil whatis NAME
672 **
673 ** Resolve the symbol NAME into its canonical 40-character SHA1-hash
674 ** artifact name and provide a description of what role that artifact
675 ** plays.
676 **
677 ** Options:
678 **
@@ -744,11 +740,11 @@
744 /*
745 ** COMMAND: test-ambiguous
746 **
747 ** Usage: %fossil test-ambiguous [--minsize N]
748 **
749 ** Show a list of ambiguous SHA1-hash abbreviations of N characters or
750 ** more where N defaults to 4. Change N to a different value using
751 ** the "--minsize N" command-line option.
752 */
753 void test_ambiguous_cmd(void){
754 Stmt q, ins;
@@ -794,11 +790,11 @@
794 ** Schema for the description table
795 */
796 static const char zDescTab[] =
797 @ CREATE TEMP TABLE IF NOT EXISTS description(
798 @ rid INTEGER PRIMARY KEY, -- RID of the object
799 @ uuid TEXT, -- SHA1 hash of the object
800 @ ctime DATETIME, -- Time of creation
801 @ isPrivate BOOLEAN DEFAULT 0, -- True for unpublished artifacts
802 @ type TEXT, -- file, checkin, wiki, ticket, etc.
803 @ summary TEXT, -- Summary comment for the object
804 @ detail TEXT -- File name, check-in comment, etc
@@ -1084,11 +1080,11 @@
1084 " WHERE description.rid=blob.rid"
1085 " ORDER BY length(content) DESC"
1086 );
1087 @ <table cellpadding="2" cellspacing="0" border="1" id="bigblobtab">
1088 @ <thead><tr><th align="right">Size<th align="right">RID
1089 @ <th align="right">Delta From<th>SHA1<th>Description<th>Date</tr></thead>
1090 @ <tbody>
1091 while( db_step(&q)==SQLITE_ROW ){
1092 int rid = db_column_int(&q,0);
1093 const char *zUuid = db_column_text(&q, 1);
1094 const char *zDesc = db_column_text(&q, 2);
@@ -1147,33 +1143,33 @@
1147
1148 /* Maximum number of collision examples to remember */
1149 #define MAX_COLLIDE 25
1150
1151 /*
1152 ** Generate a report on the number of collisions in SHA1 hashes
1153 ** generated by the SQL given in the argument.
1154 */
1155 static void collision_report(const char *zSql){
1156 int i, j, kk;
1157 int nHash = 0;
1158 Stmt q;
1159 char zPrev[UUID_SIZE+1];
1160 struct {
1161 int cnt;
1162 char *azHit[MAX_COLLIDE];
1163 char z[UUID_SIZE+1];
1164 } aCollide[UUID_SIZE+1];
1165 memset(aCollide, 0, sizeof(aCollide));
1166 memset(zPrev, 0, sizeof(zPrev));
1167 db_prepare(&q,"%s",zSql/*safe-for-%s*/);
1168 while( db_step(&q)==SQLITE_ROW ){
1169 const char *zUuid = db_column_text(&q,0);
1170 int n = db_column_bytes(&q,0);
1171 int i;
1172 nHash++;
1173 for(i=0; zPrev[i] && zPrev[i]==zUuid[i]; i++){}
1174 if( i>0 && i<=UUID_SIZE ){
1175 if( i>=4 && aCollide[i].cnt<MAX_COLLIDE ){
1176 aCollide[i].azHit[aCollide[i].cnt] = mprintf("%.*s", i, zPrev);
1177 }
1178 aCollide[i].cnt++;
1179 if( aCollide[i].z[0]==0 ) memcpy(aCollide[i].z, zPrev, n+1);
@@ -1182,18 +1178,18 @@
1182 }
1183 db_finalize(&q);
1184 @ <table border=1><thead>
1185 @ <tr><th>Length<th>Instances<th>First Instance</tr>
1186 @ </thead><tbody>
1187 for(i=1; i<=UUID_SIZE; i++){
1188 if( aCollide[i].cnt==0 ) continue;
1189 @ <tr><td>%d(i)<td>%d(aCollide[i].cnt)<td>%h(aCollide[i].z)</tr>
1190 }
1191 @ </tbody></table>
1192 @ <p>Total number of hashes: %d(nHash)</p>
1193 kk = 0;
1194 for(i=UUID_SIZE; i>=4; i--){
1195 if( aCollide[i].cnt==0 ) continue;
1196 if( aCollide[i].cnt>200 ) break;
1197 kk += aCollide[i].cnt;
1198 if( aCollide[i].cnt<25 ){
1199 @ <p>Collisions of length %d(i):
@@ -1219,11 +1215,11 @@
1219 ** Show the number of hash collisions for hash prefixes of various lengths.
1220 */
1221 void hash_collisions_webpage(void){
1222 login_check_credentials();
1223 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1224 style_header("SHA1 Prefix Collisions");
1225 style_submenu_element("Activity Reports", "reports");
1226 style_submenu_element("Stats", "stat");
1227 @ <h1>Hash Prefix Collisions on Check-ins</h1>
1228 collision_report("SELECT (SELECT uuid FROM blob WHERE rid=objid)"
1229 " FROM event WHERE event.type='ci'"
1230
--- src/name.c
+++ src/name.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7 **
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -13,15 +13,11 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains code used to resolved user-supplied object names.
 
 
 
 
19 */
20 #include "config.h"
21 #include "name.h"
22 #include <assert.h>
23
@@ -80,12 +76,12 @@
76 }
77
78 /*
79 ** Convert a symbolic name into a RID. Acceptable forms:
80 **
81 ** * artifact hash
82 ** * 4-character or larger prefix of a artifact
83 ** * Symbolic Name
84 ** * "tag:" + symbolic name
85 ** * Date or date-time
86 ** * "date:" + Date or date-time
87 ** * symbolic-name ":" date-time
@@ -105,11 +101,11 @@
101 ** If zType is "br" then find the first check-in of the named branch
102 ** rather than the last.
103 ** zType is "ci" in most use cases since we are usually searching for
104 ** a check-in.
105 **
106 ** Note that the input zTag for types "t" and "e" is the artifact hash of
107 ** the ticket-change or event-change artifact, not the randomly generated
108 ** hexadecimal identifier assigned to tickets and events. Those identifiers
109 ** live in a separate namespace.
110 */
111 int symbolic_name_to_rid(const char *zTag, const char *zType){
@@ -232,14 +228,14 @@
228 zTagBase, zDate, zType
229 );
230 return rid;
231 }
232
233 /* artifact hash or prefix */
234 if( nTag>=4 && nTag<=HNAME_MAX && validate16(zTag, nTag) ){
235 Stmt q;
236 char zUuid[HNAME_MAX+1];
237 memcpy(zUuid, zTag, nTag+1);
238 canonical16(zUuid, nTag);
239 rid = 0;
240 if( zType[0]=='*' ){
241 db_prepare(&q, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUuid);
@@ -354,11 +350,11 @@
350 */
351 int name_collisions(const char *zName){
352 int c = 0; /* count of collisions for zName */
353 int nLen; /* length of zName */
354 nLen = strlen(zName);
355 if( nLen>=4 && nLen<=HNAME_MAX && validate16(zName, nLen) ){
356 c = db_int(0,
357 "SELECT"
358 " (SELECT count(*) FROM ticket"
359 " WHERE tkt_uuid GLOB '%q*') +"
360 " (SELECT count(*) FROM tag"
@@ -396,11 +392,11 @@
392
393 /*
394 ** Convert a name to a rid. If the name can be any of the various forms
395 ** accepted:
396 **
397 ** * artifact hash or prefix thereof
398 ** * symbolic name
399 ** * date
400 ** * label:date
401 ** * prev, previous
402 ** * next
@@ -425,13 +421,13 @@
421 return name_to_typed_rid(zName, "*");
422 }
423
424 /*
425 ** WEBPAGE: ambiguous
426 ** URL: /ambiguous?name=NAME&src=WEBPAGE
427 **
428 ** The NAME given by the name parameter is ambiguous. Display a page
429 ** that shows all possible choices and let the user select between them.
430 */
431 void ambiguous_page(void){
432 Stmt q;
433 const char *zName = P("name");
@@ -668,11 +664,11 @@
664 /*
665 ** COMMAND: whatis*
666 **
667 ** Usage: %fossil whatis NAME
668 **
669 ** Resolve the symbol NAME into its canonical artifact hash
670 ** artifact name and provide a description of what role that artifact
671 ** plays.
672 **
673 ** Options:
674 **
@@ -744,11 +740,11 @@
740 /*
741 ** COMMAND: test-ambiguous
742 **
743 ** Usage: %fossil test-ambiguous [--minsize N]
744 **
745 ** Show a list of ambiguous artifact hash abbreviations of N characters or
746 ** more where N defaults to 4. Change N to a different value using
747 ** the "--minsize N" command-line option.
748 */
749 void test_ambiguous_cmd(void){
750 Stmt q, ins;
@@ -794,11 +790,11 @@
790 ** Schema for the description table
791 */
792 static const char zDescTab[] =
793 @ CREATE TEMP TABLE IF NOT EXISTS description(
794 @ rid INTEGER PRIMARY KEY, -- RID of the object
795 @ uuid TEXT, -- hash of the object
796 @ ctime DATETIME, -- Time of creation
797 @ isPrivate BOOLEAN DEFAULT 0, -- True for unpublished artifacts
798 @ type TEXT, -- file, checkin, wiki, ticket, etc.
799 @ summary TEXT, -- Summary comment for the object
800 @ detail TEXT -- File name, check-in comment, etc
@@ -1084,11 +1080,11 @@
1080 " WHERE description.rid=blob.rid"
1081 " ORDER BY length(content) DESC"
1082 );
1083 @ <table cellpadding="2" cellspacing="0" border="1" id="bigblobtab">
1084 @ <thead><tr><th align="right">Size<th align="right">RID
1085 @ <th align="right">Delta From<th>Hash<th>Description<th>Date</tr></thead>
1086 @ <tbody>
1087 while( db_step(&q)==SQLITE_ROW ){
1088 int rid = db_column_int(&q,0);
1089 const char *zUuid = db_column_text(&q, 1);
1090 const char *zDesc = db_column_text(&q, 2);
@@ -1147,33 +1143,33 @@
1143
1144 /* Maximum number of collision examples to remember */
1145 #define MAX_COLLIDE 25
1146
1147 /*
1148 ** Generate a report on the number of collisions in artifact hashes
1149 ** generated by the SQL given in the argument.
1150 */
1151 static void collision_report(const char *zSql){
1152 int i, j, kk;
1153 int nHash = 0;
1154 Stmt q;
1155 char zPrev[HNAME_MAX+1];
1156 struct {
1157 int cnt;
1158 char *azHit[MAX_COLLIDE];
1159 char z[HNAME_MAX+1];
1160 } aCollide[HNAME_MAX+1];
1161 memset(aCollide, 0, sizeof(aCollide));
1162 memset(zPrev, 0, sizeof(zPrev));
1163 db_prepare(&q,"%s",zSql/*safe-for-%s*/);
1164 while( db_step(&q)==SQLITE_ROW ){
1165 const char *zUuid = db_column_text(&q,0);
1166 int n = db_column_bytes(&q,0);
1167 int i;
1168 nHash++;
1169 for(i=0; zPrev[i] && zPrev[i]==zUuid[i]; i++){}
1170 if( i>0 && i<=HNAME_MAX ){
1171 if( i>=4 && aCollide[i].cnt<MAX_COLLIDE ){
1172 aCollide[i].azHit[aCollide[i].cnt] = mprintf("%.*s", i, zPrev);
1173 }
1174 aCollide[i].cnt++;
1175 if( aCollide[i].z[0]==0 ) memcpy(aCollide[i].z, zPrev, n+1);
@@ -1182,18 +1178,18 @@
1178 }
1179 db_finalize(&q);
1180 @ <table border=1><thead>
1181 @ <tr><th>Length<th>Instances<th>First Instance</tr>
1182 @ </thead><tbody>
1183 for(i=1; i<=HNAME_MAX; i++){
1184 if( aCollide[i].cnt==0 ) continue;
1185 @ <tr><td>%d(i)<td>%d(aCollide[i].cnt)<td>%h(aCollide[i].z)</tr>
1186 }
1187 @ </tbody></table>
1188 @ <p>Total number of hashes: %d(nHash)</p>
1189 kk = 0;
1190 for(i=HNAME_MAX; i>=4; i--){
1191 if( aCollide[i].cnt==0 ) continue;
1192 if( aCollide[i].cnt>200 ) break;
1193 kk += aCollide[i].cnt;
1194 if( aCollide[i].cnt<25 ){
1195 @ <p>Collisions of length %d(i):
@@ -1219,11 +1215,11 @@
1215 ** Show the number of hash collisions for hash prefixes of various lengths.
1216 */
1217 void hash_collisions_webpage(void){
1218 login_check_credentials();
1219 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1220 style_header("Hash Prefix Collisions");
1221 style_submenu_element("Activity Reports", "reports");
1222 style_submenu_element("Stats", "stat");
1223 @ <h1>Hash Prefix Collisions on Check-ins</h1>
1224 collision_report("SELECT (SELECT uuid FROM blob WHERE rid=objid)"
1225 " FROM event WHERE event.type='ci'"
1226
+2 -2
--- src/printf.c
+++ src/printf.c
@@ -24,11 +24,11 @@
2424
# include <io.h>
2525
# include <fcntl.h>
2626
#endif
2727
#include <time.h>
2828
29
-/* Two custom conversions are used to show a prefix of SHA1 hashes:
29
+/* Two custom conversions are used to show a prefix of artifact hashes:
3030
**
3131
** %!S Prefix of a length appropriate for URLs
3232
** %S Prefix of a length appropriate for human display
3333
**
3434
** The following macros help determine those lengths. FOSSIL_HASH_DIGITS
@@ -44,11 +44,11 @@
4444
#ifndef FOSSIL_HASH_DIGITS_URL
4545
# define FOSSIL_HASH_DIGITS_URL 16 /* For %!S (embedded in URLs) */
4646
#endif
4747
4848
/*
49
-** Return the number of SHA1 hash digits to display. The number is for
49
+** Return the number of artifact hash digits to display. The number is for
5050
** human output if the bForUrl is false and is destined for a URL if
5151
** bForUrl is false.
5252
*/
5353
static int hashDigits(int bForUrl){
5454
static int nDigitHuman = 0;
5555
--- src/printf.c
+++ src/printf.c
@@ -24,11 +24,11 @@
24 # include <io.h>
25 # include <fcntl.h>
26 #endif
27 #include <time.h>
28
29 /* Two custom conversions are used to show a prefix of SHA1 hashes:
30 **
31 ** %!S Prefix of a length appropriate for URLs
32 ** %S Prefix of a length appropriate for human display
33 **
34 ** The following macros help determine those lengths. FOSSIL_HASH_DIGITS
@@ -44,11 +44,11 @@
44 #ifndef FOSSIL_HASH_DIGITS_URL
45 # define FOSSIL_HASH_DIGITS_URL 16 /* For %!S (embedded in URLs) */
46 #endif
47
48 /*
49 ** Return the number of SHA1 hash digits to display. The number is for
50 ** human output if the bForUrl is false and is destined for a URL if
51 ** bForUrl is false.
52 */
53 static int hashDigits(int bForUrl){
54 static int nDigitHuman = 0;
55
--- src/printf.c
+++ src/printf.c
@@ -24,11 +24,11 @@
24 # include <io.h>
25 # include <fcntl.h>
26 #endif
27 #include <time.h>
28
29 /* Two custom conversions are used to show a prefix of artifact hashes:
30 **
31 ** %!S Prefix of a length appropriate for URLs
32 ** %S Prefix of a length appropriate for human display
33 **
34 ** The following macros help determine those lengths. FOSSIL_HASH_DIGITS
@@ -44,11 +44,11 @@
44 #ifndef FOSSIL_HASH_DIGITS_URL
45 # define FOSSIL_HASH_DIGITS_URL 16 /* For %!S (embedded in URLs) */
46 #endif
47
48 /*
49 ** Return the number of artifact hash digits to display. The number is for
50 ** human output if the bForUrl is false and is destined for a URL if
51 ** bForUrl is false.
52 */
53 static int hashDigits(int bForUrl){
54 static int nDigitHuman = 0;
55
+7 -13
--- src/purge.c
+++ src/purge.c
@@ -43,11 +43,11 @@
4343
@ );
4444
@ CREATE TABLE IF NOT EXISTS "%w".purgeitem(
4545
@ piid INTEGER PRIMARY KEY, -- ID for the purge item
4646
@ peid INTEGER REFERENCES purgeevent ON DELETE CASCADE, -- Purge event
4747
@ orid INTEGER, -- Original RID before purged
48
-@ uuid TEXT NOT NULL, -- SHA1 hash of the purged artifact
48
+@ uuid TEXT NOT NULL, -- hash of the purged artifact
4949
@ srcid INTEGER, -- Basis purgeitem for delta compression
5050
@ isPrivate BOOLEAN, -- True if artifact was originally private
5151
@ sz INT NOT NULL, -- Uncompressed size of the purged artifact
5252
@ desc TEXT, -- Brief description of this artifact
5353
@ data BLOB -- Compressed artifact content
@@ -347,11 +347,11 @@
347347
int piid, /* ID of the item to extract */
348348
Blob *pOut /* Write the content into this blob */
349349
){
350350
Stmt q;
351351
int srcid;
352
- Blob h1, h2, x;
352
+ Blob h1, x;
353353
static Bag busy;
354354
355355
db_prepare(&q, "SELECT uuid, srcid, data FROM purgeitem"
356356
" WHERE piid=%d", piid);
357357
if( db_step(&q)!=SQLITE_ROW ){
@@ -376,17 +376,14 @@
376376
blob_reset(&baseline);
377377
}
378378
bag_remove(&busy, piid);
379379
blob_zero(&h1);
380380
db_column_blob(&q, 0, &h1);
381
- sha1sum_blob(pOut, &h2);
382
- if( blob_compare(&h1, &h2)!=0 ){
383
- fossil_fatal("SHA1 hash mismatch - wanted %s, got %s",
384
- blob_str(&h1), blob_str(&h2));
381
+ if( hname_verify_hash(pOut, blob_buffer(&h1), blob_size(&h1))==0 ){
382
+ fossil_fatal("incorrect artifact hash on %b", &h1);
385383
}
386384
blob_reset(&h1);
387
- blob_reset(&h2);
388385
db_finalize(&q);
389386
return 0;
390387
}
391388
392389
/*
@@ -411,11 +408,11 @@
411408
" WHERE ix.srcid=%d"
412409
" AND ix.piid=purgeitem.piid;",
413410
iSrc
414411
);
415412
while( db_step(&q)==SQLITE_ROW ){
416
- Blob h1, h2, c1, c2;
413
+ Blob h1, c1, c2;
417414
int isPriv, rid;
418415
blob_zero(&h1);
419416
db_column_blob(&q, 0, &h1);
420417
blob_zero(&c1);
421418
db_column_blob(&q, 1, &c1);
@@ -425,16 +422,13 @@
425422
blob_delta_apply(pBasis, &c1, &c2);
426423
blob_reset(&c1);
427424
}else{
428425
c2 = c1;
429426
}
430
- sha1sum_blob(&c2, &h2);
431
- if( blob_compare(&h1, &h2)!=0 ){
432
- fossil_fatal("SHA1 hash mismatch - wanted %s, got %s",
433
- blob_str(&h1), blob_str(&h2));
427
+ if( hname_verify_hash(&c2, blob_buffer(&h1), blob_size(&h1))==0 ){
428
+ fossil_fatal("incorrect hash on %b", &h1);
434429
}
435
- blob_reset(&h2);
436430
isPriv = db_column_int(&q, 2);
437431
rid = content_put_ex(&c2, blob_str(&h1), 0, 0, isPriv);
438432
if( rid==0 ){
439433
fossil_fatal("%s", g.zErrMsg);
440434
}else{
441435
--- src/purge.c
+++ src/purge.c
@@ -43,11 +43,11 @@
43 @ );
44 @ CREATE TABLE IF NOT EXISTS "%w".purgeitem(
45 @ piid INTEGER PRIMARY KEY, -- ID for the purge item
46 @ peid INTEGER REFERENCES purgeevent ON DELETE CASCADE, -- Purge event
47 @ orid INTEGER, -- Original RID before purged
48 @ uuid TEXT NOT NULL, -- SHA1 hash of the purged artifact
49 @ srcid INTEGER, -- Basis purgeitem for delta compression
50 @ isPrivate BOOLEAN, -- True if artifact was originally private
51 @ sz INT NOT NULL, -- Uncompressed size of the purged artifact
52 @ desc TEXT, -- Brief description of this artifact
53 @ data BLOB -- Compressed artifact content
@@ -347,11 +347,11 @@
347 int piid, /* ID of the item to extract */
348 Blob *pOut /* Write the content into this blob */
349 ){
350 Stmt q;
351 int srcid;
352 Blob h1, h2, x;
353 static Bag busy;
354
355 db_prepare(&q, "SELECT uuid, srcid, data FROM purgeitem"
356 " WHERE piid=%d", piid);
357 if( db_step(&q)!=SQLITE_ROW ){
@@ -376,17 +376,14 @@
376 blob_reset(&baseline);
377 }
378 bag_remove(&busy, piid);
379 blob_zero(&h1);
380 db_column_blob(&q, 0, &h1);
381 sha1sum_blob(pOut, &h2);
382 if( blob_compare(&h1, &h2)!=0 ){
383 fossil_fatal("SHA1 hash mismatch - wanted %s, got %s",
384 blob_str(&h1), blob_str(&h2));
385 }
386 blob_reset(&h1);
387 blob_reset(&h2);
388 db_finalize(&q);
389 return 0;
390 }
391
392 /*
@@ -411,11 +408,11 @@
411 " WHERE ix.srcid=%d"
412 " AND ix.piid=purgeitem.piid;",
413 iSrc
414 );
415 while( db_step(&q)==SQLITE_ROW ){
416 Blob h1, h2, c1, c2;
417 int isPriv, rid;
418 blob_zero(&h1);
419 db_column_blob(&q, 0, &h1);
420 blob_zero(&c1);
421 db_column_blob(&q, 1, &c1);
@@ -425,16 +422,13 @@
425 blob_delta_apply(pBasis, &c1, &c2);
426 blob_reset(&c1);
427 }else{
428 c2 = c1;
429 }
430 sha1sum_blob(&c2, &h2);
431 if( blob_compare(&h1, &h2)!=0 ){
432 fossil_fatal("SHA1 hash mismatch - wanted %s, got %s",
433 blob_str(&h1), blob_str(&h2));
434 }
435 blob_reset(&h2);
436 isPriv = db_column_int(&q, 2);
437 rid = content_put_ex(&c2, blob_str(&h1), 0, 0, isPriv);
438 if( rid==0 ){
439 fossil_fatal("%s", g.zErrMsg);
440 }else{
441
--- src/purge.c
+++ src/purge.c
@@ -43,11 +43,11 @@
43 @ );
44 @ CREATE TABLE IF NOT EXISTS "%w".purgeitem(
45 @ piid INTEGER PRIMARY KEY, -- ID for the purge item
46 @ peid INTEGER REFERENCES purgeevent ON DELETE CASCADE, -- Purge event
47 @ orid INTEGER, -- Original RID before purged
48 @ uuid TEXT NOT NULL, -- hash of the purged artifact
49 @ srcid INTEGER, -- Basis purgeitem for delta compression
50 @ isPrivate BOOLEAN, -- True if artifact was originally private
51 @ sz INT NOT NULL, -- Uncompressed size of the purged artifact
52 @ desc TEXT, -- Brief description of this artifact
53 @ data BLOB -- Compressed artifact content
@@ -347,11 +347,11 @@
347 int piid, /* ID of the item to extract */
348 Blob *pOut /* Write the content into this blob */
349 ){
350 Stmt q;
351 int srcid;
352 Blob h1, x;
353 static Bag busy;
354
355 db_prepare(&q, "SELECT uuid, srcid, data FROM purgeitem"
356 " WHERE piid=%d", piid);
357 if( db_step(&q)!=SQLITE_ROW ){
@@ -376,17 +376,14 @@
376 blob_reset(&baseline);
377 }
378 bag_remove(&busy, piid);
379 blob_zero(&h1);
380 db_column_blob(&q, 0, &h1);
381 if( hname_verify_hash(pOut, blob_buffer(&h1), blob_size(&h1))==0 ){
382 fossil_fatal("incorrect artifact hash on %b", &h1);
 
 
383 }
384 blob_reset(&h1);
 
385 db_finalize(&q);
386 return 0;
387 }
388
389 /*
@@ -411,11 +408,11 @@
408 " WHERE ix.srcid=%d"
409 " AND ix.piid=purgeitem.piid;",
410 iSrc
411 );
412 while( db_step(&q)==SQLITE_ROW ){
413 Blob h1, c1, c2;
414 int isPriv, rid;
415 blob_zero(&h1);
416 db_column_blob(&q, 0, &h1);
417 blob_zero(&c1);
418 db_column_blob(&q, 1, &c1);
@@ -425,16 +422,13 @@
422 blob_delta_apply(pBasis, &c1, &c2);
423 blob_reset(&c1);
424 }else{
425 c2 = c1;
426 }
427 if( hname_verify_hash(&c2, blob_buffer(&h1), blob_size(&h1))==0 ){
428 fossil_fatal("incorrect hash on %b", &h1);
 
 
429 }
 
430 isPriv = db_column_int(&q, 2);
431 rid = content_put_ex(&c2, blob_str(&h1), 0, 0, isPriv);
432 if( rid==0 ){
433 fossil_fatal("%s", g.zErrMsg);
434 }else{
435
+106 -94
--- src/rebuild.c
+++ src/rebuild.c
@@ -21,76 +21,41 @@
2121
#include "rebuild.h"
2222
#include <assert.h>
2323
#include <errno.h>
2424
2525
/*
26
-** Make changes to the stable part of the schema (the part that is not
27
-** simply deleted and reconstructed on a rebuild) to bring the schema
28
-** up to the latest.
26
+** Update the schema as necessary
2927
*/
30
-static const char zSchemaUpdates1[] =
31
-@ -- Index on the delta table
32
-@ --
33
-@ CREATE INDEX IF NOT EXISTS delta_i1 ON delta(srcid);
34
-@
35
-@ -- Artifacts that should not be processed are identified in the
36
-@ -- "shun" table. Artifacts that are control-file forgeries or
37
-@ -- spam or artifacts whose contents violate administrative policy
38
-@ -- can be shunned in order to prevent them from contaminating
39
-@ -- the repository.
40
-@ --
41
-@ -- Shunned artifacts do not exist in the blob table. Hence they
42
-@ -- have not artifact ID (rid) and we thus must store their full
43
-@ -- UUID.
44
-@ --
45
-@ CREATE TABLE IF NOT EXISTS shun(
46
-@ uuid UNIQUE, -- UUID of artifact to be shunned. Canonical form
47
-@ mtime INTEGER, -- When added. Seconds since 1970
48
-@ scom TEXT -- Optional text explaining why the shun occurred
49
-@ );
50
-@
51
-@ -- Artifacts that should not be pushed are stored in the "private"
52
-@ -- table.
53
-@ --
54
-@ CREATE TABLE IF NOT EXISTS private(rid INTEGER PRIMARY KEY);
55
-@
56
-@ -- Some ticket content (such as the originators email address or contact
57
-@ -- information) needs to be obscured to protect privacy. This is achieved
58
-@ -- by storing an SHA1 hash of the content. For display, the hash is
59
-@ -- mapped back into the original text using this table.
60
-@ --
61
-@ -- This table contains sensitive information and should not be shared
62
-@ -- with unauthorized users.
63
-@ --
64
-@ CREATE TABLE IF NOT EXISTS concealed(
65
-@ hash TEXT PRIMARY KEY, -- The SHA1 hash of content
66
-@ mtime INTEGER, -- Time created. Seconds since 1970
67
-@ content TEXT -- Content intended to be concealed
68
-@ );
69
-;
70
-static const char zSchemaUpdates2[] =
71
-@ -- An entry in this table describes a database query that generates a
72
-@ -- table of tickets.
73
-@ --
74
-@ CREATE TABLE IF NOT EXISTS reportfmt(
75
-@ rn INTEGER PRIMARY KEY, -- Report number
76
-@ owner TEXT, -- Owner of this report format (not used)
77
-@ title TEXT UNIQUE, -- Title of this report
78
-@ mtime INTEGER, -- Time last modified. Seconds since 1970
79
-@ cols TEXT, -- A color-key specification
80
-@ sqlcode TEXT -- An SQL SELECT statement for this report
81
-@ );
82
-;
83
-
8428
static void rebuild_update_schema(void){
85
- int rc;
86
- db_multi_exec("%s", zSchemaUpdates1 /*safe-for-%s*/);
87
- db_multi_exec("%s", zSchemaUpdates2 /*safe-for-%s*/);
29
+ /* Verify that the PLINK table has a new column added by the
30
+ ** 2014-11-28 schema change. Create it if necessary. This code
31
+ ** can be removed in the future, once all users have upgraded to the
32
+ ** 2014-11-28 or later schema.
33
+ */
34
+ if( !db_table_has_column("repository","plink","baseid") ){
35
+ db_multi_exec(
36
+ "ALTER TABLE repository.plink ADD COLUMN baseid;"
37
+ );
38
+ }
39
+
40
+ /* Verify that the MLINK table has the newer columns added by the
41
+ ** 2015-01-24 schema change. Create them if necessary. This code
42
+ ** can be removed in the future, once all users have upgraded to the
43
+ ** 2015-01-24 or later schema.
44
+ */
45
+ if( !db_table_has_column("repository","mlink","isaux") ){
46
+ db_begin_transaction();
47
+ db_multi_exec(
48
+ "ALTER TABLE repository.mlink ADD COLUMN pmid INTEGER DEFAULT 0;"
49
+ "ALTER TABLE repository.mlink ADD COLUMN isaux BOOLEAN DEFAULT 0;"
50
+ );
51
+ db_end_transaction(0);
52
+ }
8853
89
- rc = db_exists("SELECT 1 FROM sqlite_master"
90
- " WHERE name='user' AND sql GLOB '* mtime *'");
91
- if( rc==0 ){
54
+ /* Add the user.mtime column if it is missing. (2011-04-27)
55
+ */
56
+ if( !db_table_has_column("repository", "user", "mtime") ){
9257
db_multi_exec(
9358
"CREATE TEMP TABLE temp_user AS SELECT * FROM user;"
9459
"DROP TABLE user;"
9560
"CREATE TABLE user(\n"
9661
" uid INTEGER PRIMARY KEY,\n"
@@ -109,54 +74,99 @@
10974
" ipaddr, cexpire, info, now(), photo FROM temp_user;"
11075
"DROP TABLE temp_user;"
11176
);
11277
}
11378
114
- rc = db_exists("SELECT 1 FROM sqlite_master"
115
- " WHERE name='config' AND sql GLOB '* mtime *'");
116
- if( rc==0 ){
79
+ /* Add the config.mtime column if it is missing. (2011-04-27)
80
+ */
81
+ if( !db_table_has_column("repository", "config", "mtime") ){
11782
db_multi_exec(
11883
"ALTER TABLE config ADD COLUMN mtime INTEGER;"
11984
"UPDATE config SET mtime=now();"
12085
);
12186
}
12287
123
- rc = db_exists("SELECT 1 FROM sqlite_master"
124
- " WHERE name='shun' AND sql GLOB '* mtime *'");
125
- if( rc==0 ){
88
+ /* Add the shun.mtime and shun.scom columns if they are missing.
89
+ ** (2011-04-27)
90
+ */
91
+ if( !db_table_has_column("repository", "shun", "mtime") ){
12692
db_multi_exec(
12793
"ALTER TABLE shun ADD COLUMN mtime INTEGER;"
12894
"ALTER TABLE shun ADD COLUMN scom TEXT;"
12995
"UPDATE shun SET mtime=now();"
13096
);
13197
}
13298
133
- rc = db_exists("SELECT 1 FROM sqlite_master"
134
- " WHERE name='reportfmt' AND sql GLOB '* mtime *'");
135
- if( rc==0 ){
99
+ /* Add the reportfmt.mtime column if it is missing. (2011-04-27)
100
+ */
101
+ if( !db_table_has_column("repository", "reportfmt", "mtime") ){
102
+ static const char zCreateReportFmtTable[] =
103
+ @ -- An entry in this table describes a database query that generates a
104
+ @ -- table of tickets.
105
+ @ --
106
+ @ CREATE TABLE IF NOT EXISTS reportfmt(
107
+ @ rn INTEGER PRIMARY KEY, -- Report number
108
+ @ owner TEXT, -- Owner of this report format (not used)
109
+ @ title TEXT UNIQUE, -- Title of this report
110
+ @ mtime INTEGER, -- Time last modified. Seconds since 1970
111
+ @ cols TEXT, -- A color-key specification
112
+ @ sqlcode TEXT -- An SQL SELECT statement for this report
113
+ @ );
114
+ ;
136115
db_multi_exec(
137116
"CREATE TEMP TABLE old_fmt AS SELECT * FROM reportfmt;"
138117
"DROP TABLE reportfmt;"
139118
);
140
- db_multi_exec("%s", zSchemaUpdates2/*safe-for-%s*/);
119
+ db_multi_exec("%s", zCreateReportFmtTable/*safe-for-%s*/);
141120
db_multi_exec(
142121
"INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
143122
" SELECT rn, owner, title, cols, sqlcode, now() FROM old_fmt;"
144123
"INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
145124
" SELECT rn, owner, title || ' (' || rn || ')', cols, sqlcode, now()"
146125
" FROM old_fmt;"
147126
);
148127
}
149128
150
- rc = db_exists("SELECT 1 FROM sqlite_master"
151
- " WHERE name='concealed' AND sql GLOB '* mtime *'");
152
- if( rc==0 ){
129
+ /* Add the concealed.mtime column if it is missing. (2011-04-27)
130
+ */
131
+ if( !db_table_has_column("repository", "concealed", "mtime") ){
153132
db_multi_exec(
154133
"ALTER TABLE concealed ADD COLUMN mtime INTEGER;"
155134
"UPDATE concealed SET mtime=now();"
156135
);
157136
}
137
+
138
+ /* Do the fossil-2.0 updates to the schema. (2017-02-28)
139
+ */
140
+ rebuild_schema_update_2_0();
141
+}
142
+
143
+/*
144
+** Update the repository schema for Fossil version 2.0. (2017-02-28)
145
+** (1) Change the CHECK constraint on BLOB.UUID so that the length
146
+** is greater than or equal to 40, not exactly equal to 40.
147
+*/
148
+void rebuild_schema_update_2_0(void){
149
+ char *z = db_text(0, "SELECT sql FROM repository.sqlite_master WHERE name='blob'");
150
+ if( z ){
151
+ /* Search for: length(uuid)==40
152
+ ** 0123456789 12345 */
153
+ int i;
154
+ for(i=10; z[i]; i++){
155
+ if( z[i]=='=' && strncmp(&z[i-6],"(uuid)==40",10)==0 ){
156
+ z[i] = '>';
157
+ db_multi_exec(
158
+ "PRAGMA writable_schema=ON;"
159
+ "UPDATE repository.sqlite_master SET sql=%Q WHERE name LIKE 'blob';"
160
+ "PRAGMA writable_schema=OFF;",
161
+ z
162
+ );
163
+ break;
164
+ }
165
+ }
166
+ fossil_free(z);
167
+ }
158168
}
159169
160170
/*
161171
** Variables used to store state information about an on-going "rebuild"
162172
** or "deconstruct".
@@ -330,37 +340,39 @@
330340
** extracted in a random order. This feature is used to test the
331341
** ability of fossil to accept records in any order and still
332342
** construct a sane repository.
333343
*/
334344
int rebuild_db(int randomize, int doOut, int doClustering){
335
- Stmt s;
345
+ Stmt s, q;
336346
int errCnt = 0;
337
- char *zTable;
338347
int incrSize;
348
+ Blob sql;
339349
340350
bag_init(&bagDone);
341351
ttyOutput = doOut;
342352
processCnt = 0;
343353
if (ttyOutput && !g.fQuiet) {
344354
percent_complete(0);
345355
}
346356
rebuild_update_schema();
347
- for(;;){
348
- zTable = db_text(0,
349
- "SELECT name FROM sqlite_master /*scan*/"
350
- " WHERE type='table'"
351
- " AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user',"
352
- "'config','shun','private','reportfmt',"
353
- "'concealed','accesslog','modreq',"
354
- "'purgeevent','purgeitem','unversioned')"
355
- " AND name NOT GLOB 'sqlite_*'"
356
- " AND name NOT GLOB 'fx_*'"
357
- );
358
- if( zTable==0 ) break;
359
- db_multi_exec("DROP TABLE %Q", zTable);
360
- free(zTable);
361
- }
357
+ blob_init(&sql, 0, 0);
358
+ db_prepare(&q,
359
+ "SELECT name FROM sqlite_master /*scan*/"
360
+ " WHERE type='table'"
361
+ " AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user','alias',"
362
+ "'config','shun','private','reportfmt',"
363
+ "'concealed','accesslog','modreq',"
364
+ "'purgeevent','purgeitem','unversioned')"
365
+ " AND name NOT GLOB 'sqlite_*'"
366
+ " AND name NOT GLOB 'fx_*'"
367
+ );
368
+ while( db_step(&q)==SQLITE_ROW ){
369
+ blob_appendf(&sql, "DROP TABLE \"%w\";\n", db_column_text(&q,0));
370
+ }
371
+ db_finalize(&q);
372
+ db_multi_exec("%s", blob_str(&sql)/*safe-for-%s*/);
373
+ blob_reset(&sql);
362374
db_multi_exec("%s", zRepositorySchema2/*safe-for-%s*/);
363375
ticket_create_table(0);
364376
shun_artifacts();
365377
366378
db_multi_exec(
@@ -994,11 +1006,11 @@
9941006
**
9951007
**
9961008
** This command exports all artifacts of a given repository and
9971009
** writes all artifacts to the file system. The DESTINATION directory
9981010
** will be populated with subdirectories AA and files AA/BBBBBBBBB.., where
999
-** AABBBBBBBBB.. is the 40 character artifact ID, AA the first 2 characters.
1011
+** AABBBBBBBBB.. is the 40+ character artifact ID, AA the first 2 characters.
10001012
** If -L|--prefixlength is given, the length (default 2) of the directory
10011013
** prefix can be set to 0,1,..,9 characters.
10021014
**
10031015
** Options:
10041016
** -R|--repository REPOSITORY deconstruct given REPOSITORY
10051017
--- src/rebuild.c
+++ src/rebuild.c
@@ -21,76 +21,41 @@
21 #include "rebuild.h"
22 #include <assert.h>
23 #include <errno.h>
24
25 /*
26 ** Make changes to the stable part of the schema (the part that is not
27 ** simply deleted and reconstructed on a rebuild) to bring the schema
28 ** up to the latest.
29 */
30 static const char zSchemaUpdates1[] =
31 @ -- Index on the delta table
32 @ --
33 @ CREATE INDEX IF NOT EXISTS delta_i1 ON delta(srcid);
34 @
35 @ -- Artifacts that should not be processed are identified in the
36 @ -- "shun" table. Artifacts that are control-file forgeries or
37 @ -- spam or artifacts whose contents violate administrative policy
38 @ -- can be shunned in order to prevent them from contaminating
39 @ -- the repository.
40 @ --
41 @ -- Shunned artifacts do not exist in the blob table. Hence they
42 @ -- have not artifact ID (rid) and we thus must store their full
43 @ -- UUID.
44 @ --
45 @ CREATE TABLE IF NOT EXISTS shun(
46 @ uuid UNIQUE, -- UUID of artifact to be shunned. Canonical form
47 @ mtime INTEGER, -- When added. Seconds since 1970
48 @ scom TEXT -- Optional text explaining why the shun occurred
49 @ );
50 @
51 @ -- Artifacts that should not be pushed are stored in the "private"
52 @ -- table.
53 @ --
54 @ CREATE TABLE IF NOT EXISTS private(rid INTEGER PRIMARY KEY);
55 @
56 @ -- Some ticket content (such as the originators email address or contact
57 @ -- information) needs to be obscured to protect privacy. This is achieved
58 @ -- by storing an SHA1 hash of the content. For display, the hash is
59 @ -- mapped back into the original text using this table.
60 @ --
61 @ -- This table contains sensitive information and should not be shared
62 @ -- with unauthorized users.
63 @ --
64 @ CREATE TABLE IF NOT EXISTS concealed(
65 @ hash TEXT PRIMARY KEY, -- The SHA1 hash of content
66 @ mtime INTEGER, -- Time created. Seconds since 1970
67 @ content TEXT -- Content intended to be concealed
68 @ );
69 ;
70 static const char zSchemaUpdates2[] =
71 @ -- An entry in this table describes a database query that generates a
72 @ -- table of tickets.
73 @ --
74 @ CREATE TABLE IF NOT EXISTS reportfmt(
75 @ rn INTEGER PRIMARY KEY, -- Report number
76 @ owner TEXT, -- Owner of this report format (not used)
77 @ title TEXT UNIQUE, -- Title of this report
78 @ mtime INTEGER, -- Time last modified. Seconds since 1970
79 @ cols TEXT, -- A color-key specification
80 @ sqlcode TEXT -- An SQL SELECT statement for this report
81 @ );
82 ;
83
84 static void rebuild_update_schema(void){
85 int rc;
86 db_multi_exec("%s", zSchemaUpdates1 /*safe-for-%s*/);
87 db_multi_exec("%s", zSchemaUpdates2 /*safe-for-%s*/);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
89 rc = db_exists("SELECT 1 FROM sqlite_master"
90 " WHERE name='user' AND sql GLOB '* mtime *'");
91 if( rc==0 ){
92 db_multi_exec(
93 "CREATE TEMP TABLE temp_user AS SELECT * FROM user;"
94 "DROP TABLE user;"
95 "CREATE TABLE user(\n"
96 " uid INTEGER PRIMARY KEY,\n"
@@ -109,54 +74,99 @@
109 " ipaddr, cexpire, info, now(), photo FROM temp_user;"
110 "DROP TABLE temp_user;"
111 );
112 }
113
114 rc = db_exists("SELECT 1 FROM sqlite_master"
115 " WHERE name='config' AND sql GLOB '* mtime *'");
116 if( rc==0 ){
117 db_multi_exec(
118 "ALTER TABLE config ADD COLUMN mtime INTEGER;"
119 "UPDATE config SET mtime=now();"
120 );
121 }
122
123 rc = db_exists("SELECT 1 FROM sqlite_master"
124 " WHERE name='shun' AND sql GLOB '* mtime *'");
125 if( rc==0 ){
 
126 db_multi_exec(
127 "ALTER TABLE shun ADD COLUMN mtime INTEGER;"
128 "ALTER TABLE shun ADD COLUMN scom TEXT;"
129 "UPDATE shun SET mtime=now();"
130 );
131 }
132
133 rc = db_exists("SELECT 1 FROM sqlite_master"
134 " WHERE name='reportfmt' AND sql GLOB '* mtime *'");
135 if( rc==0 ){
 
 
 
 
 
 
 
 
 
 
 
 
 
136 db_multi_exec(
137 "CREATE TEMP TABLE old_fmt AS SELECT * FROM reportfmt;"
138 "DROP TABLE reportfmt;"
139 );
140 db_multi_exec("%s", zSchemaUpdates2/*safe-for-%s*/);
141 db_multi_exec(
142 "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
143 " SELECT rn, owner, title, cols, sqlcode, now() FROM old_fmt;"
144 "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
145 " SELECT rn, owner, title || ' (' || rn || ')', cols, sqlcode, now()"
146 " FROM old_fmt;"
147 );
148 }
149
150 rc = db_exists("SELECT 1 FROM sqlite_master"
151 " WHERE name='concealed' AND sql GLOB '* mtime *'");
152 if( rc==0 ){
153 db_multi_exec(
154 "ALTER TABLE concealed ADD COLUMN mtime INTEGER;"
155 "UPDATE concealed SET mtime=now();"
156 );
157 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158 }
159
160 /*
161 ** Variables used to store state information about an on-going "rebuild"
162 ** or "deconstruct".
@@ -330,37 +340,39 @@
330 ** extracted in a random order. This feature is used to test the
331 ** ability of fossil to accept records in any order and still
332 ** construct a sane repository.
333 */
334 int rebuild_db(int randomize, int doOut, int doClustering){
335 Stmt s;
336 int errCnt = 0;
337 char *zTable;
338 int incrSize;
 
339
340 bag_init(&bagDone);
341 ttyOutput = doOut;
342 processCnt = 0;
343 if (ttyOutput && !g.fQuiet) {
344 percent_complete(0);
345 }
346 rebuild_update_schema();
347 for(;;){
348 zTable = db_text(0,
349 "SELECT name FROM sqlite_master /*scan*/"
350 " WHERE type='table'"
351 " AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user',"
352 "'config','shun','private','reportfmt',"
353 "'concealed','accesslog','modreq',"
354 "'purgeevent','purgeitem','unversioned')"
355 " AND name NOT GLOB 'sqlite_*'"
356 " AND name NOT GLOB 'fx_*'"
357 );
358 if( zTable==0 ) break;
359 db_multi_exec("DROP TABLE %Q", zTable);
360 free(zTable);
361 }
 
 
362 db_multi_exec("%s", zRepositorySchema2/*safe-for-%s*/);
363 ticket_create_table(0);
364 shun_artifacts();
365
366 db_multi_exec(
@@ -994,11 +1006,11 @@
994 **
995 **
996 ** This command exports all artifacts of a given repository and
997 ** writes all artifacts to the file system. The DESTINATION directory
998 ** will be populated with subdirectories AA and files AA/BBBBBBBBB.., where
999 ** AABBBBBBBBB.. is the 40 character artifact ID, AA the first 2 characters.
1000 ** If -L|--prefixlength is given, the length (default 2) of the directory
1001 ** prefix can be set to 0,1,..,9 characters.
1002 **
1003 ** Options:
1004 ** -R|--repository REPOSITORY deconstruct given REPOSITORY
1005
--- src/rebuild.c
+++ src/rebuild.c
@@ -21,76 +21,41 @@
21 #include "rebuild.h"
22 #include <assert.h>
23 #include <errno.h>
24
25 /*
26 ** Update the schema as necessary
 
 
27 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28 static void rebuild_update_schema(void){
29 /* Verify that the PLINK table has a new column added by the
30 ** 2014-11-28 schema change. Create it if necessary. This code
31 ** can be removed in the future, once all users have upgraded to the
32 ** 2014-11-28 or later schema.
33 */
34 if( !db_table_has_column("repository","plink","baseid") ){
35 db_multi_exec(
36 "ALTER TABLE repository.plink ADD COLUMN baseid;"
37 );
38 }
39
40 /* Verify that the MLINK table has the newer columns added by the
41 ** 2015-01-24 schema change. Create them if necessary. This code
42 ** can be removed in the future, once all users have upgraded to the
43 ** 2015-01-24 or later schema.
44 */
45 if( !db_table_has_column("repository","mlink","isaux") ){
46 db_begin_transaction();
47 db_multi_exec(
48 "ALTER TABLE repository.mlink ADD COLUMN pmid INTEGER DEFAULT 0;"
49 "ALTER TABLE repository.mlink ADD COLUMN isaux BOOLEAN DEFAULT 0;"
50 );
51 db_end_transaction(0);
52 }
53
54 /* Add the user.mtime column if it is missing. (2011-04-27)
55 */
56 if( !db_table_has_column("repository", "user", "mtime") ){
57 db_multi_exec(
58 "CREATE TEMP TABLE temp_user AS SELECT * FROM user;"
59 "DROP TABLE user;"
60 "CREATE TABLE user(\n"
61 " uid INTEGER PRIMARY KEY,\n"
@@ -109,54 +74,99 @@
74 " ipaddr, cexpire, info, now(), photo FROM temp_user;"
75 "DROP TABLE temp_user;"
76 );
77 }
78
79 /* Add the config.mtime column if it is missing. (2011-04-27)
80 */
81 if( !db_table_has_column("repository", "config", "mtime") ){
82 db_multi_exec(
83 "ALTER TABLE config ADD COLUMN mtime INTEGER;"
84 "UPDATE config SET mtime=now();"
85 );
86 }
87
88 /* Add the shun.mtime and shun.scom columns if they are missing.
89 ** (2011-04-27)
90 */
91 if( !db_table_has_column("repository", "shun", "mtime") ){
92 db_multi_exec(
93 "ALTER TABLE shun ADD COLUMN mtime INTEGER;"
94 "ALTER TABLE shun ADD COLUMN scom TEXT;"
95 "UPDATE shun SET mtime=now();"
96 );
97 }
98
99 /* Add the reportfmt.mtime column if it is missing. (2011-04-27)
100 */
101 if( !db_table_has_column("repository", "reportfmt", "mtime") ){
102 static const char zCreateReportFmtTable[] =
103 @ -- An entry in this table describes a database query that generates a
104 @ -- table of tickets.
105 @ --
106 @ CREATE TABLE IF NOT EXISTS reportfmt(
107 @ rn INTEGER PRIMARY KEY, -- Report number
108 @ owner TEXT, -- Owner of this report format (not used)
109 @ title TEXT UNIQUE, -- Title of this report
110 @ mtime INTEGER, -- Time last modified. Seconds since 1970
111 @ cols TEXT, -- A color-key specification
112 @ sqlcode TEXT -- An SQL SELECT statement for this report
113 @ );
114 ;
115 db_multi_exec(
116 "CREATE TEMP TABLE old_fmt AS SELECT * FROM reportfmt;"
117 "DROP TABLE reportfmt;"
118 );
119 db_multi_exec("%s", zCreateReportFmtTable/*safe-for-%s*/);
120 db_multi_exec(
121 "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
122 " SELECT rn, owner, title, cols, sqlcode, now() FROM old_fmt;"
123 "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
124 " SELECT rn, owner, title || ' (' || rn || ')', cols, sqlcode, now()"
125 " FROM old_fmt;"
126 );
127 }
128
129 /* Add the concealed.mtime column if it is missing. (2011-04-27)
130 */
131 if( !db_table_has_column("repository", "concealed", "mtime") ){
132 db_multi_exec(
133 "ALTER TABLE concealed ADD COLUMN mtime INTEGER;"
134 "UPDATE concealed SET mtime=now();"
135 );
136 }
137
138 /* Do the fossil-2.0 updates to the schema. (2017-02-28)
139 */
140 rebuild_schema_update_2_0();
141 }
142
143 /*
144 ** Update the repository schema for Fossil version 2.0. (2017-02-28)
145 ** (1) Change the CHECK constraint on BLOB.UUID so that the length
146 ** is greater than or equal to 40, not exactly equal to 40.
147 */
148 void rebuild_schema_update_2_0(void){
149 char *z = db_text(0, "SELECT sql FROM repository.sqlite_master WHERE name='blob'");
150 if( z ){
151 /* Search for: length(uuid)==40
152 ** 0123456789 12345 */
153 int i;
154 for(i=10; z[i]; i++){
155 if( z[i]=='=' && strncmp(&z[i-6],"(uuid)==40",10)==0 ){
156 z[i] = '>';
157 db_multi_exec(
158 "PRAGMA writable_schema=ON;"
159 "UPDATE repository.sqlite_master SET sql=%Q WHERE name LIKE 'blob';"
160 "PRAGMA writable_schema=OFF;",
161 z
162 );
163 break;
164 }
165 }
166 fossil_free(z);
167 }
168 }
169
170 /*
171 ** Variables used to store state information about an on-going "rebuild"
172 ** or "deconstruct".
@@ -330,37 +340,39 @@
340 ** extracted in a random order. This feature is used to test the
341 ** ability of fossil to accept records in any order and still
342 ** construct a sane repository.
343 */
344 int rebuild_db(int randomize, int doOut, int doClustering){
345 Stmt s, q;
346 int errCnt = 0;
 
347 int incrSize;
348 Blob sql;
349
350 bag_init(&bagDone);
351 ttyOutput = doOut;
352 processCnt = 0;
353 if (ttyOutput && !g.fQuiet) {
354 percent_complete(0);
355 }
356 rebuild_update_schema();
357 blob_init(&sql, 0, 0);
358 db_prepare(&q,
359 "SELECT name FROM sqlite_master /*scan*/"
360 " WHERE type='table'"
361 " AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user','alias',"
362 "'config','shun','private','reportfmt',"
363 "'concealed','accesslog','modreq',"
364 "'purgeevent','purgeitem','unversioned')"
365 " AND name NOT GLOB 'sqlite_*'"
366 " AND name NOT GLOB 'fx_*'"
367 );
368 while( db_step(&q)==SQLITE_ROW ){
369 blob_appendf(&sql, "DROP TABLE \"%w\";\n", db_column_text(&q,0));
370 }
371 db_finalize(&q);
372 db_multi_exec("%s", blob_str(&sql)/*safe-for-%s*/);
373 blob_reset(&sql);
374 db_multi_exec("%s", zRepositorySchema2/*safe-for-%s*/);
375 ticket_create_table(0);
376 shun_artifacts();
377
378 db_multi_exec(
@@ -994,11 +1006,11 @@
1006 **
1007 **
1008 ** This command exports all artifacts of a given repository and
1009 ** writes all artifacts to the file system. The DESTINATION directory
1010 ** will be populated with subdirectories AA and files AA/BBBBBBBBB.., where
1011 ** AABBBBBBBBB.. is the 40+ character artifact ID, AA the first 2 characters.
1012 ** If -L|--prefixlength is given, the length (default 2) of the directory
1013 ** prefix can be set to 0,1,..,9 characters.
1014 **
1015 ** Options:
1016 ** -R|--repository REPOSITORY deconstruct given REPOSITORY
1017
+2 -2
--- src/schema.c
+++ src/schema.c
@@ -79,13 +79,13 @@
7979
@ --
8080
@ CREATE TABLE blob(
8181
@ rid INTEGER PRIMARY KEY, -- Record ID
8282
@ rcvid INTEGER, -- Origin of this record
8383
@ size INTEGER, -- Size of content. -1 for a phantom.
84
-@ uuid TEXT UNIQUE NOT NULL, -- SHA1 hash of the content
84
+@ uuid TEXT UNIQUE NOT NULL, -- hash of the content
8585
@ content BLOB, -- Compressed content of this record
86
-@ CHECK( length(uuid)==40 AND rid>0 )
86
+@ CHECK( length(uuid)>=40 AND rid>0 )
8787
@ );
8888
@ CREATE TABLE delta(
8989
@ rid INTEGER PRIMARY KEY, -- BLOB that is delta-compressed
9090
@ srcid INTEGER NOT NULL REFERENCES blob -- Baseline for delta-compression
9191
@ );
9292
--- src/schema.c
+++ src/schema.c
@@ -79,13 +79,13 @@
79 @ --
80 @ CREATE TABLE blob(
81 @ rid INTEGER PRIMARY KEY, -- Record ID
82 @ rcvid INTEGER, -- Origin of this record
83 @ size INTEGER, -- Size of content. -1 for a phantom.
84 @ uuid TEXT UNIQUE NOT NULL, -- SHA1 hash of the content
85 @ content BLOB, -- Compressed content of this record
86 @ CHECK( length(uuid)==40 AND rid>0 )
87 @ );
88 @ CREATE TABLE delta(
89 @ rid INTEGER PRIMARY KEY, -- BLOB that is delta-compressed
90 @ srcid INTEGER NOT NULL REFERENCES blob -- Baseline for delta-compression
91 @ );
92
--- src/schema.c
+++ src/schema.c
@@ -79,13 +79,13 @@
79 @ --
80 @ CREATE TABLE blob(
81 @ rid INTEGER PRIMARY KEY, -- Record ID
82 @ rcvid INTEGER, -- Origin of this record
83 @ size INTEGER, -- Size of content. -1 for a phantom.
84 @ uuid TEXT UNIQUE NOT NULL, -- hash of the content
85 @ content BLOB, -- Compressed content of this record
86 @ CHECK( length(uuid)>=40 AND rid>0 )
87 @ );
88 @ CREATE TABLE delta(
89 @ rid INTEGER PRIMARY KEY, -- BLOB that is delta-compressed
90 @ srcid INTEGER NOT NULL REFERENCES blob -- Baseline for delta-compression
91 @ );
92
+79 -11
--- src/sha1.c
+++ src/sha1.c
@@ -1,22 +1,88 @@
11
/*
2
+** Copyright (c) 2006 D. Richard Hipp
3
+**
4
+** This program is free software; you can redistribute it and/or
5
+** modify it under the terms of the Simplified BSD License (also
6
+** known as the "2-Clause License" or "FreeBSD License".)
7
+**
8
+** This program is distributed in the hope that it will be useful,
9
+** but without any warranty; without even the implied warranty of
10
+** merchantability or fitness for a particular purpose.
11
+**
12
+** Author contact information:
13
+** [email protected]
14
+** http://www.hwaci.com/drh/
15
+**
16
+*******************************************************************************
17
+**
218
** This implementation of SHA1.
319
*/
420
#include "config.h"
521
#include <sys/types.h>
22
+#include <stdint.h>
623
#include "sha1.h"
724
8
-#ifdef FOSSIL_ENABLE_SSL
25
+
26
+/*
27
+** SHA1 Implementation #1 is the hardened SHA1 implementation by
28
+** Marc Stevens. Code obtained from GitHub
29
+**
30
+** https://github.com/cr-marcstevens/sha1collisiondetection
31
+**
32
+** Downloaded on 2017-03-01 then repackaged to work with Fossil
33
+** and makeheaders.
34
+*/
35
+#if FOSSIL_HARDENED_SHA1
36
+
37
+#if INTERFACE
38
+typedef void(*collision_block_callback)(uint64_t, const uint32_t*, const uint32_t*, const uint32_t*, const uint32_t*);
39
+struct SHA1_CTX {
40
+ uint64_t total;
41
+ uint32_t ihv[5];
42
+ unsigned char buffer[64];
43
+ int bigendian;
44
+ int found_collision;
45
+ int safe_hash;
46
+ int detect_coll;
47
+ int ubc_check;
48
+ int reduced_round_coll;
49
+ collision_block_callback callback;
50
+
51
+ uint32_t ihv1[5];
52
+ uint32_t ihv2[5];
53
+ uint32_t m1[80];
54
+ uint32_t m2[80];
55
+ uint32_t states[80][5];
56
+};
57
+#endif
58
+void SHA1DCInit(SHA1_CTX*);
59
+void SHA1DCUpdate(SHA1_CTX*, const unsigned char*, unsigned);
60
+int SHA1DCFinal(unsigned char[20], SHA1_CTX*);
61
+
62
+#define SHA1Context SHA1_CTX
63
+#define SHA1Init SHA1DCInit
64
+#define SHA1Update SHA1DCUpdate
65
+#define SHA1Final SHA1DCFinal
66
+
67
+/*
68
+** SHA1 Implementation #2: use the SHA1 algorithm built into SSL
69
+*/
70
+#elif defined(FOSSIL_ENABLE_SSL)
971
1072
# include <openssl/sha.h>
1173
# define SHA1Context SHA_CTX
1274
# define SHA1Init SHA1_Init
1375
# define SHA1Update SHA1_Update
14
-# define SHA1Final(a,b) SHA1_Final(b,a)
76
+# define SHA1Final SHA1_Final
1577
78
+/*
79
+** SHA1 Implementation #3: If none of the previous two SHA1
80
+** algorithms work, there is this built-in. This built-in was the
81
+** original implementation used by Fossil.
82
+*/
1683
#else
17
-
1884
/*
1985
** The SHA1 implementation below is adapted from:
2086
**
2187
** $NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $
2288
** $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $
@@ -53,10 +119,13 @@
53119
/* Generic C equivalent */
54120
#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
55121
#define rol(x,k) SHA_ROT(x,k,32-(k))
56122
#define ror(x,k) SHA_ROT(x,32-(k),k)
57123
#endif
124
+
125
+
126
+
58127
59128
60129
#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
61130
|(rol(block[i],8)&0x00FF00FF))
62131
#define blk0be(i) block[i]
@@ -188,11 +257,11 @@
188257
189258
190259
/*
191260
* Add padding and return the message digest.
192261
*/
193
-static void SHA1Final(SHA1Context *context, unsigned char digest[20]){
262
+static void SHA1Final(unsigned char *digest, SHA1Context *context){
194263
unsigned int i;
195264
unsigned char finalcount[8];
196265
197266
for (i = 0; i < 8; i++) {
198267
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
@@ -207,12 +276,11 @@
207276
for (i = 0; i < 20; i++)
208277
digest[i] = (unsigned char)
209278
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
210279
}
211280
}
212
-#endif
213
-
281
+#endif /* Built-in SHA1 implemenation */
214282
215283
/*
216284
** Convert a digest into base-16. digest should be declared as
217285
** "unsigned char digest[20]" in the calling function. The SHA1
218286
** digest is stored in the first 20 bytes. zBuf should
@@ -268,11 +336,11 @@
268336
*/
269337
char *sha1sum_finish(Blob *pOut){
270338
unsigned char zResult[20];
271339
static char zOut[41];
272340
sha1sum_step_text(0,0);
273
- SHA1Final(&incrCtx, zResult);
341
+ SHA1Final(zResult, &incrCtx);
274342
incrInit = 0;
275343
DigestToBase16(zResult, zOut);
276344
if( pOut ){
277345
blob_zero(pOut);
278346
blob_append(pOut, zOut, 40);
@@ -316,11 +384,11 @@
316384
SHA1Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
317385
}
318386
fclose(in);
319387
blob_zero(pCksum);
320388
blob_resize(pCksum, 40);
321
- SHA1Final(&ctx, zResult);
389
+ SHA1Final(zResult, &ctx);
322390
DigestToBase16(zResult, blob_buffer(pCksum));
323391
return 0;
324392
}
325393
326394
/*
@@ -340,11 +408,11 @@
340408
blob_reset(pCksum);
341409
}else{
342410
blob_zero(pCksum);
343411
}
344412
blob_resize(pCksum, 40);
345
- SHA1Final(&ctx, zResult);
413
+ SHA1Final(zResult, &ctx);
346414
DigestToBase16(zResult, blob_buffer(pCksum));
347415
return 0;
348416
}
349417
350418
/*
@@ -356,11 +424,11 @@
356424
unsigned char zResult[20];
357425
char zDigest[41];
358426
359427
SHA1Init(&ctx);
360428
SHA1Update(&ctx, (unsigned const char*)zIn, strlen(zIn));
361
- SHA1Final(&ctx, zResult);
429
+ SHA1Final(zResult, &ctx);
362430
DigestToBase16(zResult, zDigest);
363431
return mprintf("%s", zDigest);
364432
}
365433
366434
/*
@@ -407,11 +475,11 @@
407475
SHA1Update(&ctx, (unsigned char*)zProjCode, strlen(zProjCode));
408476
SHA1Update(&ctx, (unsigned char*)"/", 1);
409477
SHA1Update(&ctx, (unsigned char*)zLogin, strlen(zLogin));
410478
SHA1Update(&ctx, (unsigned char*)"/", 1);
411479
SHA1Update(&ctx, (unsigned const char*)zPw, strlen(zPw));
412
- SHA1Final(&ctx, zResult);
480
+ SHA1Final(zResult, &ctx);
413481
DigestToBase16(zResult, zDigest);
414482
return mprintf("%s", zDigest);
415483
}
416484
417485
/*
418486
419487
ADDED src/sha1hard.c
420488
ADDED src/sha3.c
--- src/sha1.c
+++ src/sha1.c
@@ -1,22 +1,88 @@
1 /*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2 ** This implementation of SHA1.
3 */
4 #include "config.h"
5 #include <sys/types.h>
 
6 #include "sha1.h"
7
8 #ifdef FOSSIL_ENABLE_SSL
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
10 # include <openssl/sha.h>
11 # define SHA1Context SHA_CTX
12 # define SHA1Init SHA1_Init
13 # define SHA1Update SHA1_Update
14 # define SHA1Final(a,b) SHA1_Final(b,a)
15
 
 
 
 
 
16 #else
17
18 /*
19 ** The SHA1 implementation below is adapted from:
20 **
21 ** $NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $
22 ** $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $
@@ -53,10 +119,13 @@
53 /* Generic C equivalent */
54 #define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
55 #define rol(x,k) SHA_ROT(x,k,32-(k))
56 #define ror(x,k) SHA_ROT(x,32-(k),k)
57 #endif
 
 
 
58
59
60 #define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
61 |(rol(block[i],8)&0x00FF00FF))
62 #define blk0be(i) block[i]
@@ -188,11 +257,11 @@
188
189
190 /*
191 * Add padding and return the message digest.
192 */
193 static void SHA1Final(SHA1Context *context, unsigned char digest[20]){
194 unsigned int i;
195 unsigned char finalcount[8];
196
197 for (i = 0; i < 8; i++) {
198 finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
@@ -207,12 +276,11 @@
207 for (i = 0; i < 20; i++)
208 digest[i] = (unsigned char)
209 ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
210 }
211 }
212 #endif
213
214
215 /*
216 ** Convert a digest into base-16. digest should be declared as
217 ** "unsigned char digest[20]" in the calling function. The SHA1
218 ** digest is stored in the first 20 bytes. zBuf should
@@ -268,11 +336,11 @@
268 */
269 char *sha1sum_finish(Blob *pOut){
270 unsigned char zResult[20];
271 static char zOut[41];
272 sha1sum_step_text(0,0);
273 SHA1Final(&incrCtx, zResult);
274 incrInit = 0;
275 DigestToBase16(zResult, zOut);
276 if( pOut ){
277 blob_zero(pOut);
278 blob_append(pOut, zOut, 40);
@@ -316,11 +384,11 @@
316 SHA1Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
317 }
318 fclose(in);
319 blob_zero(pCksum);
320 blob_resize(pCksum, 40);
321 SHA1Final(&ctx, zResult);
322 DigestToBase16(zResult, blob_buffer(pCksum));
323 return 0;
324 }
325
326 /*
@@ -340,11 +408,11 @@
340 blob_reset(pCksum);
341 }else{
342 blob_zero(pCksum);
343 }
344 blob_resize(pCksum, 40);
345 SHA1Final(&ctx, zResult);
346 DigestToBase16(zResult, blob_buffer(pCksum));
347 return 0;
348 }
349
350 /*
@@ -356,11 +424,11 @@
356 unsigned char zResult[20];
357 char zDigest[41];
358
359 SHA1Init(&ctx);
360 SHA1Update(&ctx, (unsigned const char*)zIn, strlen(zIn));
361 SHA1Final(&ctx, zResult);
362 DigestToBase16(zResult, zDigest);
363 return mprintf("%s", zDigest);
364 }
365
366 /*
@@ -407,11 +475,11 @@
407 SHA1Update(&ctx, (unsigned char*)zProjCode, strlen(zProjCode));
408 SHA1Update(&ctx, (unsigned char*)"/", 1);
409 SHA1Update(&ctx, (unsigned char*)zLogin, strlen(zLogin));
410 SHA1Update(&ctx, (unsigned char*)"/", 1);
411 SHA1Update(&ctx, (unsigned const char*)zPw, strlen(zPw));
412 SHA1Final(&ctx, zResult);
413 DigestToBase16(zResult, zDigest);
414 return mprintf("%s", zDigest);
415 }
416
417 /*
418
419 DDED src/sha1hard.c
420 DDED src/sha3.c
--- src/sha1.c
+++ src/sha1.c
@@ -1,22 +1,88 @@
1 /*
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7 **
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This implementation of SHA1.
19 */
20 #include "config.h"
21 #include <sys/types.h>
22 #include <stdint.h>
23 #include "sha1.h"
24
25
26 /*
27 ** SHA1 Implementation #1 is the hardened SHA1 implementation by
28 ** Marc Stevens. Code obtained from GitHub
29 **
30 ** https://github.com/cr-marcstevens/sha1collisiondetection
31 **
32 ** Downloaded on 2017-03-01 then repackaged to work with Fossil
33 ** and makeheaders.
34 */
35 #if FOSSIL_HARDENED_SHA1
36
37 #if INTERFACE
38 typedef void(*collision_block_callback)(uint64_t, const uint32_t*, const uint32_t*, const uint32_t*, const uint32_t*);
39 struct SHA1_CTX {
40 uint64_t total;
41 uint32_t ihv[5];
42 unsigned char buffer[64];
43 int bigendian;
44 int found_collision;
45 int safe_hash;
46 int detect_coll;
47 int ubc_check;
48 int reduced_round_coll;
49 collision_block_callback callback;
50
51 uint32_t ihv1[5];
52 uint32_t ihv2[5];
53 uint32_t m1[80];
54 uint32_t m2[80];
55 uint32_t states[80][5];
56 };
57 #endif
58 void SHA1DCInit(SHA1_CTX*);
59 void SHA1DCUpdate(SHA1_CTX*, const unsigned char*, unsigned);
60 int SHA1DCFinal(unsigned char[20], SHA1_CTX*);
61
62 #define SHA1Context SHA1_CTX
63 #define SHA1Init SHA1DCInit
64 #define SHA1Update SHA1DCUpdate
65 #define SHA1Final SHA1DCFinal
66
67 /*
68 ** SHA1 Implementation #2: use the SHA1 algorithm built into SSL
69 */
70 #elif defined(FOSSIL_ENABLE_SSL)
71
72 # include <openssl/sha.h>
73 # define SHA1Context SHA_CTX
74 # define SHA1Init SHA1_Init
75 # define SHA1Update SHA1_Update
76 # define SHA1Final SHA1_Final
77
78 /*
79 ** SHA1 Implementation #3: If none of the previous two SHA1
80 ** algorithms work, there is this built-in. This built-in was the
81 ** original implementation used by Fossil.
82 */
83 #else
 
84 /*
85 ** The SHA1 implementation below is adapted from:
86 **
87 ** $NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $
88 ** $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $
@@ -53,10 +119,13 @@
119 /* Generic C equivalent */
120 #define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
121 #define rol(x,k) SHA_ROT(x,k,32-(k))
122 #define ror(x,k) SHA_ROT(x,32-(k),k)
123 #endif
124
125
126
127
128
129 #define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
130 |(rol(block[i],8)&0x00FF00FF))
131 #define blk0be(i) block[i]
@@ -188,11 +257,11 @@
257
258
259 /*
260 * Add padding and return the message digest.
261 */
262 static void SHA1Final(unsigned char *digest, SHA1Context *context){
263 unsigned int i;
264 unsigned char finalcount[8];
265
266 for (i = 0; i < 8; i++) {
267 finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
@@ -207,12 +276,11 @@
276 for (i = 0; i < 20; i++)
277 digest[i] = (unsigned char)
278 ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
279 }
280 }
281 #endif /* Built-in SHA1 implemenation */
 
282
283 /*
284 ** Convert a digest into base-16. digest should be declared as
285 ** "unsigned char digest[20]" in the calling function. The SHA1
286 ** digest is stored in the first 20 bytes. zBuf should
@@ -268,11 +336,11 @@
336 */
337 char *sha1sum_finish(Blob *pOut){
338 unsigned char zResult[20];
339 static char zOut[41];
340 sha1sum_step_text(0,0);
341 SHA1Final(zResult, &incrCtx);
342 incrInit = 0;
343 DigestToBase16(zResult, zOut);
344 if( pOut ){
345 blob_zero(pOut);
346 blob_append(pOut, zOut, 40);
@@ -316,11 +384,11 @@
384 SHA1Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
385 }
386 fclose(in);
387 blob_zero(pCksum);
388 blob_resize(pCksum, 40);
389 SHA1Final(zResult, &ctx);
390 DigestToBase16(zResult, blob_buffer(pCksum));
391 return 0;
392 }
393
394 /*
@@ -340,11 +408,11 @@
408 blob_reset(pCksum);
409 }else{
410 blob_zero(pCksum);
411 }
412 blob_resize(pCksum, 40);
413 SHA1Final(zResult, &ctx);
414 DigestToBase16(zResult, blob_buffer(pCksum));
415 return 0;
416 }
417
418 /*
@@ -356,11 +424,11 @@
424 unsigned char zResult[20];
425 char zDigest[41];
426
427 SHA1Init(&ctx);
428 SHA1Update(&ctx, (unsigned const char*)zIn, strlen(zIn));
429 SHA1Final(zResult, &ctx);
430 DigestToBase16(zResult, zDigest);
431 return mprintf("%s", zDigest);
432 }
433
434 /*
@@ -407,11 +475,11 @@
475 SHA1Update(&ctx, (unsigned char*)zProjCode, strlen(zProjCode));
476 SHA1Update(&ctx, (unsigned char*)"/", 1);
477 SHA1Update(&ctx, (unsigned char*)zLogin, strlen(zLogin));
478 SHA1Update(&ctx, (unsigned char*)"/", 1);
479 SHA1Update(&ctx, (unsigned const char*)zPw, strlen(zPw));
480 SHA1Final(zResult, &ctx);
481 DigestToBase16(zResult, zDigest);
482 return mprintf("%s", zDigest);
483 }
484
485 /*
486
487 DDED src/sha1hard.c
488 DDED src/sha3.c

No diff available

+1
--- a/src/sha3.c
+++ b/src/sha3.c
@@ -0,0 +1 @@
1
+1241441
--- a/src/sha3.c
+++ b/src/sha3.c
@@ -0,0 +1 @@
 
--- a/src/sha3.c
+++ b/src/sha3.c
@@ -0,0 +1 @@
1 1241441
+4 -3
--- src/shell.c
+++ src/shell.c
@@ -2210,11 +2210,11 @@
22102210
" csv Comma-separated values\n"
22112211
" column Left-aligned columns. (See .width)\n"
22122212
" html HTML <table> code\n"
22132213
" insert SQL insert statements for TABLE\n"
22142214
" line One value per line\n"
2215
- " list Values delimited by .separator strings\n"
2215
+ " list Values delimited by \"|\"\n"
22162216
" quote Escape answers as for SQL\n"
22172217
" tabs Tab-separated values\n"
22182218
" tcl TCL list elements\n"
22192219
".nullvalue STRING Use STRING in place of NULL values\n"
22202220
".once FILENAME Output for the next SQL command only to FILENAME\n"
@@ -4342,10 +4342,11 @@
43424342
int newFlag = 0; /* True to delete file before opening */
43434343
/* Close the existing database */
43444344
session_close_all(p);
43454345
sqlite3_close(p->db);
43464346
p->db = 0;
4347
+ p->zDbFilename = 0;
43474348
sqlite3_free(p->zFreeOnClose);
43484349
p->zFreeOnClose = 0;
43494350
/* Check for command-line arguments */
43504351
for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
43514352
const char *z = azArg[iName];
@@ -4612,11 +4613,11 @@
46124613
}
46134614
}else
46144615
46154616
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
46164617
if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
4617
- sqlite3SelectTrace = integerValue(azArg[1]);
4618
+ sqlite3SelectTrace = (int)integerValue(azArg[1]);
46184619
}else
46194620
#endif
46204621
46214622
#if defined(SQLITE_ENABLE_SESSION)
46224623
if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
@@ -5190,10 +5191,11 @@
51905191
azArg[1]);
51915192
break;
51925193
}
51935194
}
51945195
}else
5196
+#endif /* !defined(SQLITE_UNTESTABLE) */
51955197
51965198
if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
51975199
open_db(p, 0);
51985200
sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
51995201
}else
@@ -5226,11 +5228,10 @@
52265228
}else{
52275229
sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut);
52285230
}
52295231
#endif
52305232
}else
5231
-#endif /* !defined(SQLITE_UNTESTABLE) */
52325233
52335234
#if SQLITE_USER_AUTHENTICATION
52345235
if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
52355236
if( nArg<2 ){
52365237
raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
52375238
--- src/shell.c
+++ src/shell.c
@@ -2210,11 +2210,11 @@
2210 " csv Comma-separated values\n"
2211 " column Left-aligned columns. (See .width)\n"
2212 " html HTML <table> code\n"
2213 " insert SQL insert statements for TABLE\n"
2214 " line One value per line\n"
2215 " list Values delimited by .separator strings\n"
2216 " quote Escape answers as for SQL\n"
2217 " tabs Tab-separated values\n"
2218 " tcl TCL list elements\n"
2219 ".nullvalue STRING Use STRING in place of NULL values\n"
2220 ".once FILENAME Output for the next SQL command only to FILENAME\n"
@@ -4342,10 +4342,11 @@
4342 int newFlag = 0; /* True to delete file before opening */
4343 /* Close the existing database */
4344 session_close_all(p);
4345 sqlite3_close(p->db);
4346 p->db = 0;
 
4347 sqlite3_free(p->zFreeOnClose);
4348 p->zFreeOnClose = 0;
4349 /* Check for command-line arguments */
4350 for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
4351 const char *z = azArg[iName];
@@ -4612,11 +4613,11 @@
4612 }
4613 }else
4614
4615 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
4616 if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
4617 sqlite3SelectTrace = integerValue(azArg[1]);
4618 }else
4619 #endif
4620
4621 #if defined(SQLITE_ENABLE_SESSION)
4622 if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
@@ -5190,10 +5191,11 @@
5190 azArg[1]);
5191 break;
5192 }
5193 }
5194 }else
 
5195
5196 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
5197 open_db(p, 0);
5198 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
5199 }else
@@ -5226,11 +5228,10 @@
5226 }else{
5227 sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut);
5228 }
5229 #endif
5230 }else
5231 #endif /* !defined(SQLITE_UNTESTABLE) */
5232
5233 #if SQLITE_USER_AUTHENTICATION
5234 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
5235 if( nArg<2 ){
5236 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
5237
--- src/shell.c
+++ src/shell.c
@@ -2210,11 +2210,11 @@
2210 " csv Comma-separated values\n"
2211 " column Left-aligned columns. (See .width)\n"
2212 " html HTML <table> code\n"
2213 " insert SQL insert statements for TABLE\n"
2214 " line One value per line\n"
2215 " list Values delimited by \"|\"\n"
2216 " quote Escape answers as for SQL\n"
2217 " tabs Tab-separated values\n"
2218 " tcl TCL list elements\n"
2219 ".nullvalue STRING Use STRING in place of NULL values\n"
2220 ".once FILENAME Output for the next SQL command only to FILENAME\n"
@@ -4342,10 +4342,11 @@
4342 int newFlag = 0; /* True to delete file before opening */
4343 /* Close the existing database */
4344 session_close_all(p);
4345 sqlite3_close(p->db);
4346 p->db = 0;
4347 p->zDbFilename = 0;
4348 sqlite3_free(p->zFreeOnClose);
4349 p->zFreeOnClose = 0;
4350 /* Check for command-line arguments */
4351 for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
4352 const char *z = azArg[iName];
@@ -4612,11 +4613,11 @@
4613 }
4614 }else
4615
4616 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
4617 if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
4618 sqlite3SelectTrace = (int)integerValue(azArg[1]);
4619 }else
4620 #endif
4621
4622 #if defined(SQLITE_ENABLE_SESSION)
4623 if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
@@ -5190,10 +5191,11 @@
5191 azArg[1]);
5192 break;
5193 }
5194 }
5195 }else
5196 #endif /* !defined(SQLITE_UNTESTABLE) */
5197
5198 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
5199 open_db(p, 0);
5200 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
5201 }else
@@ -5226,11 +5228,10 @@
5228 }else{
5229 sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut);
5230 }
5231 #endif
5232 }else
 
5233
5234 #if SQLITE_USER_AUTHENTICATION
5235 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
5236 if( nArg<2 ){
5237 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
5238
+14 -13
--- src/shun.c
+++ src/shun.c
@@ -26,10 +26,11 @@
2626
*/
2727
int uuid_is_shunned(const char *zUuid){
2828
static Stmt q;
2929
int rc;
3030
if( zUuid==0 || zUuid[0]==0 ) return 0;
31
+ if( g.eHashPolicy==HPOLICY_SHUN_SHA1 && zUuid[HNAME_LEN_SHA1]==0 ) return 1;
3132
db_static_prepare(&q, "SELECT 1 FROM shun WHERE uuid=:uuid");
3233
db_bind_text(&q, ":uuid", zUuid);
3334
rc = db_step(&q);
3435
db_reset(&q);
3536
return rc==SQLITE_ROW;
@@ -36,11 +37,11 @@
3637
}
3738
3839
/*
3940
** WEBPAGE: shun
4041
**
41
-** View the SHA1 hashes of all shunned artifacts. Add new hashes
42
+** View the hashes of all shunned artifacts. Add new hashes
4243
** to the shun set. Requires Admin privilege.
4344
*/
4445
void shun_page(void){
4546
Stmt q;
4647
int cnt = 0;
@@ -84,18 +85,18 @@
8485
}
8586
zCanonical[j+1] = zCanonical[j] = 0;
8687
p = zCanonical;
8788
while( *p ){
8889
int nUuid = strlen(p);
89
- if( nUuid!=UUID_SIZE || !validate16(p, nUuid) ){
90
+ if( !hname_validate(p, nUuid) ){
9091
@ <p class="generalError">Error: Bad artifact IDs.</p>
9192
fossil_free(zCanonical);
9293
zCanonical = 0;
9394
break;
9495
}else{
95
- canonical16(p, UUID_SIZE);
96
- p += UUID_SIZE+1;
96
+ canonical16(p, nUuid);
97
+ p += nUuid+1;
9798
}
9899
}
99100
zUuid = zCanonical;
100101
}
101102
style_header("Shunned Artifacts");
@@ -107,21 +108,21 @@
107108
db_multi_exec("DELETE FROM shun WHERE uuid=%Q", p);
108109
if( !db_exists("SELECT 1 FROM blob WHERE uuid=%Q", p) ){
109110
allExist = 0;
110111
}
111112
admin_log("Unshunned %Q", p);
112
- p += UUID_SIZE+1;
113
+ p += strlen(p)+1;
113114
}
114115
if( allExist ){
115116
@ <p class="noMoreShun">Artifact(s)<br />
116
- for( p = zUuid ; *p ; p += UUID_SIZE+1 ){
117
+ for( p = zUuid ; *p ; p += strlen(p)+1 ){
117118
@ <a href="%R/artifact/%s(p)">%s(p)</a><br />
118119
}
119120
@ are no longer being shunned.</p>
120121
}else{
121122
@ <p class="noMoreShun">Artifact(s)<br />
122
- for( p = zUuid ; *p ; p += UUID_SIZE+1 ){
123
+ for( p = zUuid ; *p ; p += strlen(p)+1 ){
123124
@ %s(p)<br />
124125
}
125126
@ will no longer be shunned. But they may not exist in the repository.
126127
@ It may be necessary to rebuild the repository using the
127128
@ <b>fossil rebuild</b> command-line before the artifact content
@@ -146,14 +147,14 @@
146147
db_multi_exec("DELETE FROM ticket WHERE tkt_uuid=%Q", p);
147148
db_multi_exec("DELETE FROM tag WHERE tagid=%d", tagid);
148149
db_multi_exec("DELETE FROM tagxref WHERE tagid=%d", tagid);
149150
}
150151
admin_log("Shunned %Q", p);
151
- p += UUID_SIZE+1;
152
+ p += strlen(p)+1;
152153
}
153154
@ <p class="shunned">Artifact(s)<br />
154
- for( p = zUuid ; *p ; p += UUID_SIZE+1 ){
155
+ for( p = zUuid ; *p ; p += strlen(p)+1 ){
155156
@ <a href="%R/artifact/%s(p)">%s(p)</a><br />
156157
}
157158
@ have been shunned. They will no longer be pushed.
158159
@ They will be removed from the repository the next time the repository
159160
@ is rebuilt using the <b>fossil rebuild</b> command-line</p>
@@ -167,18 +168,18 @@
167168
@ artifact content will be purged from the repository the next time the
168169
@ repository is rebuilt. A list of shunned artifacts can be seen at the
169170
@ bottom of this page.</p>
170171
@
171172
@ <a name="addshun"></a>
172
- @ <p>To shun artifacts, enter their artifact IDs (the 40-character SHA1
173
- @ hash of the artifacts) in the
173
+ @ <p>To shun artifacts, enter their artifact hashes (the 40- or
174
+ @ 64-character lowercase hexadecimal hash of the artifact content) in the
174175
@ following box and press the "Shun" button. This will cause the artifacts
175176
@ to be removed from the repository and will prevent the artifacts from being
176177
@ readded to the repository by subsequent sync operation.</p>
177178
@
178
- @ <p>Note that you must enter the full 40-character artifact IDs, not
179
- @ an abbreviation or a symbolic tag.</p>
179
+ @ <p>Note that you must enter the full 40- or 64-character artifact hashes,
180
+ @ not an abbreviation or a symbolic tag.</p>
180181
@
181182
@ <p>Warning: Shunning should only be used to remove inappropriate content
182183
@ from the repository. Inappropriate content includes such things as
183184
@ spam added to Wiki, files that violate copyright or patent agreements,
184185
@ or artifacts that by design or accident interfere with the processing
185186
--- src/shun.c
+++ src/shun.c
@@ -26,10 +26,11 @@
26 */
27 int uuid_is_shunned(const char *zUuid){
28 static Stmt q;
29 int rc;
30 if( zUuid==0 || zUuid[0]==0 ) return 0;
 
31 db_static_prepare(&q, "SELECT 1 FROM shun WHERE uuid=:uuid");
32 db_bind_text(&q, ":uuid", zUuid);
33 rc = db_step(&q);
34 db_reset(&q);
35 return rc==SQLITE_ROW;
@@ -36,11 +37,11 @@
36 }
37
38 /*
39 ** WEBPAGE: shun
40 **
41 ** View the SHA1 hashes of all shunned artifacts. Add new hashes
42 ** to the shun set. Requires Admin privilege.
43 */
44 void shun_page(void){
45 Stmt q;
46 int cnt = 0;
@@ -84,18 +85,18 @@
84 }
85 zCanonical[j+1] = zCanonical[j] = 0;
86 p = zCanonical;
87 while( *p ){
88 int nUuid = strlen(p);
89 if( nUuid!=UUID_SIZE || !validate16(p, nUuid) ){
90 @ <p class="generalError">Error: Bad artifact IDs.</p>
91 fossil_free(zCanonical);
92 zCanonical = 0;
93 break;
94 }else{
95 canonical16(p, UUID_SIZE);
96 p += UUID_SIZE+1;
97 }
98 }
99 zUuid = zCanonical;
100 }
101 style_header("Shunned Artifacts");
@@ -107,21 +108,21 @@
107 db_multi_exec("DELETE FROM shun WHERE uuid=%Q", p);
108 if( !db_exists("SELECT 1 FROM blob WHERE uuid=%Q", p) ){
109 allExist = 0;
110 }
111 admin_log("Unshunned %Q", p);
112 p += UUID_SIZE+1;
113 }
114 if( allExist ){
115 @ <p class="noMoreShun">Artifact(s)<br />
116 for( p = zUuid ; *p ; p += UUID_SIZE+1 ){
117 @ <a href="%R/artifact/%s(p)">%s(p)</a><br />
118 }
119 @ are no longer being shunned.</p>
120 }else{
121 @ <p class="noMoreShun">Artifact(s)<br />
122 for( p = zUuid ; *p ; p += UUID_SIZE+1 ){
123 @ %s(p)<br />
124 }
125 @ will no longer be shunned. But they may not exist in the repository.
126 @ It may be necessary to rebuild the repository using the
127 @ <b>fossil rebuild</b> command-line before the artifact content
@@ -146,14 +147,14 @@
146 db_multi_exec("DELETE FROM ticket WHERE tkt_uuid=%Q", p);
147 db_multi_exec("DELETE FROM tag WHERE tagid=%d", tagid);
148 db_multi_exec("DELETE FROM tagxref WHERE tagid=%d", tagid);
149 }
150 admin_log("Shunned %Q", p);
151 p += UUID_SIZE+1;
152 }
153 @ <p class="shunned">Artifact(s)<br />
154 for( p = zUuid ; *p ; p += UUID_SIZE+1 ){
155 @ <a href="%R/artifact/%s(p)">%s(p)</a><br />
156 }
157 @ have been shunned. They will no longer be pushed.
158 @ They will be removed from the repository the next time the repository
159 @ is rebuilt using the <b>fossil rebuild</b> command-line</p>
@@ -167,18 +168,18 @@
167 @ artifact content will be purged from the repository the next time the
168 @ repository is rebuilt. A list of shunned artifacts can be seen at the
169 @ bottom of this page.</p>
170 @
171 @ <a name="addshun"></a>
172 @ <p>To shun artifacts, enter their artifact IDs (the 40-character SHA1
173 @ hash of the artifacts) in the
174 @ following box and press the "Shun" button. This will cause the artifacts
175 @ to be removed from the repository and will prevent the artifacts from being
176 @ readded to the repository by subsequent sync operation.</p>
177 @
178 @ <p>Note that you must enter the full 40-character artifact IDs, not
179 @ an abbreviation or a symbolic tag.</p>
180 @
181 @ <p>Warning: Shunning should only be used to remove inappropriate content
182 @ from the repository. Inappropriate content includes such things as
183 @ spam added to Wiki, files that violate copyright or patent agreements,
184 @ or artifacts that by design or accident interfere with the processing
185
--- src/shun.c
+++ src/shun.c
@@ -26,10 +26,11 @@
26 */
27 int uuid_is_shunned(const char *zUuid){
28 static Stmt q;
29 int rc;
30 if( zUuid==0 || zUuid[0]==0 ) return 0;
31 if( g.eHashPolicy==HPOLICY_SHUN_SHA1 && zUuid[HNAME_LEN_SHA1]==0 ) return 1;
32 db_static_prepare(&q, "SELECT 1 FROM shun WHERE uuid=:uuid");
33 db_bind_text(&q, ":uuid", zUuid);
34 rc = db_step(&q);
35 db_reset(&q);
36 return rc==SQLITE_ROW;
@@ -36,11 +37,11 @@
37 }
38
39 /*
40 ** WEBPAGE: shun
41 **
42 ** View the hashes of all shunned artifacts. Add new hashes
43 ** to the shun set. Requires Admin privilege.
44 */
45 void shun_page(void){
46 Stmt q;
47 int cnt = 0;
@@ -84,18 +85,18 @@
85 }
86 zCanonical[j+1] = zCanonical[j] = 0;
87 p = zCanonical;
88 while( *p ){
89 int nUuid = strlen(p);
90 if( !hname_validate(p, nUuid) ){
91 @ <p class="generalError">Error: Bad artifact IDs.</p>
92 fossil_free(zCanonical);
93 zCanonical = 0;
94 break;
95 }else{
96 canonical16(p, nUuid);
97 p += nUuid+1;
98 }
99 }
100 zUuid = zCanonical;
101 }
102 style_header("Shunned Artifacts");
@@ -107,21 +108,21 @@
108 db_multi_exec("DELETE FROM shun WHERE uuid=%Q", p);
109 if( !db_exists("SELECT 1 FROM blob WHERE uuid=%Q", p) ){
110 allExist = 0;
111 }
112 admin_log("Unshunned %Q", p);
113 p += strlen(p)+1;
114 }
115 if( allExist ){
116 @ <p class="noMoreShun">Artifact(s)<br />
117 for( p = zUuid ; *p ; p += strlen(p)+1 ){
118 @ <a href="%R/artifact/%s(p)">%s(p)</a><br />
119 }
120 @ are no longer being shunned.</p>
121 }else{
122 @ <p class="noMoreShun">Artifact(s)<br />
123 for( p = zUuid ; *p ; p += strlen(p)+1 ){
124 @ %s(p)<br />
125 }
126 @ will no longer be shunned. But they may not exist in the repository.
127 @ It may be necessary to rebuild the repository using the
128 @ <b>fossil rebuild</b> command-line before the artifact content
@@ -146,14 +147,14 @@
147 db_multi_exec("DELETE FROM ticket WHERE tkt_uuid=%Q", p);
148 db_multi_exec("DELETE FROM tag WHERE tagid=%d", tagid);
149 db_multi_exec("DELETE FROM tagxref WHERE tagid=%d", tagid);
150 }
151 admin_log("Shunned %Q", p);
152 p += strlen(p)+1;
153 }
154 @ <p class="shunned">Artifact(s)<br />
155 for( p = zUuid ; *p ; p += strlen(p)+1 ){
156 @ <a href="%R/artifact/%s(p)">%s(p)</a><br />
157 }
158 @ have been shunned. They will no longer be pushed.
159 @ They will be removed from the repository the next time the repository
160 @ is rebuilt using the <b>fossil rebuild</b> command-line</p>
@@ -167,18 +168,18 @@
168 @ artifact content will be purged from the repository the next time the
169 @ repository is rebuilt. A list of shunned artifacts can be seen at the
170 @ bottom of this page.</p>
171 @
172 @ <a name="addshun"></a>
173 @ <p>To shun artifacts, enter their artifact hashes (the 40- or
174 @ 64-character lowercase hexadecimal hash of the artifact content) in the
175 @ following box and press the "Shun" button. This will cause the artifacts
176 @ to be removed from the repository and will prevent the artifacts from being
177 @ readded to the repository by subsequent sync operation.</p>
178 @
179 @ <p>Note that you must enter the full 40- or 64-character artifact hashes,
180 @ not an abbreviation or a symbolic tag.</p>
181 @
182 @ <p>Warning: Shunning should only be used to remove inappropriate content
183 @ from the repository. Inappropriate content includes such things as
184 @ spam added to Wiki, files that violate copyright or patent agreements,
185 @ or artifacts that by design or accident interfere with the processing
186
+1 -2
--- src/sitemap.c
+++ src/sitemap.c
@@ -111,12 +111,11 @@
111111
}
112112
@ <li>%z(href("%R/login"))Login/Logout/Change Password</a></li>
113113
if( g.perm.Read ){
114114
@ <li>%z(href("%R/stat"))Repository Status</a>
115115
@ <ul>
116
- @ <li>%z(href("%R/hash-collisions"))Collisions on SHA1 hash
117
- @ prefixes</a></li>
116
+ @ <li>%z(href("%R/hash-collisions"))Collisions on hash prefixes</a></li>
118117
if( g.perm.Admin ){
119118
@ <li>%z(href("%R/urllist"))List of URLs used to access
120119
@ this repository</a></li>
121120
}
122121
@ <li>%z(href("%R/bloblist"))List of Artifacts</a></li>
123122
--- src/sitemap.c
+++ src/sitemap.c
@@ -111,12 +111,11 @@
111 }
112 @ <li>%z(href("%R/login"))Login/Logout/Change Password</a></li>
113 if( g.perm.Read ){
114 @ <li>%z(href("%R/stat"))Repository Status</a>
115 @ <ul>
116 @ <li>%z(href("%R/hash-collisions"))Collisions on SHA1 hash
117 @ prefixes</a></li>
118 if( g.perm.Admin ){
119 @ <li>%z(href("%R/urllist"))List of URLs used to access
120 @ this repository</a></li>
121 }
122 @ <li>%z(href("%R/bloblist"))List of Artifacts</a></li>
123
--- src/sitemap.c
+++ src/sitemap.c
@@ -111,12 +111,11 @@
111 }
112 @ <li>%z(href("%R/login"))Login/Logout/Change Password</a></li>
113 if( g.perm.Read ){
114 @ <li>%z(href("%R/stat"))Repository Status</a>
115 @ <ul>
116 @ <li>%z(href("%R/hash-collisions"))Collisions on hash prefixes</a></li>
 
117 if( g.perm.Admin ){
118 @ <li>%z(href("%R/urllist"))List of URLs used to access
119 @ this repository</a></li>
120 }
121 @ <li>%z(href("%R/bloblist"))List of Artifacts</a></li>
122
+2 -2
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -185,12 +185,12 @@
185185
** in ways that are unrecoverable. Be sure you know what you are doing before
186186
** running any SQL commands that modify the repository database.
187187
**
188188
** The following extensions to the usual SQLite commands are provided:
189189
**
190
-** content(X) Return the content of artifact X. X can be a
191
-** SHA1 hash or prefix or a tag.
190
+** content(X) Return the content of artifact X. X can be an
191
+** artifact hash or prefix or a tag.
192192
**
193193
** compress(X) Compress text X.
194194
**
195195
** decompress(X) Decompress text X. Undoes the work of
196196
** compress(X).
197197
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -185,12 +185,12 @@
185 ** in ways that are unrecoverable. Be sure you know what you are doing before
186 ** running any SQL commands that modify the repository database.
187 **
188 ** The following extensions to the usual SQLite commands are provided:
189 **
190 ** content(X) Return the content of artifact X. X can be a
191 ** SHA1 hash or prefix or a tag.
192 **
193 ** compress(X) Compress text X.
194 **
195 ** decompress(X) Decompress text X. Undoes the work of
196 ** compress(X).
197
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -185,12 +185,12 @@
185 ** in ways that are unrecoverable. Be sure you know what you are doing before
186 ** running any SQL commands that modify the repository database.
187 **
188 ** The following extensions to the usual SQLite commands are provided:
189 **
190 ** content(X) Return the content of artifact X. X can be an
191 ** artifact hash or prefix or a tag.
192 **
193 ** compress(X) Compress text X.
194 **
195 ** decompress(X) Decompress text X. Undoes the work of
196 ** compress(X).
197
+35 -32
--- src/stash.c
+++ src/stash.c
@@ -332,52 +332,45 @@
332332
isBin2 = fIncludeBinary ? 0 : looks_like_binary(&a);
333333
diff_file_mem(&empty, &a, isBin1, isBin2, zNew, zDiffCmd,
334334
zBinGlob, fIncludeBinary, diffFlags);
335335
}else if( isRemoved ){
336336
fossil_print("DELETE %s\n", zOrig);
337
- if( fBaseline==0 ){
338
- if( file_wd_islink(zOPath) ){
339
- blob_read_link(&a, zOPath);
340
- }else{
341
- blob_read_from_file(&a, zOPath);
342
- }
343
- }else{
344
- content_get(rid, &a);
345
- }
346
- diff_print_index(zNew, diffFlags);
347
- isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a);
348
- isBin2 = 0;
349
- diff_file_mem(&a, &empty, isBin1, isBin2, zOrig, zDiffCmd,
350
- zBinGlob, fIncludeBinary, diffFlags);
351
- }else{
352
- Blob delta, disk;
337
+ diff_print_index(zNew, diffFlags);
338
+ isBin2 = 0;
339
+ if( fBaseline ){
340
+ content_get(rid, &a);
341
+ isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a);
342
+ diff_file_mem(&a, &empty, isBin1, isBin2, zOrig, zDiffCmd,
343
+ zBinGlob, fIncludeBinary, diffFlags);
344
+ }else{
345
+ }
346
+ }else{
347
+ Blob delta;
353348
int isOrigLink = file_wd_islink(zOPath);
354349
db_ephemeral_blob(&q, 6, &delta);
355
- if( fBaseline==0 ){
356
- if( isOrigLink ){
357
- blob_read_link(&disk, zOPath);
358
- }else{
359
- blob_read_from_file(&disk, zOPath);
360
- }
361
- }
362350
fossil_print("CHANGED %s\n", zNew);
363351
if( !isOrigLink != !isLink ){
364352
diff_print_index(zNew, diffFlags);
365353
diff_print_filenames(zOrig, zNew, diffFlags);
366354
printf(DIFF_CANNOT_COMPUTE_SYMLINK);
367355
}else{
368
- Blob *pBase = fBaseline ? &a : &disk;
369356
content_get(rid, &a);
370357
blob_delta_apply(&a, &delta, &b);
371
- isBin1 = fIncludeBinary ? 0 : looks_like_binary(pBase);
358
+ isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a);
372359
isBin2 = fIncludeBinary ? 0 : looks_like_binary(&b);
373
- diff_file_mem(fBaseline? &a : &disk, &b, isBin1, isBin2, zNew,
374
- zDiffCmd, zBinGlob, fIncludeBinary, diffFlags);
360
+ if( fBaseline ){
361
+ diff_file_mem(&a, &b, isBin1, isBin2, zNew,
362
+ zDiffCmd, zBinGlob, fIncludeBinary, diffFlags);
363
+ }else{
364
+ /*Diff with file on disk using fSwapDiff=1 to show the diff in the
365
+ same direction as if fBaseline=1.*/
366
+ diff_file(&b, isBin2, zOPath, zNew, zDiffCmd,
367
+ zBinGlob, fIncludeBinary, diffFlags, 1);
368
+ }
375369
blob_reset(&a);
376370
blob_reset(&b);
377371
}
378
- if( !fBaseline ) blob_reset(&disk);
379372
blob_reset(&delta);
380373
}
381374
}
382375
db_finalize(&q);
383376
}
@@ -433,12 +426,15 @@
433426
**
434427
** List all changes sets currently stashed. Show information about
435428
** individual files in each changeset if -v or --verbose is used.
436429
**
437430
** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
431
+** fossil stash gshow|gcat ?STASHID? ?DIFF-OPTIONS?
438432
**
439
-** Show the contents of a stash.
433
+** Show the contents of a stash as a diff against it's baseline.
434
+** With gshow and gcat, gdiff-command is used instead of internal
435
+** diff logic.
440436
**
441437
** fossil stash pop
442438
** fossil stash apply ?STASHID?
443439
**
444440
** Apply STASHID or the most recently create stash to the current
@@ -460,18 +456,20 @@
460456
**
461457
** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
462458
** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
463459
**
464460
** Show diffs of the current working directory and what that
465
-** directory would be if STASHID were applied.
461
+** directory would be if STASHID were applied. With gdiff,
462
+** gdiff-command is used instead of internal diff logic.
466463
**
467464
** SUMMARY:
468465
** fossil stash
469466
** fossil stash save ?-m|--comment COMMENT? ?FILES...?
470467
** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
471468
** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
472469
** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
470
+** fossil stash gshow|gcat ?STASHID? ?DIFF-OPTIONS?
473471
** fossil stash pop
474472
** fossil stash apply|goto ?STASHID?
475473
** fossil stash drop|rm ?STASHID? ?-a|--all?
476474
** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
477475
** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
@@ -654,25 +652,30 @@
654652
undo_finish();
655653
}else
656654
if( memcmp(zCmd, "diff", nCmd)==0
657655
|| memcmp(zCmd, "gdiff", nCmd)==0
658656
|| memcmp(zCmd, "show", nCmd)==0
657
+ || memcmp(zCmd, "gshow", nCmd)==0
659658
|| memcmp(zCmd, "cat", nCmd)==0
659
+ || memcmp(zCmd, "gcat", nCmd)==0
660660
){
661661
const char *zDiffCmd = 0;
662662
const char *zBinGlob = 0;
663663
int fIncludeBinary = 0;
664
- int fBaseline = zCmd[0]=='s' || zCmd[0]=='c';
664
+ int fBaseline = 0;
665665
u64 diffFlags;
666666
667
+ if( strstr(zCmd,"show")!=0 || strstr(zCmd,"cat")!=0 ){
668
+ fBaseline = 1;
669
+ }
667670
if( find_option("tk",0,0)!=0 ){
668671
db_close(0);
669672
diff_tk(fBaseline ? "stash show" : "stash diff", 3);
670673
return;
671674
}
672675
if( find_option("internal","i",0)==0 ){
673
- zDiffCmd = diff_command_external(memcmp(zCmd, "gdiff", nCmd)==0);
676
+ zDiffCmd = diff_command_external(zCmd[0]=='g');
674677
}
675678
diffFlags = diff_options();
676679
if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE;
677680
if( g.argc>4 ) usage(mprintf("%s ?STASHID? ?DIFF-OPTIONS?", zCmd));
678681
if( zDiffCmd ){
679682
--- src/stash.c
+++ src/stash.c
@@ -332,52 +332,45 @@
332 isBin2 = fIncludeBinary ? 0 : looks_like_binary(&a);
333 diff_file_mem(&empty, &a, isBin1, isBin2, zNew, zDiffCmd,
334 zBinGlob, fIncludeBinary, diffFlags);
335 }else if( isRemoved ){
336 fossil_print("DELETE %s\n", zOrig);
337 if( fBaseline==0 ){
338 if( file_wd_islink(zOPath) ){
339 blob_read_link(&a, zOPath);
340 }else{
341 blob_read_from_file(&a, zOPath);
342 }
343 }else{
344 content_get(rid, &a);
345 }
346 diff_print_index(zNew, diffFlags);
347 isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a);
348 isBin2 = 0;
349 diff_file_mem(&a, &empty, isBin1, isBin2, zOrig, zDiffCmd,
350 zBinGlob, fIncludeBinary, diffFlags);
351 }else{
352 Blob delta, disk;
353 int isOrigLink = file_wd_islink(zOPath);
354 db_ephemeral_blob(&q, 6, &delta);
355 if( fBaseline==0 ){
356 if( isOrigLink ){
357 blob_read_link(&disk, zOPath);
358 }else{
359 blob_read_from_file(&disk, zOPath);
360 }
361 }
362 fossil_print("CHANGED %s\n", zNew);
363 if( !isOrigLink != !isLink ){
364 diff_print_index(zNew, diffFlags);
365 diff_print_filenames(zOrig, zNew, diffFlags);
366 printf(DIFF_CANNOT_COMPUTE_SYMLINK);
367 }else{
368 Blob *pBase = fBaseline ? &a : &disk;
369 content_get(rid, &a);
370 blob_delta_apply(&a, &delta, &b);
371 isBin1 = fIncludeBinary ? 0 : looks_like_binary(pBase);
372 isBin2 = fIncludeBinary ? 0 : looks_like_binary(&b);
373 diff_file_mem(fBaseline? &a : &disk, &b, isBin1, isBin2, zNew,
374 zDiffCmd, zBinGlob, fIncludeBinary, diffFlags);
 
 
 
 
 
 
 
375 blob_reset(&a);
376 blob_reset(&b);
377 }
378 if( !fBaseline ) blob_reset(&disk);
379 blob_reset(&delta);
380 }
381 }
382 db_finalize(&q);
383 }
@@ -433,12 +426,15 @@
433 **
434 ** List all changes sets currently stashed. Show information about
435 ** individual files in each changeset if -v or --verbose is used.
436 **
437 ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
 
438 **
439 ** Show the contents of a stash.
 
 
440 **
441 ** fossil stash pop
442 ** fossil stash apply ?STASHID?
443 **
444 ** Apply STASHID or the most recently create stash to the current
@@ -460,18 +456,20 @@
460 **
461 ** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
462 ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
463 **
464 ** Show diffs of the current working directory and what that
465 ** directory would be if STASHID were applied.
 
466 **
467 ** SUMMARY:
468 ** fossil stash
469 ** fossil stash save ?-m|--comment COMMENT? ?FILES...?
470 ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
471 ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
472 ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
 
473 ** fossil stash pop
474 ** fossil stash apply|goto ?STASHID?
475 ** fossil stash drop|rm ?STASHID? ?-a|--all?
476 ** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
477 ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
@@ -654,25 +652,30 @@
654 undo_finish();
655 }else
656 if( memcmp(zCmd, "diff", nCmd)==0
657 || memcmp(zCmd, "gdiff", nCmd)==0
658 || memcmp(zCmd, "show", nCmd)==0
 
659 || memcmp(zCmd, "cat", nCmd)==0
 
660 ){
661 const char *zDiffCmd = 0;
662 const char *zBinGlob = 0;
663 int fIncludeBinary = 0;
664 int fBaseline = zCmd[0]=='s' || zCmd[0]=='c';
665 u64 diffFlags;
666
 
 
 
667 if( find_option("tk",0,0)!=0 ){
668 db_close(0);
669 diff_tk(fBaseline ? "stash show" : "stash diff", 3);
670 return;
671 }
672 if( find_option("internal","i",0)==0 ){
673 zDiffCmd = diff_command_external(memcmp(zCmd, "gdiff", nCmd)==0);
674 }
675 diffFlags = diff_options();
676 if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE;
677 if( g.argc>4 ) usage(mprintf("%s ?STASHID? ?DIFF-OPTIONS?", zCmd));
678 if( zDiffCmd ){
679
--- src/stash.c
+++ src/stash.c
@@ -332,52 +332,45 @@
332 isBin2 = fIncludeBinary ? 0 : looks_like_binary(&a);
333 diff_file_mem(&empty, &a, isBin1, isBin2, zNew, zDiffCmd,
334 zBinGlob, fIncludeBinary, diffFlags);
335 }else if( isRemoved ){
336 fossil_print("DELETE %s\n", zOrig);
337 diff_print_index(zNew, diffFlags);
338 isBin2 = 0;
339 if( fBaseline ){
340 content_get(rid, &a);
341 isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a);
342 diff_file_mem(&a, &empty, isBin1, isBin2, zOrig, zDiffCmd,
343 zBinGlob, fIncludeBinary, diffFlags);
344 }else{
345 }
346 }else{
347 Blob delta;
 
 
 
 
 
348 int isOrigLink = file_wd_islink(zOPath);
349 db_ephemeral_blob(&q, 6, &delta);
 
 
 
 
 
 
 
350 fossil_print("CHANGED %s\n", zNew);
351 if( !isOrigLink != !isLink ){
352 diff_print_index(zNew, diffFlags);
353 diff_print_filenames(zOrig, zNew, diffFlags);
354 printf(DIFF_CANNOT_COMPUTE_SYMLINK);
355 }else{
 
356 content_get(rid, &a);
357 blob_delta_apply(&a, &delta, &b);
358 isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a);
359 isBin2 = fIncludeBinary ? 0 : looks_like_binary(&b);
360 if( fBaseline ){
361 diff_file_mem(&a, &b, isBin1, isBin2, zNew,
362 zDiffCmd, zBinGlob, fIncludeBinary, diffFlags);
363 }else{
364 /*Diff with file on disk using fSwapDiff=1 to show the diff in the
365 same direction as if fBaseline=1.*/
366 diff_file(&b, isBin2, zOPath, zNew, zDiffCmd,
367 zBinGlob, fIncludeBinary, diffFlags, 1);
368 }
369 blob_reset(&a);
370 blob_reset(&b);
371 }
 
372 blob_reset(&delta);
373 }
374 }
375 db_finalize(&q);
376 }
@@ -433,12 +426,15 @@
426 **
427 ** List all changes sets currently stashed. Show information about
428 ** individual files in each changeset if -v or --verbose is used.
429 **
430 ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
431 ** fossil stash gshow|gcat ?STASHID? ?DIFF-OPTIONS?
432 **
433 ** Show the contents of a stash as a diff against it's baseline.
434 ** With gshow and gcat, gdiff-command is used instead of internal
435 ** diff logic.
436 **
437 ** fossil stash pop
438 ** fossil stash apply ?STASHID?
439 **
440 ** Apply STASHID or the most recently create stash to the current
@@ -460,18 +456,20 @@
456 **
457 ** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
458 ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
459 **
460 ** Show diffs of the current working directory and what that
461 ** directory would be if STASHID were applied. With gdiff,
462 ** gdiff-command is used instead of internal diff logic.
463 **
464 ** SUMMARY:
465 ** fossil stash
466 ** fossil stash save ?-m|--comment COMMENT? ?FILES...?
467 ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
468 ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
469 ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
470 ** fossil stash gshow|gcat ?STASHID? ?DIFF-OPTIONS?
471 ** fossil stash pop
472 ** fossil stash apply|goto ?STASHID?
473 ** fossil stash drop|rm ?STASHID? ?-a|--all?
474 ** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
475 ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
@@ -654,25 +652,30 @@
652 undo_finish();
653 }else
654 if( memcmp(zCmd, "diff", nCmd)==0
655 || memcmp(zCmd, "gdiff", nCmd)==0
656 || memcmp(zCmd, "show", nCmd)==0
657 || memcmp(zCmd, "gshow", nCmd)==0
658 || memcmp(zCmd, "cat", nCmd)==0
659 || memcmp(zCmd, "gcat", nCmd)==0
660 ){
661 const char *zDiffCmd = 0;
662 const char *zBinGlob = 0;
663 int fIncludeBinary = 0;
664 int fBaseline = 0;
665 u64 diffFlags;
666
667 if( strstr(zCmd,"show")!=0 || strstr(zCmd,"cat")!=0 ){
668 fBaseline = 1;
669 }
670 if( find_option("tk",0,0)!=0 ){
671 db_close(0);
672 diff_tk(fBaseline ? "stash show" : "stash diff", 3);
673 return;
674 }
675 if( find_option("internal","i",0)==0 ){
676 zDiffCmd = diff_command_external(zCmd[0]=='g');
677 }
678 diffFlags = diff_options();
679 if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE;
680 if( g.argc>4 ) usage(mprintf("%s ?STASHID? ?DIFF-OPTIONS?", zCmd));
681 if( zDiffCmd ){
682
+7 -2
--- src/stat.c
+++ src/stat.c
@@ -76,11 +76,11 @@
7676
style_submenu_element("URLs", "urllist");
7777
style_submenu_element("Schema", "repo_schema");
7878
style_submenu_element("Web-Cache", "cachestat");
7979
}
8080
style_submenu_element("Activity Reports", "reports");
81
- style_submenu_element("SHA1 Collisions", "hash-collisions");
81
+ style_submenu_element("Hash Collisions", "hash-collisions");
8282
if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){
8383
style_submenu_element("Table Sizes", "repo-tabsize");
8484
}
8585
if( g.perm.Admin || g.perm.Setup || db_get_boolean("test_env_enable",0) ){
8686
style_submenu_element("Environment", "test_env");
@@ -183,11 +183,16 @@
183183
@ (%h(RELEASE_VERSION)) <a href='version?verbose=1'>(details)</a>
184184
@ </td></tr>
185185
@ <tr><th>SQLite&nbsp;Version:</th><td>%.19s(sqlite3_sourceid())
186186
@ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))
187187
@ <a href='version?verbose=2'>(details)</a></td></tr>
188
- @ <tr><th>Schema&nbsp;Version:</th><td>%h(g.zAuxSchema)</td></tr>
188
+ if( g.eHashPolicy!=HPOLICY_AUTO ){
189
+ @ <tr><th>Schema&nbsp;Version:</th><td>%h(g.zAuxSchema),
190
+ @ %s(hpolicy_name())</td></tr>
191
+ }else{
192
+ @ <tr><th>Schema&nbsp;Version:</th><td>%h(g.zAuxSchema)</td></tr>
193
+ }
189194
@ <tr><th>Repository Rebuilt:</th><td>
190195
@ %h(db_get_mtime("rebuilt","%Y-%m-%d %H:%M:%S","Never"))
191196
@ By Fossil %h(db_get("rebuilt","Unknown"))</td></tr>
192197
@ <tr><th>Database&nbsp;Stats:</th><td>
193198
@ %d(db_int(0, "PRAGMA repository.page_count")) pages,
194199
--- src/stat.c
+++ src/stat.c
@@ -76,11 +76,11 @@
76 style_submenu_element("URLs", "urllist");
77 style_submenu_element("Schema", "repo_schema");
78 style_submenu_element("Web-Cache", "cachestat");
79 }
80 style_submenu_element("Activity Reports", "reports");
81 style_submenu_element("SHA1 Collisions", "hash-collisions");
82 if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){
83 style_submenu_element("Table Sizes", "repo-tabsize");
84 }
85 if( g.perm.Admin || g.perm.Setup || db_get_boolean("test_env_enable",0) ){
86 style_submenu_element("Environment", "test_env");
@@ -183,11 +183,16 @@
183 @ (%h(RELEASE_VERSION)) <a href='version?verbose=1'>(details)</a>
184 @ </td></tr>
185 @ <tr><th>SQLite&nbsp;Version:</th><td>%.19s(sqlite3_sourceid())
186 @ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))
187 @ <a href='version?verbose=2'>(details)</a></td></tr>
188 @ <tr><th>Schema&nbsp;Version:</th><td>%h(g.zAuxSchema)</td></tr>
 
 
 
 
 
189 @ <tr><th>Repository Rebuilt:</th><td>
190 @ %h(db_get_mtime("rebuilt","%Y-%m-%d %H:%M:%S","Never"))
191 @ By Fossil %h(db_get("rebuilt","Unknown"))</td></tr>
192 @ <tr><th>Database&nbsp;Stats:</th><td>
193 @ %d(db_int(0, "PRAGMA repository.page_count")) pages,
194
--- src/stat.c
+++ src/stat.c
@@ -76,11 +76,11 @@
76 style_submenu_element("URLs", "urllist");
77 style_submenu_element("Schema", "repo_schema");
78 style_submenu_element("Web-Cache", "cachestat");
79 }
80 style_submenu_element("Activity Reports", "reports");
81 style_submenu_element("Hash Collisions", "hash-collisions");
82 if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){
83 style_submenu_element("Table Sizes", "repo-tabsize");
84 }
85 if( g.perm.Admin || g.perm.Setup || db_get_boolean("test_env_enable",0) ){
86 style_submenu_element("Environment", "test_env");
@@ -183,11 +183,16 @@
183 @ (%h(RELEASE_VERSION)) <a href='version?verbose=1'>(details)</a>
184 @ </td></tr>
185 @ <tr><th>SQLite&nbsp;Version:</th><td>%.19s(sqlite3_sourceid())
186 @ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))
187 @ <a href='version?verbose=2'>(details)</a></td></tr>
188 if( g.eHashPolicy!=HPOLICY_AUTO ){
189 @ <tr><th>Schema&nbsp;Version:</th><td>%h(g.zAuxSchema),
190 @ %s(hpolicy_name())</td></tr>
191 }else{
192 @ <tr><th>Schema&nbsp;Version:</th><td>%h(g.zAuxSchema)</td></tr>
193 }
194 @ <tr><th>Repository Rebuilt:</th><td>
195 @ %h(db_get_mtime("rebuilt","%Y-%m-%d %H:%M:%S","Never"))
196 @ By Fossil %h(db_get("rebuilt","Unknown"))</td></tr>
197 @ <tr><th>Database&nbsp;Stats:</th><td>
198 @ %d(db_int(0, "PRAGMA repository.page_count")) pages,
199
+7 -2
--- src/stat.c
+++ src/stat.c
@@ -76,11 +76,11 @@
7676
style_submenu_element("URLs", "urllist");
7777
style_submenu_element("Schema", "repo_schema");
7878
style_submenu_element("Web-Cache", "cachestat");
7979
}
8080
style_submenu_element("Activity Reports", "reports");
81
- style_submenu_element("SHA1 Collisions", "hash-collisions");
81
+ style_submenu_element("Hash Collisions", "hash-collisions");
8282
if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){
8383
style_submenu_element("Table Sizes", "repo-tabsize");
8484
}
8585
if( g.perm.Admin || g.perm.Setup || db_get_boolean("test_env_enable",0) ){
8686
style_submenu_element("Environment", "test_env");
@@ -183,11 +183,16 @@
183183
@ (%h(RELEASE_VERSION)) <a href='version?verbose=1'>(details)</a>
184184
@ </td></tr>
185185
@ <tr><th>SQLite&nbsp;Version:</th><td>%.19s(sqlite3_sourceid())
186186
@ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))
187187
@ <a href='version?verbose=2'>(details)</a></td></tr>
188
- @ <tr><th>Schema&nbsp;Version:</th><td>%h(g.zAuxSchema)</td></tr>
188
+ if( g.eHashPolicy!=HPOLICY_AUTO ){
189
+ @ <tr><th>Schema&nbsp;Version:</th><td>%h(g.zAuxSchema),
190
+ @ %s(hpolicy_name())</td></tr>
191
+ }else{
192
+ @ <tr><th>Schema&nbsp;Version:</th><td>%h(g.zAuxSchema)</td></tr>
193
+ }
189194
@ <tr><th>Repository Rebuilt:</th><td>
190195
@ %h(db_get_mtime("rebuilt","%Y-%m-%d %H:%M:%S","Never"))
191196
@ By Fossil %h(db_get("rebuilt","Unknown"))</td></tr>
192197
@ <tr><th>Database&nbsp;Stats:</th><td>
193198
@ %d(db_int(0, "PRAGMA repository.page_count")) pages,
194199
--- src/stat.c
+++ src/stat.c
@@ -76,11 +76,11 @@
76 style_submenu_element("URLs", "urllist");
77 style_submenu_element("Schema", "repo_schema");
78 style_submenu_element("Web-Cache", "cachestat");
79 }
80 style_submenu_element("Activity Reports", "reports");
81 style_submenu_element("SHA1 Collisions", "hash-collisions");
82 if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){
83 style_submenu_element("Table Sizes", "repo-tabsize");
84 }
85 if( g.perm.Admin || g.perm.Setup || db_get_boolean("test_env_enable",0) ){
86 style_submenu_element("Environment", "test_env");
@@ -183,11 +183,16 @@
183 @ (%h(RELEASE_VERSION)) <a href='version?verbose=1'>(details)</a>
184 @ </td></tr>
185 @ <tr><th>SQLite&nbsp;Version:</th><td>%.19s(sqlite3_sourceid())
186 @ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))
187 @ <a href='version?verbose=2'>(details)</a></td></tr>
188 @ <tr><th>Schema&nbsp;Version:</th><td>%h(g.zAuxSchema)</td></tr>
 
 
 
 
 
189 @ <tr><th>Repository Rebuilt:</th><td>
190 @ %h(db_get_mtime("rebuilt","%Y-%m-%d %H:%M:%S","Never"))
191 @ By Fossil %h(db_get("rebuilt","Unknown"))</td></tr>
192 @ <tr><th>Database&nbsp;Stats:</th><td>
193 @ %d(db_int(0, "PRAGMA repository.page_count")) pages,
194
--- src/stat.c
+++ src/stat.c
@@ -76,11 +76,11 @@
76 style_submenu_element("URLs", "urllist");
77 style_submenu_element("Schema", "repo_schema");
78 style_submenu_element("Web-Cache", "cachestat");
79 }
80 style_submenu_element("Activity Reports", "reports");
81 style_submenu_element("Hash Collisions", "hash-collisions");
82 if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){
83 style_submenu_element("Table Sizes", "repo-tabsize");
84 }
85 if( g.perm.Admin || g.perm.Setup || db_get_boolean("test_env_enable",0) ){
86 style_submenu_element("Environment", "test_env");
@@ -183,11 +183,16 @@
183 @ (%h(RELEASE_VERSION)) <a href='version?verbose=1'>(details)</a>
184 @ </td></tr>
185 @ <tr><th>SQLite&nbsp;Version:</th><td>%.19s(sqlite3_sourceid())
186 @ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))
187 @ <a href='version?verbose=2'>(details)</a></td></tr>
188 if( g.eHashPolicy!=HPOLICY_AUTO ){
189 @ <tr><th>Schema&nbsp;Version:</th><td>%h(g.zAuxSchema),
190 @ %s(hpolicy_name())</td></tr>
191 }else{
192 @ <tr><th>Schema&nbsp;Version:</th><td>%h(g.zAuxSchema)</td></tr>
193 }
194 @ <tr><th>Repository Rebuilt:</th><td>
195 @ %h(db_get_mtime("rebuilt","%Y-%m-%d %H:%M:%S","Never"))
196 @ By Fossil %h(db_get("rebuilt","Unknown"))</td></tr>
197 @ <tr><th>Database&nbsp;Stats:</th><td>
198 @ %d(db_int(0, "PRAGMA repository.page_count")) pages,
199
+1 -1
--- src/tag.c
+++ src/tag.c
@@ -627,11 +627,11 @@
627627
blob_init(&value, 0, 0);
628628
for(i=3; i<g.argc; i++){
629629
int pid = name_to_typed_rid(g.argv[i], "ci");
630630
if( i>3 ) blob_append(&value, " ", 1);
631631
zUuid = rid_to_uuid(pid);
632
- blob_append(&value, zUuid, UUID_SIZE);
632
+ blob_append(&value, zUuid, strlen(zUuid));
633633
fossil_free(zUuid);
634634
}
635635
if( bTest && !dryRun ){
636636
tag_insert("parent", 1, blob_str(&value), -1, 0.0, rid);
637637
}else{
638638
--- src/tag.c
+++ src/tag.c
@@ -627,11 +627,11 @@
627 blob_init(&value, 0, 0);
628 for(i=3; i<g.argc; i++){
629 int pid = name_to_typed_rid(g.argv[i], "ci");
630 if( i>3 ) blob_append(&value, " ", 1);
631 zUuid = rid_to_uuid(pid);
632 blob_append(&value, zUuid, UUID_SIZE);
633 fossil_free(zUuid);
634 }
635 if( bTest && !dryRun ){
636 tag_insert("parent", 1, blob_str(&value), -1, 0.0, rid);
637 }else{
638
--- src/tag.c
+++ src/tag.c
@@ -627,11 +627,11 @@
627 blob_init(&value, 0, 0);
628 for(i=3; i<g.argc; i++){
629 int pid = name_to_typed_rid(g.argv[i], "ci");
630 if( i>3 ) blob_append(&value, " ", 1);
631 zUuid = rid_to_uuid(pid);
632 blob_append(&value, zUuid, strlen(zUuid));
633 fossil_free(zUuid);
634 }
635 if( bTest && !dryRun ){
636 tag_insert("parent", 1, blob_str(&value), -1, 0.0, rid);
637 }else{
638
+2 -6
--- src/tar.c
+++ src/tar.c
@@ -483,11 +483,11 @@
483483
content_get(rid, &mfile);
484484
if( blob_size(&mfile)==0 ){
485485
blob_zero(pTar);
486486
return;
487487
}
488
- blob_zero(&hash);
488
+ blob_set_dynamic(&hash, rid_to_uuid(rid));
489489
blob_zero(&filename);
490490
491491
if( zDir && zDir[0] ){
492492
blob_appendf(&filename, "%s/", zDir);
493493
}
@@ -520,13 +520,10 @@
520520
if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){
521521
if( eflg & MFESTFLG_RAW ){
522522
blob_append(&filename, "manifest", -1);
523523
zName = blob_str(&filename);
524524
}
525
- if( eflg & MFESTFLG_UUID ){
526
- sha1sum_blob(&mfile, &hash);
527
- }
528525
if( eflg & MFESTFLG_RAW ) {
529526
sterilize_manifest(&mfile);
530527
tar_add_file(zName, &mfile, 0, mTime);
531528
}
532529
}
@@ -535,11 +532,10 @@
535532
blob_append(&hash, "\n", 1);
536533
blob_resize(&filename, nPrefix);
537534
blob_append(&filename, "manifest.uuid", -1);
538535
zName = blob_str(&filename);
539536
tar_add_file(zName, &hash, 0, mTime);
540
- blob_reset(&hash);
541537
}
542538
if( eflg & MFESTFLG_TAGS ){
543539
Blob tagslist;
544540
blob_zero(&tagslist);
545541
get_checkin_taglist(rid, &tagslist);
@@ -564,19 +560,19 @@
564560
tar_add_file(zName, &file, manifest_file_mperm(pFile), mTime);
565561
blob_reset(&file);
566562
}
567563
}
568564
}else{
569
- sha1sum_blob(&mfile, &hash);
570565
blob_append(&filename, blob_str(&hash), 16);
571566
zName = blob_str(&filename);
572567
mTime = db_int64(0, "SELECT (julianday('now') - 2440587.5)*86400.0;");
573568
tar_begin(mTime);
574569
tar_add_file(zName, &mfile, 0, mTime);
575570
}
576571
manifest_destroy(pManifest);
577572
blob_reset(&mfile);
573
+ blob_reset(&hash);
578574
blob_reset(&filename);
579575
tar_finish(pTar);
580576
}
581577
582578
/*
583579
--- src/tar.c
+++ src/tar.c
@@ -483,11 +483,11 @@
483 content_get(rid, &mfile);
484 if( blob_size(&mfile)==0 ){
485 blob_zero(pTar);
486 return;
487 }
488 blob_zero(&hash);
489 blob_zero(&filename);
490
491 if( zDir && zDir[0] ){
492 blob_appendf(&filename, "%s/", zDir);
493 }
@@ -520,13 +520,10 @@
520 if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){
521 if( eflg & MFESTFLG_RAW ){
522 blob_append(&filename, "manifest", -1);
523 zName = blob_str(&filename);
524 }
525 if( eflg & MFESTFLG_UUID ){
526 sha1sum_blob(&mfile, &hash);
527 }
528 if( eflg & MFESTFLG_RAW ) {
529 sterilize_manifest(&mfile);
530 tar_add_file(zName, &mfile, 0, mTime);
531 }
532 }
@@ -535,11 +532,10 @@
535 blob_append(&hash, "\n", 1);
536 blob_resize(&filename, nPrefix);
537 blob_append(&filename, "manifest.uuid", -1);
538 zName = blob_str(&filename);
539 tar_add_file(zName, &hash, 0, mTime);
540 blob_reset(&hash);
541 }
542 if( eflg & MFESTFLG_TAGS ){
543 Blob tagslist;
544 blob_zero(&tagslist);
545 get_checkin_taglist(rid, &tagslist);
@@ -564,19 +560,19 @@
564 tar_add_file(zName, &file, manifest_file_mperm(pFile), mTime);
565 blob_reset(&file);
566 }
567 }
568 }else{
569 sha1sum_blob(&mfile, &hash);
570 blob_append(&filename, blob_str(&hash), 16);
571 zName = blob_str(&filename);
572 mTime = db_int64(0, "SELECT (julianday('now') - 2440587.5)*86400.0;");
573 tar_begin(mTime);
574 tar_add_file(zName, &mfile, 0, mTime);
575 }
576 manifest_destroy(pManifest);
577 blob_reset(&mfile);
 
578 blob_reset(&filename);
579 tar_finish(pTar);
580 }
581
582 /*
583
--- src/tar.c
+++ src/tar.c
@@ -483,11 +483,11 @@
483 content_get(rid, &mfile);
484 if( blob_size(&mfile)==0 ){
485 blob_zero(pTar);
486 return;
487 }
488 blob_set_dynamic(&hash, rid_to_uuid(rid));
489 blob_zero(&filename);
490
491 if( zDir && zDir[0] ){
492 blob_appendf(&filename, "%s/", zDir);
493 }
@@ -520,13 +520,10 @@
520 if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){
521 if( eflg & MFESTFLG_RAW ){
522 blob_append(&filename, "manifest", -1);
523 zName = blob_str(&filename);
524 }
 
 
 
525 if( eflg & MFESTFLG_RAW ) {
526 sterilize_manifest(&mfile);
527 tar_add_file(zName, &mfile, 0, mTime);
528 }
529 }
@@ -535,11 +532,10 @@
532 blob_append(&hash, "\n", 1);
533 blob_resize(&filename, nPrefix);
534 blob_append(&filename, "manifest.uuid", -1);
535 zName = blob_str(&filename);
536 tar_add_file(zName, &hash, 0, mTime);
 
537 }
538 if( eflg & MFESTFLG_TAGS ){
539 Blob tagslist;
540 blob_zero(&tagslist);
541 get_checkin_taglist(rid, &tagslist);
@@ -564,19 +560,19 @@
560 tar_add_file(zName, &file, manifest_file_mperm(pFile), mTime);
561 blob_reset(&file);
562 }
563 }
564 }else{
 
565 blob_append(&filename, blob_str(&hash), 16);
566 zName = blob_str(&filename);
567 mTime = db_int64(0, "SELECT (julianday('now') - 2440587.5)*86400.0;");
568 tar_begin(mTime);
569 tar_add_file(zName, &mfile, 0, mTime);
570 }
571 manifest_destroy(pManifest);
572 blob_reset(&mfile);
573 blob_reset(&hash);
574 blob_reset(&filename);
575 tar_finish(pTar);
576 }
577
578 /*
579
+2 -2
--- src/timeline.c
+++ src/timeline.c
@@ -723,11 +723,11 @@
723723
** mi: "merge-in". An array of integer rail positions from which
724724
** merge arrows should be drawn into this node. If the value is
725725
** negative, then the rail position is the absolute value of mi[]
726726
** and a thin merge-arrow descender is drawn to the bottom of
727727
** the screen.
728
- ** h: The SHA1 hash of the object being graphed
728
+ ** h: The artifact hash of the object being graphed
729729
*/
730730
cgi_printf("var rowinfo = [\n");
731731
for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
732732
cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,f:%d,au:",
733733
pRow->idx, /* id */
@@ -1461,11 +1461,11 @@
14611461
** v Show details of files changed
14621462
** f=CHECKIN Show family (immediate parents and children) of CHECKIN
14631463
** from=CHECKIN Path from...
14641464
** to=CHECKIN ... to this
14651465
** shortest ... show only the shortest path
1466
-** uf=FILE_SHA1 Show only check-ins that contain the given file version
1466
+** uf=FILE_HASH Show only check-ins that contain the given file version
14671467
** chng=GLOBLIST Show only check-ins that involve changes to a file whose
14681468
** name matches one of the comma-separate GLOBLIST
14691469
** brbg Background color from branch name
14701470
** ubg Background color from user
14711471
** namechng Show only check-ins that have filename changes
14721472
--- src/timeline.c
+++ src/timeline.c
@@ -723,11 +723,11 @@
723 ** mi: "merge-in". An array of integer rail positions from which
724 ** merge arrows should be drawn into this node. If the value is
725 ** negative, then the rail position is the absolute value of mi[]
726 ** and a thin merge-arrow descender is drawn to the bottom of
727 ** the screen.
728 ** h: The SHA1 hash of the object being graphed
729 */
730 cgi_printf("var rowinfo = [\n");
731 for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
732 cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,f:%d,au:",
733 pRow->idx, /* id */
@@ -1461,11 +1461,11 @@
1461 ** v Show details of files changed
1462 ** f=CHECKIN Show family (immediate parents and children) of CHECKIN
1463 ** from=CHECKIN Path from...
1464 ** to=CHECKIN ... to this
1465 ** shortest ... show only the shortest path
1466 ** uf=FILE_SHA1 Show only check-ins that contain the given file version
1467 ** chng=GLOBLIST Show only check-ins that involve changes to a file whose
1468 ** name matches one of the comma-separate GLOBLIST
1469 ** brbg Background color from branch name
1470 ** ubg Background color from user
1471 ** namechng Show only check-ins that have filename changes
1472
--- src/timeline.c
+++ src/timeline.c
@@ -723,11 +723,11 @@
723 ** mi: "merge-in". An array of integer rail positions from which
724 ** merge arrows should be drawn into this node. If the value is
725 ** negative, then the rail position is the absolute value of mi[]
726 ** and a thin merge-arrow descender is drawn to the bottom of
727 ** the screen.
728 ** h: The artifact hash of the object being graphed
729 */
730 cgi_printf("var rowinfo = [\n");
731 for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
732 cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,f:%d,au:",
733 pRow->idx, /* id */
@@ -1461,11 +1461,11 @@
1461 ** v Show details of files changed
1462 ** f=CHECKIN Show family (immediate parents and children) of CHECKIN
1463 ** from=CHECKIN Path from...
1464 ** to=CHECKIN ... to this
1465 ** shortest ... show only the shortest path
1466 ** uf=FILE_HASH Show only check-ins that contain the given file version
1467 ** chng=GLOBLIST Show only check-ins that involve changes to a file whose
1468 ** name matches one of the comma-separate GLOBLIST
1469 ** brbg Background color from branch name
1470 ** ubg Background color from user
1471 ** namechng Show only check-ins that have filename changes
1472
--- src/unversioned.c
+++ src/unversioned.c
@@ -456,11 +456,11 @@
456456
** Query parameters:
457457
**
458458
** byage=1 Order the initial display be decreasing age
459459
** showdel=0 Show deleted files
460460
*/
461
-void uvstat_page(void){
461
+void uvlist_page(void){
462462
Stmt q;
463463
sqlite3_int64 iNow;
464464
sqlite3_int64 iTotalSz = 0;
465465
int cnt = 0;
466466
int n = 0;
@@ -554,5 +554,62 @@
554554
}else{
555555
@ No unversioned files on this server.
556556
}
557557
style_footer();
558558
}
559
+
560
+/*
561
+** WEBPAGE: juvlist
562
+**
563
+** Return a complete list of unversioned files as JSON. The JSON
564
+** looks like this:
565
+**
566
+** [{"name":NAME,
567
+** "mtime":MTIME,
568
+** "hash":HASH,
569
+** "size":SIZE,
570
+** "user":USER}]
571
+*/
572
+void uvlist_json_page(void){
573
+ Stmt q;
574
+ char *zSep = "[";
575
+ Blob json;
576
+
577
+ login_check_credentials();
578
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
579
+ cgi_set_content_type("text/json");
580
+ if( !db_table_exists("repository","unversioned") ){
581
+ blob_init(&json, "[]", -1);
582
+ cgi_set_content(&json);
583
+ return;
584
+ }
585
+ blob_init(&json, 0, 0);
586
+ db_prepare(&q,
587
+ "SELECT"
588
+ " name,"
589
+ " mtime,"
590
+ " hash,"
591
+ " sz,"
592
+ " (SELECT login FROM rcvfrom, user"
593
+ " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid)"
594
+ " FROM unversioned WHERE hash IS NOT NULL"
595
+ );
596
+ while( db_step(&q)==SQLITE_ROW ){
597
+ const char *zName = db_column_text(&q, 0);
598
+ sqlite3_int64 mtime = db_column_int(&q, 1);
599
+ const char *zHash = db_column_text(&q, 2);
600
+ int fullSize = db_column_int(&q, 3);
601
+ const char *zLogin = db_column_text(&q, 4);
602
+ if( zLogin==0 ) zLogin = "";
603
+ blob_appendf(&json, "%s{\"name\":\"", zSep);
604
+ zSep = ",\n ";
605
+ blob_append_json_string(&json, zName);
606
+ blob_appendf(&json, "\",\n \"mtime\":%lld,\n \"hash\":\"", mtime);
607
+ blob_append_json_string(&json, zHash);
608
+ blob_appendf(&json, "\",\n \"size\":%d,\n \"user\":\"", fullSize);
609
+ blob_append_json_string(&json, zLogin);
610
+ blob_appendf(&json, "\"}");
611
+ }
612
+ db_finalize(&q);
613
+ blob_appendf(&json,"]\n");
614
+ cgi_set_content(&json);
615
+}
559616
--- src/unversioned.c
+++ src/unversioned.c
@@ -456,11 +456,11 @@
456 ** Query parameters:
457 **
458 ** byage=1 Order the initial display be decreasing age
459 ** showdel=0 Show deleted files
460 */
461 void uvstat_page(void){
462 Stmt q;
463 sqlite3_int64 iNow;
464 sqlite3_int64 iTotalSz = 0;
465 int cnt = 0;
466 int n = 0;
@@ -554,5 +554,62 @@
554 }else{
555 @ No unversioned files on this server.
556 }
557 style_footer();
558 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
559
--- src/unversioned.c
+++ src/unversioned.c
@@ -456,11 +456,11 @@
456 ** Query parameters:
457 **
458 ** byage=1 Order the initial display be decreasing age
459 ** showdel=0 Show deleted files
460 */
461 void uvlist_page(void){
462 Stmt q;
463 sqlite3_int64 iNow;
464 sqlite3_int64 iTotalSz = 0;
465 int cnt = 0;
466 int n = 0;
@@ -554,5 +554,62 @@
554 }else{
555 @ No unversioned files on this server.
556 }
557 style_footer();
558 }
559
560 /*
561 ** WEBPAGE: juvlist
562 **
563 ** Return a complete list of unversioned files as JSON. The JSON
564 ** looks like this:
565 **
566 ** [{"name":NAME,
567 ** "mtime":MTIME,
568 ** "hash":HASH,
569 ** "size":SIZE,
570 ** "user":USER}]
571 */
572 void uvlist_json_page(void){
573 Stmt q;
574 char *zSep = "[";
575 Blob json;
576
577 login_check_credentials();
578 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
579 cgi_set_content_type("text/json");
580 if( !db_table_exists("repository","unversioned") ){
581 blob_init(&json, "[]", -1);
582 cgi_set_content(&json);
583 return;
584 }
585 blob_init(&json, 0, 0);
586 db_prepare(&q,
587 "SELECT"
588 " name,"
589 " mtime,"
590 " hash,"
591 " sz,"
592 " (SELECT login FROM rcvfrom, user"
593 " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid)"
594 " FROM unversioned WHERE hash IS NOT NULL"
595 );
596 while( db_step(&q)==SQLITE_ROW ){
597 const char *zName = db_column_text(&q, 0);
598 sqlite3_int64 mtime = db_column_int(&q, 1);
599 const char *zHash = db_column_text(&q, 2);
600 int fullSize = db_column_int(&q, 3);
601 const char *zLogin = db_column_text(&q, 4);
602 if( zLogin==0 ) zLogin = "";
603 blob_appendf(&json, "%s{\"name\":\"", zSep);
604 zSep = ",\n ";
605 blob_append_json_string(&json, zName);
606 blob_appendf(&json, "\",\n \"mtime\":%lld,\n \"hash\":\"", mtime);
607 blob_append_json_string(&json, zHash);
608 blob_appendf(&json, "\",\n \"size\":%d,\n \"user\":\"", fullSize);
609 blob_append_json_string(&json, zLogin);
610 blob_appendf(&json, "\"}");
611 }
612 db_finalize(&q);
613 blob_appendf(&json,"]\n");
614 cgi_set_content(&json);
615 }
616
+6 -8
--- src/verify.c
+++ src/verify.c
@@ -34,27 +34,25 @@
3434
**
3535
** Panic if anything goes wrong. If this procedure returns it means
3636
** that everything is OK.
3737
*/
3838
static void verify_rid(int rid){
39
- Blob uuid, hash, content;
39
+ Blob uuid, content;
4040
if( content_size(rid, 0)<0 ){
4141
return; /* No way to verify phantoms */
4242
}
4343
blob_zero(&uuid);
4444
db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid);
45
- if( blob_size(&uuid)!=UUID_SIZE ){
45
+ if( !hname_validate(blob_buffer(&uuid), blob_size(&uuid)) ){
4646
fossil_fatal("not a valid rid: %d", rid);
4747
}
4848
if( content_get(rid, &content) ){
49
- sha1sum_blob(&content, &hash);
50
- blob_reset(&content);
51
- if( blob_compare(&uuid, &hash) ){
52
- fossil_fatal("hash of rid %d (%b) does not match its uuid (%b)",
53
- rid, &hash, &uuid);
49
+ if( !hname_verify_hash(&content, blob_buffer(&uuid), blob_size(&uuid)) ){
50
+ fossil_fatal("hash of rid %d does not match its uuid (%b)",
51
+ rid, &uuid);
5452
}
55
- blob_reset(&hash);
53
+ blob_reset(&content);
5654
}
5755
blob_reset(&uuid);
5856
}
5957
6058
/*
6159
--- src/verify.c
+++ src/verify.c
@@ -34,27 +34,25 @@
34 **
35 ** Panic if anything goes wrong. If this procedure returns it means
36 ** that everything is OK.
37 */
38 static void verify_rid(int rid){
39 Blob uuid, hash, content;
40 if( content_size(rid, 0)<0 ){
41 return; /* No way to verify phantoms */
42 }
43 blob_zero(&uuid);
44 db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid);
45 if( blob_size(&uuid)!=UUID_SIZE ){
46 fossil_fatal("not a valid rid: %d", rid);
47 }
48 if( content_get(rid, &content) ){
49 sha1sum_blob(&content, &hash);
50 blob_reset(&content);
51 if( blob_compare(&uuid, &hash) ){
52 fossil_fatal("hash of rid %d (%b) does not match its uuid (%b)",
53 rid, &hash, &uuid);
54 }
55 blob_reset(&hash);
56 }
57 blob_reset(&uuid);
58 }
59
60 /*
61
--- src/verify.c
+++ src/verify.c
@@ -34,27 +34,25 @@
34 **
35 ** Panic if anything goes wrong. If this procedure returns it means
36 ** that everything is OK.
37 */
38 static void verify_rid(int rid){
39 Blob uuid, content;
40 if( content_size(rid, 0)<0 ){
41 return; /* No way to verify phantoms */
42 }
43 blob_zero(&uuid);
44 db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid);
45 if( !hname_validate(blob_buffer(&uuid), blob_size(&uuid)) ){
46 fossil_fatal("not a valid rid: %d", rid);
47 }
48 if( content_get(rid, &content) ){
49 if( !hname_verify_hash(&content, blob_buffer(&uuid), blob_size(&uuid)) ){
50 fossil_fatal("hash of rid %d does not match its uuid (%b)",
51 rid, &uuid);
 
 
52 }
53 blob_reset(&content);
54 }
55 blob_reset(&uuid);
56 }
57
58 /*
59
+19 -30
--- src/vfile.c
+++ src/vfile.c
@@ -21,12 +21,12 @@
2121
#include "vfile.h"
2222
#include <assert.h>
2323
#include <sys/types.h>
2424
2525
/*
26
-** The input is guaranteed to be a 40-character well-formed UUID.
27
-** Find its rid.
26
+** The input is guaranteed to be a 40- or 64-character well-formed
27
+** artifact hash. Find its rid.
2828
*/
2929
int fast_uuid_to_rid(const char *zUuid){
3030
static Stmt q;
3131
int rid;
3232
db_static_prepare(&q, "SELECT rid FROM blob WHERE uuid=:uuid");
@@ -51,17 +51,17 @@
5151
** create a phantom record. A private phantom is created for 2 and
5252
** a public phantom is created for 1.
5353
*/
5454
int uuid_to_rid(const char *zUuid, int phantomize){
5555
int rid, sz;
56
- char z[UUID_SIZE+1];
56
+ char z[HNAME_MAX+1];
5757
5858
sz = strlen(zUuid);
59
- if( sz!=UUID_SIZE || !validate16(zUuid, sz) ){
60
- return 0;
59
+ if( !hname_validate(zUuid, sz) ){
60
+ return 0; /* Not a valid hash */
6161
}
62
- memcpy(z, zUuid, UUID_SIZE+1);
62
+ memcpy(z, zUuid, sz+1);
6363
canonical16(z, sz);
6464
rid = fast_uuid_to_rid(z);
6565
if( rid==0 && phantomize ){
6666
rid = content_new(zUuid, phantomize-1);
6767
}
@@ -130,11 +130,11 @@
130130
/*
131131
** The cksigFlags parameter to vfile_check_signature() is an OR-ed
132132
** combination of the following bits:
133133
*/
134134
#define CKSIG_ENOTFILE 0x001 /* non-file FS objects throw an error */
135
-#define CKSIG_SHA1 0x002 /* Verify file content using sha1sum */
135
+#define CKSIG_HASH 0x002 /* Verify file content using hashing */
136136
#define CKSIG_SETMTIME 0x004 /* Set mtime to last check-out time */
137137
138138
#endif /* INTERFACE */
139139
140140
/*
@@ -159,12 +159,12 @@
159159
**
160160
** If the size of the file has changed, then we always know that the file
161161
** changed without having to look at the mtime or on-disk content.
162162
**
163163
** The mtime of the file is only a factor if the mtime-changes setting
164
-** is false and the useSha1sum flag is false. If the mtime-changes
165
-** setting is true (or undefined - it defaults to true) or if useSha1sum
164
+** is false and the CKSIG_HASH flag is false. If the mtime-changes
165
+** setting is true (or undefined - it defaults to true) or if CKSIG_HASH
166166
** is true, then we do not trust the mtime and will examine the on-disk
167167
** content to determine if a file really is the same.
168168
**
169169
** If the mtime is used, it is used only to determine if files are the same.
170170
** If the mtime of a file has changed, we still examine the on-disk content
@@ -171,12 +171,11 @@
171171
** to see whether or not the edit was a null-edit.
172172
*/
173173
void vfile_check_signature(int vid, unsigned int cksigFlags){
174174
int nErr = 0;
175175
Stmt q;
176
- Blob fileCksum, origCksum;
177
- int useMtime = (cksigFlags & CKSIG_SHA1)==0
176
+ int useMtime = (cksigFlags & CKSIG_HASH)==0
178177
&& db_get_boolean("mtime-changes", 1);
179178
180179
db_begin_transaction();
181180
db_prepare(&q, "SELECT id, %Q || pathname,"
182181
" vfile.mrid, deleted, chnged, uuid, size, mtime,"
@@ -222,40 +221,30 @@
222221
chnged = 1;
223222
}
224223
if( origSize!=currentSize ){
225224
if( chnged!=1 ){
226225
/* A file size change is definitive - the file has changed. No
227
- ** need to check the mtime or sha1sum */
226
+ ** need to check the mtime or hash */
228227
chnged = 1;
229228
}
230229
}else if( chnged==1 && rid!=0 && !isDeleted ){
231230
/* File is believed to have changed but it is the same size.
232231
** Double check that it really has changed by looking at content. */
232
+ const char *zUuid = db_column_text(&q, 5);
233
+ int nUuid = db_column_bytes(&q, 5);
233234
assert( origSize==currentSize );
234
- db_ephemeral_blob(&q, 5, &origCksum);
235
- if( sha1sum_file(zName, &fileCksum) ){
236
- blob_zero(&fileCksum);
237
- }
238
- if( blob_compare(&fileCksum, &origCksum)==0 ) chnged = 0;
239
- blob_reset(&origCksum);
240
- blob_reset(&fileCksum);
235
+ if( hname_verify_file_hash(zName, zUuid, nUuid) ) chnged = 0;
241236
}else if( (chnged==0 || chnged==2 || chnged==4)
242237
&& (useMtime==0 || currentMtime!=oldMtime) ){
243238
/* For files that were formerly believed to be unchanged or that were
244239
** changed by merging, if their mtime changes, or unconditionally
245
- ** if --sha1sum is used, check to see if they have been edited by
246
- ** looking at their SHA1 sum */
240
+ ** if --hash is used, check to see if they have been edited by
241
+ ** looking at their artifact hashes */
242
+ const char *zUuid = db_column_text(&q, 5);
243
+ int nUuid = db_column_bytes(&q, 5);
247244
assert( origSize==currentSize );
248
- db_ephemeral_blob(&q, 5, &origCksum);
249
- if( sha1sum_file(zName, &fileCksum) ){
250
- blob_zero(&fileCksum);
251
- }
252
- if( blob_compare(&fileCksum, &origCksum) ){
253
- chnged = 1;
254
- }
255
- blob_reset(&origCksum);
256
- blob_reset(&fileCksum);
245
+ if( !hname_verify_file_hash(zName, zUuid, nUuid) ) chnged = 1;
257246
}
258247
if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2 || chnged==4) ){
259248
i64 desiredMtime;
260249
if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){
261250
if( currentMtime!=desiredMtime ){
262251
--- src/vfile.c
+++ src/vfile.c
@@ -21,12 +21,12 @@
21 #include "vfile.h"
22 #include <assert.h>
23 #include <sys/types.h>
24
25 /*
26 ** The input is guaranteed to be a 40-character well-formed UUID.
27 ** Find its rid.
28 */
29 int fast_uuid_to_rid(const char *zUuid){
30 static Stmt q;
31 int rid;
32 db_static_prepare(&q, "SELECT rid FROM blob WHERE uuid=:uuid");
@@ -51,17 +51,17 @@
51 ** create a phantom record. A private phantom is created for 2 and
52 ** a public phantom is created for 1.
53 */
54 int uuid_to_rid(const char *zUuid, int phantomize){
55 int rid, sz;
56 char z[UUID_SIZE+1];
57
58 sz = strlen(zUuid);
59 if( sz!=UUID_SIZE || !validate16(zUuid, sz) ){
60 return 0;
61 }
62 memcpy(z, zUuid, UUID_SIZE+1);
63 canonical16(z, sz);
64 rid = fast_uuid_to_rid(z);
65 if( rid==0 && phantomize ){
66 rid = content_new(zUuid, phantomize-1);
67 }
@@ -130,11 +130,11 @@
130 /*
131 ** The cksigFlags parameter to vfile_check_signature() is an OR-ed
132 ** combination of the following bits:
133 */
134 #define CKSIG_ENOTFILE 0x001 /* non-file FS objects throw an error */
135 #define CKSIG_SHA1 0x002 /* Verify file content using sha1sum */
136 #define CKSIG_SETMTIME 0x004 /* Set mtime to last check-out time */
137
138 #endif /* INTERFACE */
139
140 /*
@@ -159,12 +159,12 @@
159 **
160 ** If the size of the file has changed, then we always know that the file
161 ** changed without having to look at the mtime or on-disk content.
162 **
163 ** The mtime of the file is only a factor if the mtime-changes setting
164 ** is false and the useSha1sum flag is false. If the mtime-changes
165 ** setting is true (or undefined - it defaults to true) or if useSha1sum
166 ** is true, then we do not trust the mtime and will examine the on-disk
167 ** content to determine if a file really is the same.
168 **
169 ** If the mtime is used, it is used only to determine if files are the same.
170 ** If the mtime of a file has changed, we still examine the on-disk content
@@ -171,12 +171,11 @@
171 ** to see whether or not the edit was a null-edit.
172 */
173 void vfile_check_signature(int vid, unsigned int cksigFlags){
174 int nErr = 0;
175 Stmt q;
176 Blob fileCksum, origCksum;
177 int useMtime = (cksigFlags & CKSIG_SHA1)==0
178 && db_get_boolean("mtime-changes", 1);
179
180 db_begin_transaction();
181 db_prepare(&q, "SELECT id, %Q || pathname,"
182 " vfile.mrid, deleted, chnged, uuid, size, mtime,"
@@ -222,40 +221,30 @@
222 chnged = 1;
223 }
224 if( origSize!=currentSize ){
225 if( chnged!=1 ){
226 /* A file size change is definitive - the file has changed. No
227 ** need to check the mtime or sha1sum */
228 chnged = 1;
229 }
230 }else if( chnged==1 && rid!=0 && !isDeleted ){
231 /* File is believed to have changed but it is the same size.
232 ** Double check that it really has changed by looking at content. */
 
 
233 assert( origSize==currentSize );
234 db_ephemeral_blob(&q, 5, &origCksum);
235 if( sha1sum_file(zName, &fileCksum) ){
236 blob_zero(&fileCksum);
237 }
238 if( blob_compare(&fileCksum, &origCksum)==0 ) chnged = 0;
239 blob_reset(&origCksum);
240 blob_reset(&fileCksum);
241 }else if( (chnged==0 || chnged==2 || chnged==4)
242 && (useMtime==0 || currentMtime!=oldMtime) ){
243 /* For files that were formerly believed to be unchanged or that were
244 ** changed by merging, if their mtime changes, or unconditionally
245 ** if --sha1sum is used, check to see if they have been edited by
246 ** looking at their SHA1 sum */
 
 
247 assert( origSize==currentSize );
248 db_ephemeral_blob(&q, 5, &origCksum);
249 if( sha1sum_file(zName, &fileCksum) ){
250 blob_zero(&fileCksum);
251 }
252 if( blob_compare(&fileCksum, &origCksum) ){
253 chnged = 1;
254 }
255 blob_reset(&origCksum);
256 blob_reset(&fileCksum);
257 }
258 if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2 || chnged==4) ){
259 i64 desiredMtime;
260 if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){
261 if( currentMtime!=desiredMtime ){
262
--- src/vfile.c
+++ src/vfile.c
@@ -21,12 +21,12 @@
21 #include "vfile.h"
22 #include <assert.h>
23 #include <sys/types.h>
24
25 /*
26 ** The input is guaranteed to be a 40- or 64-character well-formed
27 ** artifact hash. Find its rid.
28 */
29 int fast_uuid_to_rid(const char *zUuid){
30 static Stmt q;
31 int rid;
32 db_static_prepare(&q, "SELECT rid FROM blob WHERE uuid=:uuid");
@@ -51,17 +51,17 @@
51 ** create a phantom record. A private phantom is created for 2 and
52 ** a public phantom is created for 1.
53 */
54 int uuid_to_rid(const char *zUuid, int phantomize){
55 int rid, sz;
56 char z[HNAME_MAX+1];
57
58 sz = strlen(zUuid);
59 if( !hname_validate(zUuid, sz) ){
60 return 0; /* Not a valid hash */
61 }
62 memcpy(z, zUuid, sz+1);
63 canonical16(z, sz);
64 rid = fast_uuid_to_rid(z);
65 if( rid==0 && phantomize ){
66 rid = content_new(zUuid, phantomize-1);
67 }
@@ -130,11 +130,11 @@
130 /*
131 ** The cksigFlags parameter to vfile_check_signature() is an OR-ed
132 ** combination of the following bits:
133 */
134 #define CKSIG_ENOTFILE 0x001 /* non-file FS objects throw an error */
135 #define CKSIG_HASH 0x002 /* Verify file content using hashing */
136 #define CKSIG_SETMTIME 0x004 /* Set mtime to last check-out time */
137
138 #endif /* INTERFACE */
139
140 /*
@@ -159,12 +159,12 @@
159 **
160 ** If the size of the file has changed, then we always know that the file
161 ** changed without having to look at the mtime or on-disk content.
162 **
163 ** The mtime of the file is only a factor if the mtime-changes setting
164 ** is false and the CKSIG_HASH flag is false. If the mtime-changes
165 ** setting is true (or undefined - it defaults to true) or if CKSIG_HASH
166 ** is true, then we do not trust the mtime and will examine the on-disk
167 ** content to determine if a file really is the same.
168 **
169 ** If the mtime is used, it is used only to determine if files are the same.
170 ** If the mtime of a file has changed, we still examine the on-disk content
@@ -171,12 +171,11 @@
171 ** to see whether or not the edit was a null-edit.
172 */
173 void vfile_check_signature(int vid, unsigned int cksigFlags){
174 int nErr = 0;
175 Stmt q;
176 int useMtime = (cksigFlags & CKSIG_HASH)==0
 
177 && db_get_boolean("mtime-changes", 1);
178
179 db_begin_transaction();
180 db_prepare(&q, "SELECT id, %Q || pathname,"
181 " vfile.mrid, deleted, chnged, uuid, size, mtime,"
@@ -222,40 +221,30 @@
221 chnged = 1;
222 }
223 if( origSize!=currentSize ){
224 if( chnged!=1 ){
225 /* A file size change is definitive - the file has changed. No
226 ** need to check the mtime or hash */
227 chnged = 1;
228 }
229 }else if( chnged==1 && rid!=0 && !isDeleted ){
230 /* File is believed to have changed but it is the same size.
231 ** Double check that it really has changed by looking at content. */
232 const char *zUuid = db_column_text(&q, 5);
233 int nUuid = db_column_bytes(&q, 5);
234 assert( origSize==currentSize );
235 if( hname_verify_file_hash(zName, zUuid, nUuid) ) chnged = 0;
 
 
 
 
 
 
236 }else if( (chnged==0 || chnged==2 || chnged==4)
237 && (useMtime==0 || currentMtime!=oldMtime) ){
238 /* For files that were formerly believed to be unchanged or that were
239 ** changed by merging, if their mtime changes, or unconditionally
240 ** if --hash is used, check to see if they have been edited by
241 ** looking at their artifact hashes */
242 const char *zUuid = db_column_text(&q, 5);
243 int nUuid = db_column_bytes(&q, 5);
244 assert( origSize==currentSize );
245 if( !hname_verify_file_hash(zName, zUuid, nUuid) ) chnged = 1;
 
 
 
 
 
 
 
 
246 }
247 if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2 || chnged==4) ){
248 i64 desiredMtime;
249 if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){
250 if( currentMtime!=desiredMtime ){
251
+2 -2
--- src/wiki.c
+++ src/wiki.c
@@ -1122,12 +1122,12 @@
11221122
*/
11231123
int wiki_technote_to_rid(const char *zETime) {
11241124
int rid=0; /* Artifact ID of the tech note */
11251125
int nETime = strlen(zETime);
11261126
Stmt q;
1127
- if( nETime>=4 && nETime<=UUID_SIZE && validate16(zETime, nETime) ){
1128
- char zUuid[UUID_SIZE+1];
1127
+ if( nETime>=4 && hname_validate(zETime, nETime) ){
1128
+ char zUuid[HNAME_MAX+1];
11291129
memcpy(zUuid, zETime, nETime+1);
11301130
canonical16(zUuid, nETime);
11311131
db_prepare(&q,
11321132
"SELECT e.objid"
11331133
" FROM event e, tag t"
11341134
--- src/wiki.c
+++ src/wiki.c
@@ -1122,12 +1122,12 @@
1122 */
1123 int wiki_technote_to_rid(const char *zETime) {
1124 int rid=0; /* Artifact ID of the tech note */
1125 int nETime = strlen(zETime);
1126 Stmt q;
1127 if( nETime>=4 && nETime<=UUID_SIZE && validate16(zETime, nETime) ){
1128 char zUuid[UUID_SIZE+1];
1129 memcpy(zUuid, zETime, nETime+1);
1130 canonical16(zUuid, nETime);
1131 db_prepare(&q,
1132 "SELECT e.objid"
1133 " FROM event e, tag t"
1134
--- src/wiki.c
+++ src/wiki.c
@@ -1122,12 +1122,12 @@
1122 */
1123 int wiki_technote_to_rid(const char *zETime) {
1124 int rid=0; /* Artifact ID of the tech note */
1125 int nETime = strlen(zETime);
1126 Stmt q;
1127 if( nETime>=4 && hname_validate(zETime, nETime) ){
1128 char zUuid[HNAME_MAX+1];
1129 memcpy(zUuid, zETime, nETime+1);
1130 canonical16(zUuid, nETime);
1131 db_prepare(&q,
1132 "SELECT e.objid"
1133 " FROM event e, tag t"
1134
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1067,11 +1067,11 @@
10671067
** If the input string corresponds to an existing baseline,
10681068
** return true.
10691069
*/
10701070
static int is_valid_uuid(const char *z){
10711071
int n = strlen(z);
1072
- if( n<4 || n>UUID_SIZE ) return 0;
1072
+ if( n<4 || n>HNAME_MAX ) return 0;
10731073
if( !validate16(z, n) ) return 0;
10741074
return 1;
10751075
}
10761076
10771077
/*
10781078
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1067,11 +1067,11 @@
1067 ** If the input string corresponds to an existing baseline,
1068 ** return true.
1069 */
1070 static int is_valid_uuid(const char *z){
1071 int n = strlen(z);
1072 if( n<4 || n>UUID_SIZE ) return 0;
1073 if( !validate16(z, n) ) return 0;
1074 return 1;
1075 }
1076
1077 /*
1078
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1067,11 +1067,11 @@
1067 ** If the input string corresponds to an existing baseline,
1068 ** return true.
1069 */
1070 static int is_valid_uuid(const char *z){
1071 int n = strlen(z);
1072 if( n<4 || n>HNAME_MAX ) return 0;
1073 if( !validate16(z, n) ) return 0;
1074 return 1;
1075 }
1076
1077 /*
1078
+96 -66
--- src/xfer.c
+++ src/xfer.c
@@ -49,16 +49,17 @@
4949
int nDanglingFile; /* Number of dangling deltas received */
5050
int mxSend; /* Stop sending "file" when pOut reaches this size */
5151
int resync; /* Send igot cards for all holdings */
5252
u8 syncPrivate; /* True to enable syncing private content */
5353
u8 nextIsPrivate; /* If true, next "file" received is a private */
54
+ u32 clientVersion; /* Version of the client software */
5455
time_t maxTime; /* Time when this transfer should be finished */
5556
};
5657
5758
5859
/*
59
-** The input blob contains a UUID. Convert it into a record ID.
60
+** The input blob contains an artifact. Convert it into a record ID.
6061
** Create a phantom record if no prior record exists and
6162
** phantomize is true.
6263
**
6364
** Compare to uuid_to_rid(). This routine takes a blob argument
6465
** and does less error checking.
@@ -100,12 +101,12 @@
100101
** message. This routine finishes parsing that message and does
101102
** a record insert of the file.
102103
**
103104
** The file line is in one of the following two forms:
104105
**
105
-** file UUID SIZE \n CONTENT
106
-** file UUID DELTASRC SIZE \n CONTENT
106
+** file HASH SIZE \n CONTENT
107
+** file HASH DELTASRC SIZE \n CONTENT
107108
**
108109
** The content is SIZE bytes immediately following the newline.
109110
** If DELTASRC exists, then the CONTENT is a delta against the
110111
** content of DELTASRC.
111112
**
@@ -122,29 +123,30 @@
122123
int *pnUuidList
123124
){
124125
int n;
125126
int rid;
126127
int srcid = 0;
127
- Blob content, hash;
128
+ Blob content;
128129
int isPriv;
130
+ Blob *pUuid;
129131
130132
isPriv = pXfer->nextIsPrivate;
131133
pXfer->nextIsPrivate = 0;
132134
if( pXfer->nToken<3
133135
|| pXfer->nToken>4
134
- || !blob_is_uuid(&pXfer->aToken[1])
136
+ || !blob_is_hname(&pXfer->aToken[1])
135137
|| !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &n)
136138
|| n<0
137
- || (pXfer->nToken==4 && !blob_is_uuid(&pXfer->aToken[2]))
139
+ || (pXfer->nToken==4 && !blob_is_hname(&pXfer->aToken[2]))
138140
){
139141
blob_appendf(&pXfer->err, "malformed file line");
140142
return;
141143
}
142144
blob_zero(&content);
143
- blob_zero(&hash);
144145
blob_extract(pXfer->pIn, n, &content);
145
- if( !cloneFlag && uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){
146
+ pUuid = &pXfer->aToken[1];
147
+ if( !cloneFlag && uuid_is_shunned(blob_str(pUuid)) ){
146148
/* Ignore files that have been shunned */
147149
blob_reset(&content);
148150
return;
149151
}
150152
if( isPriv && !g.perm.Private ){
@@ -158,26 +160,26 @@
158160
pXfer->nDeltaRcvd++;
159161
}else{
160162
srcid = 0;
161163
pXfer->nFileRcvd++;
162164
}
163
- rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid,
165
+ rid = content_put_ex(&content, blob_str(pUuid), srcid,
164166
0, isPriv);
165
- Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]),
166
- blob_size(&pXfer->aToken[1]));
167
+ Th_AppendToList(pzUuidList, pnUuidList, blob_str(pUuid),
168
+ blob_size(pUuid));
167169
remote_has(rid);
168170
blob_reset(&content);
169171
return;
170172
}
171173
if( pXfer->nToken==4 ){
172174
Blob src, next;
173175
srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv);
174176
if( content_get(srcid, &src)==0 ){
175
- rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid,
177
+ rid = content_put_ex(&content, blob_str(pUuid), srcid,
176178
0, isPriv);
177
- Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]),
178
- blob_size(&pXfer->aToken[1]));
179
+ Th_AppendToList(pzUuidList, pnUuidList, blob_str(pUuid),
180
+ blob_size(pUuid));
179181
pXfer->nDanglingFile++;
180182
db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid);
181183
if( !isPriv ) content_make_public(rid);
182184
blob_reset(&src);
183185
blob_reset(&content);
@@ -189,19 +191,15 @@
189191
blob_reset(&content);
190192
content = next;
191193
}else{
192194
pXfer->nFileRcvd++;
193195
}
194
- sha1sum_blob(&content, &hash);
195
- if( !blob_eq_str(&pXfer->aToken[1], blob_str(&hash), -1) ){
196
- blob_appendf(&pXfer->err,
197
- "wrong hash on received artifact: expected %s but got %s",
198
- blob_str(&pXfer->aToken[1]), blob_str(&hash));
199
- }
200
- rid = content_put_ex(&content, blob_str(&hash), 0, 0, isPriv);
201
- Th_AppendToList(pzUuidList, pnUuidList, blob_str(&hash), blob_size(&hash));
202
- blob_reset(&hash);
196
+ if( hname_verify_hash(&content, blob_buffer(pUuid), blob_size(pUuid))==0 ){
197
+ blob_appendf(&pXfer->err, "wrong hash on received artifact: %b", pUuid);
198
+ }
199
+ rid = content_put_ex(&content, blob_str(pUuid), 0, 0, isPriv);
200
+ Th_AppendToList(pzUuidList, pnUuidList, blob_str(pUuid), blob_size(pUuid));
203201
if( rid==0 ){
204202
blob_appendf(&pXfer->err, "%s", g.zErrMsg);
205203
blob_reset(&content);
206204
}else{
207205
if( !isPriv ) content_make_public(rid);
@@ -217,18 +215,18 @@
217215
** a record insert of the file. The difference between "file" and
218216
** "cfile" is that with "cfile" the content is already compressed.
219217
**
220218
** The file line is in one of the following two forms:
221219
**
222
-** cfile UUID USIZE CSIZE \n CONTENT
223
-** cfile UUID DELTASRC USIZE CSIZE \n CONTENT
220
+** cfile HASH USIZE CSIZE \n CONTENT
221
+** cfile HASH DELTASRC USIZE CSIZE \n CONTENT
224222
**
225223
** The content is CSIZE bytes immediately following the newline.
226224
** If DELTASRC exists, then the CONTENT is a delta against the
227225
** content of DELTASRC.
228226
**
229
-** The original size of the UUID artifact is USIZE.
227
+** The original size of the HASH artifact is USIZE.
230228
**
231229
** If any error occurs, write a message into pErr which has already
232230
** be initialized to an empty string.
233231
**
234232
** Any artifact successfully received by this routine is considered to
@@ -248,15 +246,15 @@
248246
249247
isPriv = pXfer->nextIsPrivate;
250248
pXfer->nextIsPrivate = 0;
251249
if( pXfer->nToken<4
252250
|| pXfer->nToken>5
253
- || !blob_is_uuid(&pXfer->aToken[1])
251
+ || !blob_is_hname(&pXfer->aToken[1])
254252
|| !blob_is_int(&pXfer->aToken[pXfer->nToken-2], &szU)
255253
|| !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &szC)
256254
|| szC<0 || szU<0
257
- || (pXfer->nToken==5 && !blob_is_uuid(&pXfer->aToken[2]))
255
+ || (pXfer->nToken==5 && !blob_is_hname(&pXfer->aToken[2]))
258256
){
259257
blob_appendf(&pXfer->err, "malformed cfile line");
260258
return;
261259
}
262260
if( isPriv && !g.perm.Private ){
@@ -297,11 +295,11 @@
297295
**
298296
** If the 0x0001 bit of FLAGS is set, that means the file has been
299297
** deleted, SIZE is zero, the HASH is "-", and the "\n CONTENT" is omitted.
300298
**
301299
** SIZE is the number of bytes of CONTENT. The CONTENT is uncompressed.
302
-** HASH is the SHA1 hash of CONTENT.
300
+** HASH is the artifact hash of CONTENT.
303301
**
304302
** If the 0x0004 bit of FLAGS is set, that means the CONTENT is omitted.
305303
** The sender might have omitted the content because it is too big to
306304
** transmit, or because it is unchanged and this record exists purely
307305
** to update the MTIME.
@@ -310,11 +308,10 @@
310308
sqlite3_int64 mtime; /* The MTIME */
311309
Blob *pHash; /* The HASH value */
312310
int sz; /* The SIZE */
313311
int flags; /* The FLAGS */
314312
Blob content; /* The CONTENT */
315
- Blob hash; /* Hash computed from CONTENT to compare with HASH */
316313
Blob x; /* Compressed content */
317314
Stmt q; /* SQL statements for comparison and insert */
318315
int isDelete; /* HASH is "-" indicating this is a delete */
319316
int nullContent; /* True of CONTENT is NULL */
320317
int iStatus; /* Result from unversioned_status() */
@@ -321,25 +318,23 @@
321318
322319
pHash = &pXfer->aToken[3];
323320
if( pXfer->nToken==5
324321
|| !blob_is_filename(&pXfer->aToken[1])
325322
|| !blob_is_int64(&pXfer->aToken[2], &mtime)
326
- || (!blob_eq(pHash,"-") && !blob_is_uuid(pHash))
323
+ || (!blob_eq(pHash,"-") && !blob_is_hname(pHash))
327324
|| !blob_is_int(&pXfer->aToken[4], &sz)
328325
|| !blob_is_int(&pXfer->aToken[5], &flags)
329326
){
330327
blob_appendf(&pXfer->err, "malformed uvfile line");
331328
return;
332329
}
333330
blob_init(&content, 0, 0);
334
- blob_init(&hash, 0, 0);
335331
blob_init(&x, 0, 0);
336332
if( sz>0 && (flags & 0x0005)==0 ){
337333
blob_extract(pXfer->pIn, sz, &content);
338334
nullContent = 0;
339
- sha1sum_blob(&content, &hash);
340
- if( blob_compare(&hash, pHash)!=0 ){
335
+ if( hname_verify_hash(&content, blob_buffer(pHash), blob_size(pHash))==0 ){
341336
blob_appendf(&pXfer->err, "in uvfile line, HASH does not match CONTENT");
342337
goto end_accept_unversioned_file;
343338
}
344339
}else{
345340
nullContent = 1;
@@ -399,11 +394,10 @@
399394
db_unset("uv-hash", 0);
400395
401396
end_accept_unversioned_file:
402397
blob_reset(&x);
403398
blob_reset(&content);
404
- blob_reset(&hash);
405399
}
406400
407401
/*
408402
** Try to send a file as a delta against its parent.
409403
** If successful, return the number of bytes in the delta.
@@ -415,11 +409,11 @@
415409
static int send_delta_parent(
416410
Xfer *pXfer, /* The transfer context */
417411
int rid, /* record id of the file to send */
418412
int isPrivate, /* True if rid is a private artifact */
419413
Blob *pContent, /* The content of the file to send */
420
- Blob *pUuid /* The UUID of the file to send */
414
+ Blob *pUuid /* The HASH of the file to send */
421415
){
422416
static const char *const azQuery[] = {
423417
"SELECT pid FROM plink x"
424418
" WHERE cid=%d"
425419
" AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)",
@@ -469,11 +463,11 @@
469463
*/
470464
static int send_delta_native(
471465
Xfer *pXfer, /* The transfer context */
472466
int rid, /* record id of the file to send */
473467
int isPrivate, /* True if rid is a private artifact */
474
- Blob *pUuid /* The UUID of the file to send */
468
+ Blob *pUuid /* The HASH of the file to send */
475469
){
476470
Blob src, delta;
477471
int size = 0;
478472
int srcId;
479473
@@ -500,15 +494,26 @@
500494
}else{
501495
size = 0;
502496
}
503497
return size;
504498
}
499
+
500
+/*
501
+** Push an error message to alert the older client that the repository
502
+** has SHA3 content and cannot be synced or cloned.
503
+*/
504
+static void xfer_cannot_send_sha3_error(Xfer *pXfer){
505
+ blob_appendf(pXfer->pOut,
506
+ "error Fossil\\sversion\\s2.0\\sor\\slater\\srequired.\n"
507
+ );
508
+}
509
+
505510
506511
/*
507512
** Send the file identified by rid.
508513
**
509
-** The pUuid can be NULL in which case the correct UUID is computed
514
+** The pUuid can be NULL in which case the correct hash is computed
510515
** from the rid.
511516
**
512517
** Try to send the file as a native delta if nativeDelta is true, or
513518
** as a parent delta if nativeDelta is false.
514519
**
@@ -527,10 +532,14 @@
527532
}
528533
blob_zero(&uuid);
529534
db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d AND size>=0", rid);
530535
if( blob_size(&uuid)==0 ){
531536
return;
537
+ }
538
+ if( blob_size(&uuid)>HNAME_LEN_SHA1 && pXfer->clientVersion<20000 ){
539
+ xfer_cannot_send_sha3_error(pXfer);
540
+ return;
532541
}
533542
if( pUuid ){
534543
if( blob_compare(pUuid, &uuid)!=0 ){
535544
blob_reset(&uuid);
536545
return;
@@ -617,10 +626,15 @@
617626
szC = db_column_bytes(&q1, 2);
618627
zContent = db_column_raw(&q1, 2);
619628
srcIsPrivate = db_column_int(&q1, 3);
620629
zDelta = db_column_text(&q1, 4);
621630
if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1);
631
+ if( pXfer->clientVersion<20000 && db_column_bytes(&q1,0)!=HNAME_LEN_SHA1 ){
632
+ xfer_cannot_send_sha3_error(pXfer);
633
+ db_reset(&q1);
634
+ return;
635
+ }
622636
blob_appendf(pXfer->pOut, "cfile %s ", zUuid);
623637
if( !isPrivate && srcIsPrivate ){
624638
content_get(rid, &fullContent);
625639
szU = blob_size(&fullContent);
626640
blob_compress(&fullContent, &fullContent);
@@ -676,10 +690,15 @@
676690
);
677691
}
678692
if( db_step(&q1)==SQLITE_ROW ){
679693
sqlite3_int64 mtime = db_column_int64(&q1, 0);
680694
const char *zHash = db_column_text(&q1, 1);
695
+ if( pXfer->clientVersion<20000 && db_column_bytes(&q1,1)>HNAME_LEN_SHA1 ){
696
+ xfer_cannot_send_sha3_error(pXfer);
697
+ db_reset(&q1);
698
+ return;
699
+ }
681700
if( blob_size(pXfer->pOut)>=pXfer->mxSend ){
682701
/* If we have already reached the send size limit, send a (short)
683702
** uvigot card rather than a uvfile card. This only happens on the
684703
** server side. The uvigot card will provoke the client to resend
685704
** another uvgimme on the next cycle. */
@@ -728,23 +747,23 @@
728747
}
729748
db_finalize(&q);
730749
}
731750
732751
/*
733
-** Compute an SHA1 hash on the tail of pMsg. Verify that it matches the
752
+** Compute an hash on the tail of pMsg. Verify that it matches the
734753
** the hash given in pHash. Return non-zero for an error and 0 on success.
754
+**
755
+** The type of hash computed (SHA1, SHA3-256) is determined by
756
+** the length of the input hash in pHash.
735757
*/
736758
static int check_tail_hash(Blob *pHash, Blob *pMsg){
737759
Blob tail;
738
- Blob h2;
739760
int rc;
740761
blob_tail(pMsg, &tail);
741
- sha1sum_blob(&tail, &h2);
742
- rc = blob_compare(pHash, &h2);
743
- blob_reset(&h2);
762
+ rc = hname_verify_hash(&tail, blob_buffer(pHash), blob_size(pHash));
744763
blob_reset(&tail);
745
- return rc;
764
+ return rc==HNAME_ERROR;
746765
}
747766
748767
/*
749768
** Check the signature on an application/x-fossil payload received by
750769
** the HTTP server. The signature is a line of the following form:
@@ -1198,12 +1217,12 @@
11981217
while( blob_line(xfer.pIn, &xfer.line) ){
11991218
if( blob_buffer(&xfer.line)[0]=='#' ) continue;
12001219
if( blob_size(&xfer.line)==0 ) continue;
12011220
xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));
12021221
1203
- /* file UUID SIZE \n CONTENT
1204
- ** file UUID DELTASRC SIZE \n CONTENT
1222
+ /* file HASH SIZE \n CONTENT
1223
+ ** file HASH DELTASRC SIZE \n CONTENT
12051224
**
12061225
** Accept a file from the client.
12071226
*/
12081227
if( blob_eq(&xfer.aToken[0], "file") ){
12091228
if( !isPush ){
@@ -1219,12 +1238,12 @@
12191238
nErr++;
12201239
break;
12211240
}
12221241
}else
12231242
1224
- /* cfile UUID USIZE CSIZE \n CONTENT
1225
- ** cfile UUID DELTASRC USIZE CSIZE \n CONTENT
1243
+ /* cfile HASH USIZE CSIZE \n CONTENT
1244
+ ** cfile HASH DELTASRC USIZE CSIZE \n CONTENT
12261245
**
12271246
** Accept a file from the client.
12281247
*/
12291248
if( blob_eq(&xfer.aToken[0], "cfile") ){
12301249
if( !isPush ){
@@ -1254,17 +1273,17 @@
12541273
nErr++;
12551274
break;
12561275
}
12571276
}else
12581277
1259
- /* gimme UUID
1278
+ /* gimme HASH
12601279
**
12611280
** Client is requesting a file. Send it.
12621281
*/
12631282
if( blob_eq(&xfer.aToken[0], "gimme")
12641283
&& xfer.nToken==2
1265
- && blob_is_uuid(&xfer.aToken[1])
1284
+ && blob_is_hname(&xfer.aToken[1])
12661285
){
12671286
nGimme++;
12681287
if( isPull ){
12691288
int rid = rid_from_uuid(&xfer.aToken[1], 0, 0);
12701289
if( rid ){
@@ -1282,18 +1301,18 @@
12821301
&& blob_is_filename(&xfer.aToken[1])
12831302
){
12841303
send_unversioned_file(&xfer, blob_str(&xfer.aToken[1]), 0);
12851304
}else
12861305
1287
- /* igot UUID ?ISPRIVATE?
1306
+ /* igot HASH ?ISPRIVATE?
12881307
**
12891308
** Client announces that it has a particular file. If the ISPRIVATE
12901309
** argument exists and is non-zero, then the file is a private file.
12911310
*/
12921311
if( xfer.nToken>=2
12931312
&& blob_eq(&xfer.aToken[0], "igot")
1294
- && blob_is_uuid(&xfer.aToken[1])
1313
+ && blob_is_hname(&xfer.aToken[1])
12951314
){
12961315
if( isPush ){
12971316
if( xfer.nToken==2 || blob_eq(&xfer.aToken[2],"1")==0 ){
12981317
rid_from_uuid(&xfer.aToken[1], 1, 0);
12991318
}else if( g.perm.Private ){
@@ -1307,16 +1326,15 @@
13071326
13081327
/* pull SERVERCODE PROJECTCODE
13091328
** push SERVERCODE PROJECTCODE
13101329
**
13111330
** The client wants either send or receive. The server should
1312
- ** verify that the project code matches.
1331
+ ** verify that the project code matches. The server code is ignored.
13131332
*/
13141333
if( xfer.nToken==3
13151334
&& (blob_eq(&xfer.aToken[0], "pull") || blob_eq(&xfer.aToken[0], "push"))
1316
- && blob_is_uuid(&xfer.aToken[1])
1317
- && blob_is_uuid(&xfer.aToken[2])
1335
+ && blob_is_hname(&xfer.aToken[2])
13181336
){
13191337
const char *zPCode;
13201338
zPCode = db_get("project-code", 0);
13211339
if( zPCode==0 ){
13221340
fossil_panic("missing project code");
@@ -1534,19 +1552,27 @@
15341552
** Send igot cards for all known artifacts.
15351553
*/
15361554
if( blob_eq(&xfer.aToken[1], "send-catalog") ){
15371555
xfer.resync = 0x7fffffff;
15381556
}
1557
+
1558
+ /* pragma client-version VERSION
1559
+ **
1560
+ ** Let the server know what version of Fossil is running on the client.
1561
+ */
1562
+ if( xfer.nToken>=3 && blob_eq(&xfer.aToken[1], "client-version") ){
1563
+ xfer.clientVersion = atoi(blob_str(&xfer.aToken[2]));
1564
+ }
15391565
15401566
/* pragma uv-hash HASH
15411567
**
15421568
** The client wants to make sure that unversioned files are all synced.
15431569
** If the HASH does not match, send a complete catalog of
15441570
** "uvigot" cards.
15451571
*/
15461572
if( blob_eq(&xfer.aToken[1], "uv-hash")
1547
- && blob_is_uuid(&xfer.aToken[2])
1573
+ && blob_is_hname(&xfer.aToken[2])
15481574
){
15491575
if( !uvCatalogSent ){
15501576
if( g.perm.Read && g.perm.WrUnver ){
15511577
@ pragma uv-push-ok
15521578
send_unversioned_catalog(&xfer);
@@ -1742,10 +1768,11 @@
17421768
memset(&xfer, 0, sizeof(xfer));
17431769
xfer.pIn = &recv;
17441770
xfer.pOut = &send;
17451771
xfer.mxSend = db_get_int("max-upload", 250000);
17461772
xfer.maxTime = -1;
1773
+ xfer.clientVersion = RELEASE_VERSION_NUMBER;
17471774
if( syncFlags & SYNC_PRIVATE ){
17481775
g.perm.Private = 1;
17491776
xfer.syncPrivate = 1;
17501777
}
17511778
@@ -1783,10 +1810,11 @@
17831810
}
17841811
17851812
/*
17861813
** Always begin with a clone, pull, or push message
17871814
*/
1815
+ blob_appendf(&send, "pragma client-version %d\n", RELEASE_VERSION_NUMBER);
17881816
if( syncFlags & SYNC_CLONE ){
17891817
blob_appendf(&send, "clone 3 %d\n", cloneSeqno);
17901818
syncFlags &= ~(SYNC_PUSH|SYNC_PULL);
17911819
nCardSent++;
17921820
/* TBD: Request all transferable configuration values */
@@ -1819,10 +1847,11 @@
18191847
db_record_repository_filename(0);
18201848
db_multi_exec(
18211849
"CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
18221850
);
18231851
manifest_crosslink_begin();
1852
+
18241853
18251854
/* Send back the most recently received cookie. Let the server
18261855
** figure out if this is a cookie that it cares about.
18271856
*/
18281857
zCookie = db_get("cookie", 0);
@@ -1976,10 +2005,11 @@
19762005
xfer.nGimmeSent = 0;
19772006
xfer.nIGotSent = 0;
19782007
19792008
lastPctDone = -1;
19802009
blob_reset(&send);
2010
+ blob_appendf(&send, "pragma client-version %d\n", RELEASE_VERSION_NUMBER);
19812011
rArrivalTime = db_double(0.0, "SELECT julianday('now')");
19822012
19832013
/* Send the send-private pragma if we are trying to sync private data */
19842014
if( syncFlags & SYNC_PRIVATE ){
19852015
blob_append(&send, "pragma send-private\n", -1);
@@ -2028,22 +2058,22 @@
20282058
lastPctDone = pctDone;
20292059
fflush(stdout);
20302060
}
20312061
}
20322062
2033
- /* file UUID SIZE \n CONTENT
2034
- ** file UUID DELTASRC SIZE \n CONTENT
2063
+ /* file HASH SIZE \n CONTENT
2064
+ ** file HASH DELTASRC SIZE \n CONTENT
20352065
**
20362066
** Receive a file transmitted from the server.
20372067
*/
20382068
if( blob_eq(&xfer.aToken[0],"file") ){
20392069
xfer_accept_file(&xfer, (syncFlags & SYNC_CLONE)!=0, 0, 0);
20402070
nArtifactRcvd++;
20412071
}else
20422072
2043
- /* cfile UUID USIZE CSIZE \n CONTENT
2044
- ** cfile UUID DELTASRC USIZE CSIZE \n CONTENT
2073
+ /* cfile HASH USIZE CSIZE \n CONTENT
2074
+ ** cfile HASH DELTASRC USIZE CSIZE \n CONTENT
20452075
**
20462076
** Receive a compressed file transmitted from the server.
20472077
*/
20482078
if( blob_eq(&xfer.aToken[0],"cfile") ){
20492079
xfer_accept_compressed_file(&xfer, 0, 0);
@@ -2062,27 +2092,27 @@
20622092
fossil_print("\rUnversioned-file received: %s\n",
20632093
blob_str(&xfer.aToken[1]));
20642094
}
20652095
}else
20662096
2067
- /* gimme UUID
2097
+ /* gimme HASH
20682098
**
20692099
** Server is requesting a file. If the file is a manifest, assume
20702100
** that the server will also want to know all of the content files
20712101
** associated with the manifest and send those too.
20722102
*/
20732103
if( blob_eq(&xfer.aToken[0], "gimme")
20742104
&& xfer.nToken==2
2075
- && blob_is_uuid(&xfer.aToken[1])
2105
+ && blob_is_hname(&xfer.aToken[1])
20762106
){
20772107
if( syncFlags & SYNC_PUSH ){
20782108
int rid = rid_from_uuid(&xfer.aToken[1], 0, 0);
20792109
if( rid ) send_file(&xfer, rid, &xfer.aToken[1], 0);
20802110
}
20812111
}else
20822112
2083
- /* igot UUID ?PRIVATEFLAG?
2113
+ /* igot HASH ?PRIVATEFLAG?
20842114
**
20852115
** Server announces that it has a particular file. If this is
20862116
** not a file that we have and we are pulling, then create a
20872117
** phantom to cause this file to be requested on the next cycle.
20882118
** Always remember that the server has this file so that we do
@@ -2092,11 +2122,11 @@
20922122
** private. Pretend it does not exists if we are not pulling
20932123
** private files.
20942124
*/
20952125
if( xfer.nToken>=2
20962126
&& blob_eq(&xfer.aToken[0], "igot")
2097
- && blob_is_uuid(&xfer.aToken[1])
2127
+ && blob_is_hname(&xfer.aToken[1])
20982128
){
20992129
int rid;
21002130
int isPriv = xfer.nToken>=3 && blob_eq(&xfer.aToken[2],"1");
21012131
rid = rid_from_uuid(&xfer.aToken[1], 0, 0);
21022132
if( rid>0 ){
@@ -2126,11 +2156,11 @@
21262156
if( xfer.nToken==5
21272157
&& blob_eq(&xfer.aToken[0], "uvigot")
21282158
&& blob_is_filename(&xfer.aToken[1])
21292159
&& blob_is_int64(&xfer.aToken[2], &mtime)
21302160
&& blob_is_int(&xfer.aToken[4], &size)
2131
- && (blob_eq(&xfer.aToken[3],"-") || blob_is_uuid(&xfer.aToken[3]))
2161
+ && (blob_eq(&xfer.aToken[3],"-") || blob_is_hname(&xfer.aToken[3]))
21322162
){
21332163
const char *zName = blob_str(&xfer.aToken[1]);
21342164
const char *zHash = blob_str(&xfer.aToken[3]);
21352165
int iStatus;
21362166
iStatus = unversioned_status(zName, mtime, zHash);
@@ -2188,11 +2218,11 @@
21882218
** the client what product to use for the new database.
21892219
*/
21902220
if( blob_eq(&xfer.aToken[0],"push")
21912221
&& xfer.nToken==3
21922222
&& (syncFlags & SYNC_CLONE)!=0
2193
- && blob_is_uuid(&xfer.aToken[2])
2223
+ && blob_is_hname(&xfer.aToken[2])
21942224
){
21952225
if( zPCode==0 ){
21962226
zPCode = mprintf("%b", &xfer.aToken[2]);
21972227
db_set("project-code", zPCode, 0);
21982228
}
21992229
--- src/xfer.c
+++ src/xfer.c
@@ -49,16 +49,17 @@
49 int nDanglingFile; /* Number of dangling deltas received */
50 int mxSend; /* Stop sending "file" when pOut reaches this size */
51 int resync; /* Send igot cards for all holdings */
52 u8 syncPrivate; /* True to enable syncing private content */
53 u8 nextIsPrivate; /* If true, next "file" received is a private */
 
54 time_t maxTime; /* Time when this transfer should be finished */
55 };
56
57
58 /*
59 ** The input blob contains a UUID. Convert it into a record ID.
60 ** Create a phantom record if no prior record exists and
61 ** phantomize is true.
62 **
63 ** Compare to uuid_to_rid(). This routine takes a blob argument
64 ** and does less error checking.
@@ -100,12 +101,12 @@
100 ** message. This routine finishes parsing that message and does
101 ** a record insert of the file.
102 **
103 ** The file line is in one of the following two forms:
104 **
105 ** file UUID SIZE \n CONTENT
106 ** file UUID DELTASRC SIZE \n CONTENT
107 **
108 ** The content is SIZE bytes immediately following the newline.
109 ** If DELTASRC exists, then the CONTENT is a delta against the
110 ** content of DELTASRC.
111 **
@@ -122,29 +123,30 @@
122 int *pnUuidList
123 ){
124 int n;
125 int rid;
126 int srcid = 0;
127 Blob content, hash;
128 int isPriv;
 
129
130 isPriv = pXfer->nextIsPrivate;
131 pXfer->nextIsPrivate = 0;
132 if( pXfer->nToken<3
133 || pXfer->nToken>4
134 || !blob_is_uuid(&pXfer->aToken[1])
135 || !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &n)
136 || n<0
137 || (pXfer->nToken==4 && !blob_is_uuid(&pXfer->aToken[2]))
138 ){
139 blob_appendf(&pXfer->err, "malformed file line");
140 return;
141 }
142 blob_zero(&content);
143 blob_zero(&hash);
144 blob_extract(pXfer->pIn, n, &content);
145 if( !cloneFlag && uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){
 
146 /* Ignore files that have been shunned */
147 blob_reset(&content);
148 return;
149 }
150 if( isPriv && !g.perm.Private ){
@@ -158,26 +160,26 @@
158 pXfer->nDeltaRcvd++;
159 }else{
160 srcid = 0;
161 pXfer->nFileRcvd++;
162 }
163 rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid,
164 0, isPriv);
165 Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]),
166 blob_size(&pXfer->aToken[1]));
167 remote_has(rid);
168 blob_reset(&content);
169 return;
170 }
171 if( pXfer->nToken==4 ){
172 Blob src, next;
173 srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv);
174 if( content_get(srcid, &src)==0 ){
175 rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid,
176 0, isPriv);
177 Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]),
178 blob_size(&pXfer->aToken[1]));
179 pXfer->nDanglingFile++;
180 db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid);
181 if( !isPriv ) content_make_public(rid);
182 blob_reset(&src);
183 blob_reset(&content);
@@ -189,19 +191,15 @@
189 blob_reset(&content);
190 content = next;
191 }else{
192 pXfer->nFileRcvd++;
193 }
194 sha1sum_blob(&content, &hash);
195 if( !blob_eq_str(&pXfer->aToken[1], blob_str(&hash), -1) ){
196 blob_appendf(&pXfer->err,
197 "wrong hash on received artifact: expected %s but got %s",
198 blob_str(&pXfer->aToken[1]), blob_str(&hash));
199 }
200 rid = content_put_ex(&content, blob_str(&hash), 0, 0, isPriv);
201 Th_AppendToList(pzUuidList, pnUuidList, blob_str(&hash), blob_size(&hash));
202 blob_reset(&hash);
203 if( rid==0 ){
204 blob_appendf(&pXfer->err, "%s", g.zErrMsg);
205 blob_reset(&content);
206 }else{
207 if( !isPriv ) content_make_public(rid);
@@ -217,18 +215,18 @@
217 ** a record insert of the file. The difference between "file" and
218 ** "cfile" is that with "cfile" the content is already compressed.
219 **
220 ** The file line is in one of the following two forms:
221 **
222 ** cfile UUID USIZE CSIZE \n CONTENT
223 ** cfile UUID DELTASRC USIZE CSIZE \n CONTENT
224 **
225 ** The content is CSIZE bytes immediately following the newline.
226 ** If DELTASRC exists, then the CONTENT is a delta against the
227 ** content of DELTASRC.
228 **
229 ** The original size of the UUID artifact is USIZE.
230 **
231 ** If any error occurs, write a message into pErr which has already
232 ** be initialized to an empty string.
233 **
234 ** Any artifact successfully received by this routine is considered to
@@ -248,15 +246,15 @@
248
249 isPriv = pXfer->nextIsPrivate;
250 pXfer->nextIsPrivate = 0;
251 if( pXfer->nToken<4
252 || pXfer->nToken>5
253 || !blob_is_uuid(&pXfer->aToken[1])
254 || !blob_is_int(&pXfer->aToken[pXfer->nToken-2], &szU)
255 || !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &szC)
256 || szC<0 || szU<0
257 || (pXfer->nToken==5 && !blob_is_uuid(&pXfer->aToken[2]))
258 ){
259 blob_appendf(&pXfer->err, "malformed cfile line");
260 return;
261 }
262 if( isPriv && !g.perm.Private ){
@@ -297,11 +295,11 @@
297 **
298 ** If the 0x0001 bit of FLAGS is set, that means the file has been
299 ** deleted, SIZE is zero, the HASH is "-", and the "\n CONTENT" is omitted.
300 **
301 ** SIZE is the number of bytes of CONTENT. The CONTENT is uncompressed.
302 ** HASH is the SHA1 hash of CONTENT.
303 **
304 ** If the 0x0004 bit of FLAGS is set, that means the CONTENT is omitted.
305 ** The sender might have omitted the content because it is too big to
306 ** transmit, or because it is unchanged and this record exists purely
307 ** to update the MTIME.
@@ -310,11 +308,10 @@
310 sqlite3_int64 mtime; /* The MTIME */
311 Blob *pHash; /* The HASH value */
312 int sz; /* The SIZE */
313 int flags; /* The FLAGS */
314 Blob content; /* The CONTENT */
315 Blob hash; /* Hash computed from CONTENT to compare with HASH */
316 Blob x; /* Compressed content */
317 Stmt q; /* SQL statements for comparison and insert */
318 int isDelete; /* HASH is "-" indicating this is a delete */
319 int nullContent; /* True of CONTENT is NULL */
320 int iStatus; /* Result from unversioned_status() */
@@ -321,25 +318,23 @@
321
322 pHash = &pXfer->aToken[3];
323 if( pXfer->nToken==5
324 || !blob_is_filename(&pXfer->aToken[1])
325 || !blob_is_int64(&pXfer->aToken[2], &mtime)
326 || (!blob_eq(pHash,"-") && !blob_is_uuid(pHash))
327 || !blob_is_int(&pXfer->aToken[4], &sz)
328 || !blob_is_int(&pXfer->aToken[5], &flags)
329 ){
330 blob_appendf(&pXfer->err, "malformed uvfile line");
331 return;
332 }
333 blob_init(&content, 0, 0);
334 blob_init(&hash, 0, 0);
335 blob_init(&x, 0, 0);
336 if( sz>0 && (flags & 0x0005)==0 ){
337 blob_extract(pXfer->pIn, sz, &content);
338 nullContent = 0;
339 sha1sum_blob(&content, &hash);
340 if( blob_compare(&hash, pHash)!=0 ){
341 blob_appendf(&pXfer->err, "in uvfile line, HASH does not match CONTENT");
342 goto end_accept_unversioned_file;
343 }
344 }else{
345 nullContent = 1;
@@ -399,11 +394,10 @@
399 db_unset("uv-hash", 0);
400
401 end_accept_unversioned_file:
402 blob_reset(&x);
403 blob_reset(&content);
404 blob_reset(&hash);
405 }
406
407 /*
408 ** Try to send a file as a delta against its parent.
409 ** If successful, return the number of bytes in the delta.
@@ -415,11 +409,11 @@
415 static int send_delta_parent(
416 Xfer *pXfer, /* The transfer context */
417 int rid, /* record id of the file to send */
418 int isPrivate, /* True if rid is a private artifact */
419 Blob *pContent, /* The content of the file to send */
420 Blob *pUuid /* The UUID of the file to send */
421 ){
422 static const char *const azQuery[] = {
423 "SELECT pid FROM plink x"
424 " WHERE cid=%d"
425 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)",
@@ -469,11 +463,11 @@
469 */
470 static int send_delta_native(
471 Xfer *pXfer, /* The transfer context */
472 int rid, /* record id of the file to send */
473 int isPrivate, /* True if rid is a private artifact */
474 Blob *pUuid /* The UUID of the file to send */
475 ){
476 Blob src, delta;
477 int size = 0;
478 int srcId;
479
@@ -500,15 +494,26 @@
500 }else{
501 size = 0;
502 }
503 return size;
504 }
 
 
 
 
 
 
 
 
 
 
 
505
506 /*
507 ** Send the file identified by rid.
508 **
509 ** The pUuid can be NULL in which case the correct UUID is computed
510 ** from the rid.
511 **
512 ** Try to send the file as a native delta if nativeDelta is true, or
513 ** as a parent delta if nativeDelta is false.
514 **
@@ -527,10 +532,14 @@
527 }
528 blob_zero(&uuid);
529 db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d AND size>=0", rid);
530 if( blob_size(&uuid)==0 ){
531 return;
 
 
 
 
532 }
533 if( pUuid ){
534 if( blob_compare(pUuid, &uuid)!=0 ){
535 blob_reset(&uuid);
536 return;
@@ -617,10 +626,15 @@
617 szC = db_column_bytes(&q1, 2);
618 zContent = db_column_raw(&q1, 2);
619 srcIsPrivate = db_column_int(&q1, 3);
620 zDelta = db_column_text(&q1, 4);
621 if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1);
 
 
 
 
 
622 blob_appendf(pXfer->pOut, "cfile %s ", zUuid);
623 if( !isPrivate && srcIsPrivate ){
624 content_get(rid, &fullContent);
625 szU = blob_size(&fullContent);
626 blob_compress(&fullContent, &fullContent);
@@ -676,10 +690,15 @@
676 );
677 }
678 if( db_step(&q1)==SQLITE_ROW ){
679 sqlite3_int64 mtime = db_column_int64(&q1, 0);
680 const char *zHash = db_column_text(&q1, 1);
 
 
 
 
 
681 if( blob_size(pXfer->pOut)>=pXfer->mxSend ){
682 /* If we have already reached the send size limit, send a (short)
683 ** uvigot card rather than a uvfile card. This only happens on the
684 ** server side. The uvigot card will provoke the client to resend
685 ** another uvgimme on the next cycle. */
@@ -728,23 +747,23 @@
728 }
729 db_finalize(&q);
730 }
731
732 /*
733 ** Compute an SHA1 hash on the tail of pMsg. Verify that it matches the
734 ** the hash given in pHash. Return non-zero for an error and 0 on success.
 
 
 
735 */
736 static int check_tail_hash(Blob *pHash, Blob *pMsg){
737 Blob tail;
738 Blob h2;
739 int rc;
740 blob_tail(pMsg, &tail);
741 sha1sum_blob(&tail, &h2);
742 rc = blob_compare(pHash, &h2);
743 blob_reset(&h2);
744 blob_reset(&tail);
745 return rc;
746 }
747
748 /*
749 ** Check the signature on an application/x-fossil payload received by
750 ** the HTTP server. The signature is a line of the following form:
@@ -1198,12 +1217,12 @@
1198 while( blob_line(xfer.pIn, &xfer.line) ){
1199 if( blob_buffer(&xfer.line)[0]=='#' ) continue;
1200 if( blob_size(&xfer.line)==0 ) continue;
1201 xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));
1202
1203 /* file UUID SIZE \n CONTENT
1204 ** file UUID DELTASRC SIZE \n CONTENT
1205 **
1206 ** Accept a file from the client.
1207 */
1208 if( blob_eq(&xfer.aToken[0], "file") ){
1209 if( !isPush ){
@@ -1219,12 +1238,12 @@
1219 nErr++;
1220 break;
1221 }
1222 }else
1223
1224 /* cfile UUID USIZE CSIZE \n CONTENT
1225 ** cfile UUID DELTASRC USIZE CSIZE \n CONTENT
1226 **
1227 ** Accept a file from the client.
1228 */
1229 if( blob_eq(&xfer.aToken[0], "cfile") ){
1230 if( !isPush ){
@@ -1254,17 +1273,17 @@
1254 nErr++;
1255 break;
1256 }
1257 }else
1258
1259 /* gimme UUID
1260 **
1261 ** Client is requesting a file. Send it.
1262 */
1263 if( blob_eq(&xfer.aToken[0], "gimme")
1264 && xfer.nToken==2
1265 && blob_is_uuid(&xfer.aToken[1])
1266 ){
1267 nGimme++;
1268 if( isPull ){
1269 int rid = rid_from_uuid(&xfer.aToken[1], 0, 0);
1270 if( rid ){
@@ -1282,18 +1301,18 @@
1282 && blob_is_filename(&xfer.aToken[1])
1283 ){
1284 send_unversioned_file(&xfer, blob_str(&xfer.aToken[1]), 0);
1285 }else
1286
1287 /* igot UUID ?ISPRIVATE?
1288 **
1289 ** Client announces that it has a particular file. If the ISPRIVATE
1290 ** argument exists and is non-zero, then the file is a private file.
1291 */
1292 if( xfer.nToken>=2
1293 && blob_eq(&xfer.aToken[0], "igot")
1294 && blob_is_uuid(&xfer.aToken[1])
1295 ){
1296 if( isPush ){
1297 if( xfer.nToken==2 || blob_eq(&xfer.aToken[2],"1")==0 ){
1298 rid_from_uuid(&xfer.aToken[1], 1, 0);
1299 }else if( g.perm.Private ){
@@ -1307,16 +1326,15 @@
1307
1308 /* pull SERVERCODE PROJECTCODE
1309 ** push SERVERCODE PROJECTCODE
1310 **
1311 ** The client wants either send or receive. The server should
1312 ** verify that the project code matches.
1313 */
1314 if( xfer.nToken==3
1315 && (blob_eq(&xfer.aToken[0], "pull") || blob_eq(&xfer.aToken[0], "push"))
1316 && blob_is_uuid(&xfer.aToken[1])
1317 && blob_is_uuid(&xfer.aToken[2])
1318 ){
1319 const char *zPCode;
1320 zPCode = db_get("project-code", 0);
1321 if( zPCode==0 ){
1322 fossil_panic("missing project code");
@@ -1534,19 +1552,27 @@
1534 ** Send igot cards for all known artifacts.
1535 */
1536 if( blob_eq(&xfer.aToken[1], "send-catalog") ){
1537 xfer.resync = 0x7fffffff;
1538 }
 
 
 
 
 
 
 
 
1539
1540 /* pragma uv-hash HASH
1541 **
1542 ** The client wants to make sure that unversioned files are all synced.
1543 ** If the HASH does not match, send a complete catalog of
1544 ** "uvigot" cards.
1545 */
1546 if( blob_eq(&xfer.aToken[1], "uv-hash")
1547 && blob_is_uuid(&xfer.aToken[2])
1548 ){
1549 if( !uvCatalogSent ){
1550 if( g.perm.Read && g.perm.WrUnver ){
1551 @ pragma uv-push-ok
1552 send_unversioned_catalog(&xfer);
@@ -1742,10 +1768,11 @@
1742 memset(&xfer, 0, sizeof(xfer));
1743 xfer.pIn = &recv;
1744 xfer.pOut = &send;
1745 xfer.mxSend = db_get_int("max-upload", 250000);
1746 xfer.maxTime = -1;
 
1747 if( syncFlags & SYNC_PRIVATE ){
1748 g.perm.Private = 1;
1749 xfer.syncPrivate = 1;
1750 }
1751
@@ -1783,10 +1810,11 @@
1783 }
1784
1785 /*
1786 ** Always begin with a clone, pull, or push message
1787 */
 
1788 if( syncFlags & SYNC_CLONE ){
1789 blob_appendf(&send, "clone 3 %d\n", cloneSeqno);
1790 syncFlags &= ~(SYNC_PUSH|SYNC_PULL);
1791 nCardSent++;
1792 /* TBD: Request all transferable configuration values */
@@ -1819,10 +1847,11 @@
1819 db_record_repository_filename(0);
1820 db_multi_exec(
1821 "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
1822 );
1823 manifest_crosslink_begin();
 
1824
1825 /* Send back the most recently received cookie. Let the server
1826 ** figure out if this is a cookie that it cares about.
1827 */
1828 zCookie = db_get("cookie", 0);
@@ -1976,10 +2005,11 @@
1976 xfer.nGimmeSent = 0;
1977 xfer.nIGotSent = 0;
1978
1979 lastPctDone = -1;
1980 blob_reset(&send);
 
1981 rArrivalTime = db_double(0.0, "SELECT julianday('now')");
1982
1983 /* Send the send-private pragma if we are trying to sync private data */
1984 if( syncFlags & SYNC_PRIVATE ){
1985 blob_append(&send, "pragma send-private\n", -1);
@@ -2028,22 +2058,22 @@
2028 lastPctDone = pctDone;
2029 fflush(stdout);
2030 }
2031 }
2032
2033 /* file UUID SIZE \n CONTENT
2034 ** file UUID DELTASRC SIZE \n CONTENT
2035 **
2036 ** Receive a file transmitted from the server.
2037 */
2038 if( blob_eq(&xfer.aToken[0],"file") ){
2039 xfer_accept_file(&xfer, (syncFlags & SYNC_CLONE)!=0, 0, 0);
2040 nArtifactRcvd++;
2041 }else
2042
2043 /* cfile UUID USIZE CSIZE \n CONTENT
2044 ** cfile UUID DELTASRC USIZE CSIZE \n CONTENT
2045 **
2046 ** Receive a compressed file transmitted from the server.
2047 */
2048 if( blob_eq(&xfer.aToken[0],"cfile") ){
2049 xfer_accept_compressed_file(&xfer, 0, 0);
@@ -2062,27 +2092,27 @@
2062 fossil_print("\rUnversioned-file received: %s\n",
2063 blob_str(&xfer.aToken[1]));
2064 }
2065 }else
2066
2067 /* gimme UUID
2068 **
2069 ** Server is requesting a file. If the file is a manifest, assume
2070 ** that the server will also want to know all of the content files
2071 ** associated with the manifest and send those too.
2072 */
2073 if( blob_eq(&xfer.aToken[0], "gimme")
2074 && xfer.nToken==2
2075 && blob_is_uuid(&xfer.aToken[1])
2076 ){
2077 if( syncFlags & SYNC_PUSH ){
2078 int rid = rid_from_uuid(&xfer.aToken[1], 0, 0);
2079 if( rid ) send_file(&xfer, rid, &xfer.aToken[1], 0);
2080 }
2081 }else
2082
2083 /* igot UUID ?PRIVATEFLAG?
2084 **
2085 ** Server announces that it has a particular file. If this is
2086 ** not a file that we have and we are pulling, then create a
2087 ** phantom to cause this file to be requested on the next cycle.
2088 ** Always remember that the server has this file so that we do
@@ -2092,11 +2122,11 @@
2092 ** private. Pretend it does not exists if we are not pulling
2093 ** private files.
2094 */
2095 if( xfer.nToken>=2
2096 && blob_eq(&xfer.aToken[0], "igot")
2097 && blob_is_uuid(&xfer.aToken[1])
2098 ){
2099 int rid;
2100 int isPriv = xfer.nToken>=3 && blob_eq(&xfer.aToken[2],"1");
2101 rid = rid_from_uuid(&xfer.aToken[1], 0, 0);
2102 if( rid>0 ){
@@ -2126,11 +2156,11 @@
2126 if( xfer.nToken==5
2127 && blob_eq(&xfer.aToken[0], "uvigot")
2128 && blob_is_filename(&xfer.aToken[1])
2129 && blob_is_int64(&xfer.aToken[2], &mtime)
2130 && blob_is_int(&xfer.aToken[4], &size)
2131 && (blob_eq(&xfer.aToken[3],"-") || blob_is_uuid(&xfer.aToken[3]))
2132 ){
2133 const char *zName = blob_str(&xfer.aToken[1]);
2134 const char *zHash = blob_str(&xfer.aToken[3]);
2135 int iStatus;
2136 iStatus = unversioned_status(zName, mtime, zHash);
@@ -2188,11 +2218,11 @@
2188 ** the client what product to use for the new database.
2189 */
2190 if( blob_eq(&xfer.aToken[0],"push")
2191 && xfer.nToken==3
2192 && (syncFlags & SYNC_CLONE)!=0
2193 && blob_is_uuid(&xfer.aToken[2])
2194 ){
2195 if( zPCode==0 ){
2196 zPCode = mprintf("%b", &xfer.aToken[2]);
2197 db_set("project-code", zPCode, 0);
2198 }
2199
--- src/xfer.c
+++ src/xfer.c
@@ -49,16 +49,17 @@
49 int nDanglingFile; /* Number of dangling deltas received */
50 int mxSend; /* Stop sending "file" when pOut reaches this size */
51 int resync; /* Send igot cards for all holdings */
52 u8 syncPrivate; /* True to enable syncing private content */
53 u8 nextIsPrivate; /* If true, next "file" received is a private */
54 u32 clientVersion; /* Version of the client software */
55 time_t maxTime; /* Time when this transfer should be finished */
56 };
57
58
59 /*
60 ** The input blob contains an artifact. Convert it into a record ID.
61 ** Create a phantom record if no prior record exists and
62 ** phantomize is true.
63 **
64 ** Compare to uuid_to_rid(). This routine takes a blob argument
65 ** and does less error checking.
@@ -100,12 +101,12 @@
101 ** message. This routine finishes parsing that message and does
102 ** a record insert of the file.
103 **
104 ** The file line is in one of the following two forms:
105 **
106 ** file HASH SIZE \n CONTENT
107 ** file HASH DELTASRC SIZE \n CONTENT
108 **
109 ** The content is SIZE bytes immediately following the newline.
110 ** If DELTASRC exists, then the CONTENT is a delta against the
111 ** content of DELTASRC.
112 **
@@ -122,29 +123,30 @@
123 int *pnUuidList
124 ){
125 int n;
126 int rid;
127 int srcid = 0;
128 Blob content;
129 int isPriv;
130 Blob *pUuid;
131
132 isPriv = pXfer->nextIsPrivate;
133 pXfer->nextIsPrivate = 0;
134 if( pXfer->nToken<3
135 || pXfer->nToken>4
136 || !blob_is_hname(&pXfer->aToken[1])
137 || !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &n)
138 || n<0
139 || (pXfer->nToken==4 && !blob_is_hname(&pXfer->aToken[2]))
140 ){
141 blob_appendf(&pXfer->err, "malformed file line");
142 return;
143 }
144 blob_zero(&content);
 
145 blob_extract(pXfer->pIn, n, &content);
146 pUuid = &pXfer->aToken[1];
147 if( !cloneFlag && uuid_is_shunned(blob_str(pUuid)) ){
148 /* Ignore files that have been shunned */
149 blob_reset(&content);
150 return;
151 }
152 if( isPriv && !g.perm.Private ){
@@ -158,26 +160,26 @@
160 pXfer->nDeltaRcvd++;
161 }else{
162 srcid = 0;
163 pXfer->nFileRcvd++;
164 }
165 rid = content_put_ex(&content, blob_str(pUuid), srcid,
166 0, isPriv);
167 Th_AppendToList(pzUuidList, pnUuidList, blob_str(pUuid),
168 blob_size(pUuid));
169 remote_has(rid);
170 blob_reset(&content);
171 return;
172 }
173 if( pXfer->nToken==4 ){
174 Blob src, next;
175 srcid = rid_from_uuid(&pXfer->aToken[2], 1, isPriv);
176 if( content_get(srcid, &src)==0 ){
177 rid = content_put_ex(&content, blob_str(pUuid), srcid,
178 0, isPriv);
179 Th_AppendToList(pzUuidList, pnUuidList, blob_str(pUuid),
180 blob_size(pUuid));
181 pXfer->nDanglingFile++;
182 db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid);
183 if( !isPriv ) content_make_public(rid);
184 blob_reset(&src);
185 blob_reset(&content);
@@ -189,19 +191,15 @@
191 blob_reset(&content);
192 content = next;
193 }else{
194 pXfer->nFileRcvd++;
195 }
196 if( hname_verify_hash(&content, blob_buffer(pUuid), blob_size(pUuid))==0 ){
197 blob_appendf(&pXfer->err, "wrong hash on received artifact: %b", pUuid);
198 }
199 rid = content_put_ex(&content, blob_str(pUuid), 0, 0, isPriv);
200 Th_AppendToList(pzUuidList, pnUuidList, blob_str(pUuid), blob_size(pUuid));
 
 
 
 
201 if( rid==0 ){
202 blob_appendf(&pXfer->err, "%s", g.zErrMsg);
203 blob_reset(&content);
204 }else{
205 if( !isPriv ) content_make_public(rid);
@@ -217,18 +215,18 @@
215 ** a record insert of the file. The difference between "file" and
216 ** "cfile" is that with "cfile" the content is already compressed.
217 **
218 ** The file line is in one of the following two forms:
219 **
220 ** cfile HASH USIZE CSIZE \n CONTENT
221 ** cfile HASH DELTASRC USIZE CSIZE \n CONTENT
222 **
223 ** The content is CSIZE bytes immediately following the newline.
224 ** If DELTASRC exists, then the CONTENT is a delta against the
225 ** content of DELTASRC.
226 **
227 ** The original size of the HASH artifact is USIZE.
228 **
229 ** If any error occurs, write a message into pErr which has already
230 ** be initialized to an empty string.
231 **
232 ** Any artifact successfully received by this routine is considered to
@@ -248,15 +246,15 @@
246
247 isPriv = pXfer->nextIsPrivate;
248 pXfer->nextIsPrivate = 0;
249 if( pXfer->nToken<4
250 || pXfer->nToken>5
251 || !blob_is_hname(&pXfer->aToken[1])
252 || !blob_is_int(&pXfer->aToken[pXfer->nToken-2], &szU)
253 || !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &szC)
254 || szC<0 || szU<0
255 || (pXfer->nToken==5 && !blob_is_hname(&pXfer->aToken[2]))
256 ){
257 blob_appendf(&pXfer->err, "malformed cfile line");
258 return;
259 }
260 if( isPriv && !g.perm.Private ){
@@ -297,11 +295,11 @@
295 **
296 ** If the 0x0001 bit of FLAGS is set, that means the file has been
297 ** deleted, SIZE is zero, the HASH is "-", and the "\n CONTENT" is omitted.
298 **
299 ** SIZE is the number of bytes of CONTENT. The CONTENT is uncompressed.
300 ** HASH is the artifact hash of CONTENT.
301 **
302 ** If the 0x0004 bit of FLAGS is set, that means the CONTENT is omitted.
303 ** The sender might have omitted the content because it is too big to
304 ** transmit, or because it is unchanged and this record exists purely
305 ** to update the MTIME.
@@ -310,11 +308,10 @@
308 sqlite3_int64 mtime; /* The MTIME */
309 Blob *pHash; /* The HASH value */
310 int sz; /* The SIZE */
311 int flags; /* The FLAGS */
312 Blob content; /* The CONTENT */
 
313 Blob x; /* Compressed content */
314 Stmt q; /* SQL statements for comparison and insert */
315 int isDelete; /* HASH is "-" indicating this is a delete */
316 int nullContent; /* True of CONTENT is NULL */
317 int iStatus; /* Result from unversioned_status() */
@@ -321,25 +318,23 @@
318
319 pHash = &pXfer->aToken[3];
320 if( pXfer->nToken==5
321 || !blob_is_filename(&pXfer->aToken[1])
322 || !blob_is_int64(&pXfer->aToken[2], &mtime)
323 || (!blob_eq(pHash,"-") && !blob_is_hname(pHash))
324 || !blob_is_int(&pXfer->aToken[4], &sz)
325 || !blob_is_int(&pXfer->aToken[5], &flags)
326 ){
327 blob_appendf(&pXfer->err, "malformed uvfile line");
328 return;
329 }
330 blob_init(&content, 0, 0);
 
331 blob_init(&x, 0, 0);
332 if( sz>0 && (flags & 0x0005)==0 ){
333 blob_extract(pXfer->pIn, sz, &content);
334 nullContent = 0;
335 if( hname_verify_hash(&content, blob_buffer(pHash), blob_size(pHash))==0 ){
 
336 blob_appendf(&pXfer->err, "in uvfile line, HASH does not match CONTENT");
337 goto end_accept_unversioned_file;
338 }
339 }else{
340 nullContent = 1;
@@ -399,11 +394,10 @@
394 db_unset("uv-hash", 0);
395
396 end_accept_unversioned_file:
397 blob_reset(&x);
398 blob_reset(&content);
 
399 }
400
401 /*
402 ** Try to send a file as a delta against its parent.
403 ** If successful, return the number of bytes in the delta.
@@ -415,11 +409,11 @@
409 static int send_delta_parent(
410 Xfer *pXfer, /* The transfer context */
411 int rid, /* record id of the file to send */
412 int isPrivate, /* True if rid is a private artifact */
413 Blob *pContent, /* The content of the file to send */
414 Blob *pUuid /* The HASH of the file to send */
415 ){
416 static const char *const azQuery[] = {
417 "SELECT pid FROM plink x"
418 " WHERE cid=%d"
419 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)",
@@ -469,11 +463,11 @@
463 */
464 static int send_delta_native(
465 Xfer *pXfer, /* The transfer context */
466 int rid, /* record id of the file to send */
467 int isPrivate, /* True if rid is a private artifact */
468 Blob *pUuid /* The HASH of the file to send */
469 ){
470 Blob src, delta;
471 int size = 0;
472 int srcId;
473
@@ -500,15 +494,26 @@
494 }else{
495 size = 0;
496 }
497 return size;
498 }
499
500 /*
501 ** Push an error message to alert the older client that the repository
502 ** has SHA3 content and cannot be synced or cloned.
503 */
504 static void xfer_cannot_send_sha3_error(Xfer *pXfer){
505 blob_appendf(pXfer->pOut,
506 "error Fossil\\sversion\\s2.0\\sor\\slater\\srequired.\n"
507 );
508 }
509
510
511 /*
512 ** Send the file identified by rid.
513 **
514 ** The pUuid can be NULL in which case the correct hash is computed
515 ** from the rid.
516 **
517 ** Try to send the file as a native delta if nativeDelta is true, or
518 ** as a parent delta if nativeDelta is false.
519 **
@@ -527,10 +532,14 @@
532 }
533 blob_zero(&uuid);
534 db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d AND size>=0", rid);
535 if( blob_size(&uuid)==0 ){
536 return;
537 }
538 if( blob_size(&uuid)>HNAME_LEN_SHA1 && pXfer->clientVersion<20000 ){
539 xfer_cannot_send_sha3_error(pXfer);
540 return;
541 }
542 if( pUuid ){
543 if( blob_compare(pUuid, &uuid)!=0 ){
544 blob_reset(&uuid);
545 return;
@@ -617,10 +626,15 @@
626 szC = db_column_bytes(&q1, 2);
627 zContent = db_column_raw(&q1, 2);
628 srcIsPrivate = db_column_int(&q1, 3);
629 zDelta = db_column_text(&q1, 4);
630 if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1);
631 if( pXfer->clientVersion<20000 && db_column_bytes(&q1,0)!=HNAME_LEN_SHA1 ){
632 xfer_cannot_send_sha3_error(pXfer);
633 db_reset(&q1);
634 return;
635 }
636 blob_appendf(pXfer->pOut, "cfile %s ", zUuid);
637 if( !isPrivate && srcIsPrivate ){
638 content_get(rid, &fullContent);
639 szU = blob_size(&fullContent);
640 blob_compress(&fullContent, &fullContent);
@@ -676,10 +690,15 @@
690 );
691 }
692 if( db_step(&q1)==SQLITE_ROW ){
693 sqlite3_int64 mtime = db_column_int64(&q1, 0);
694 const char *zHash = db_column_text(&q1, 1);
695 if( pXfer->clientVersion<20000 && db_column_bytes(&q1,1)>HNAME_LEN_SHA1 ){
696 xfer_cannot_send_sha3_error(pXfer);
697 db_reset(&q1);
698 return;
699 }
700 if( blob_size(pXfer->pOut)>=pXfer->mxSend ){
701 /* If we have already reached the send size limit, send a (short)
702 ** uvigot card rather than a uvfile card. This only happens on the
703 ** server side. The uvigot card will provoke the client to resend
704 ** another uvgimme on the next cycle. */
@@ -728,23 +747,23 @@
747 }
748 db_finalize(&q);
749 }
750
751 /*
752 ** Compute an hash on the tail of pMsg. Verify that it matches the
753 ** the hash given in pHash. Return non-zero for an error and 0 on success.
754 **
755 ** The type of hash computed (SHA1, SHA3-256) is determined by
756 ** the length of the input hash in pHash.
757 */
758 static int check_tail_hash(Blob *pHash, Blob *pMsg){
759 Blob tail;
 
760 int rc;
761 blob_tail(pMsg, &tail);
762 rc = hname_verify_hash(&tail, blob_buffer(pHash), blob_size(pHash));
 
 
763 blob_reset(&tail);
764 return rc==HNAME_ERROR;
765 }
766
767 /*
768 ** Check the signature on an application/x-fossil payload received by
769 ** the HTTP server. The signature is a line of the following form:
@@ -1198,12 +1217,12 @@
1217 while( blob_line(xfer.pIn, &xfer.line) ){
1218 if( blob_buffer(&xfer.line)[0]=='#' ) continue;
1219 if( blob_size(&xfer.line)==0 ) continue;
1220 xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));
1221
1222 /* file HASH SIZE \n CONTENT
1223 ** file HASH DELTASRC SIZE \n CONTENT
1224 **
1225 ** Accept a file from the client.
1226 */
1227 if( blob_eq(&xfer.aToken[0], "file") ){
1228 if( !isPush ){
@@ -1219,12 +1238,12 @@
1238 nErr++;
1239 break;
1240 }
1241 }else
1242
1243 /* cfile HASH USIZE CSIZE \n CONTENT
1244 ** cfile HASH DELTASRC USIZE CSIZE \n CONTENT
1245 **
1246 ** Accept a file from the client.
1247 */
1248 if( blob_eq(&xfer.aToken[0], "cfile") ){
1249 if( !isPush ){
@@ -1254,17 +1273,17 @@
1273 nErr++;
1274 break;
1275 }
1276 }else
1277
1278 /* gimme HASH
1279 **
1280 ** Client is requesting a file. Send it.
1281 */
1282 if( blob_eq(&xfer.aToken[0], "gimme")
1283 && xfer.nToken==2
1284 && blob_is_hname(&xfer.aToken[1])
1285 ){
1286 nGimme++;
1287 if( isPull ){
1288 int rid = rid_from_uuid(&xfer.aToken[1], 0, 0);
1289 if( rid ){
@@ -1282,18 +1301,18 @@
1301 && blob_is_filename(&xfer.aToken[1])
1302 ){
1303 send_unversioned_file(&xfer, blob_str(&xfer.aToken[1]), 0);
1304 }else
1305
1306 /* igot HASH ?ISPRIVATE?
1307 **
1308 ** Client announces that it has a particular file. If the ISPRIVATE
1309 ** argument exists and is non-zero, then the file is a private file.
1310 */
1311 if( xfer.nToken>=2
1312 && blob_eq(&xfer.aToken[0], "igot")
1313 && blob_is_hname(&xfer.aToken[1])
1314 ){
1315 if( isPush ){
1316 if( xfer.nToken==2 || blob_eq(&xfer.aToken[2],"1")==0 ){
1317 rid_from_uuid(&xfer.aToken[1], 1, 0);
1318 }else if( g.perm.Private ){
@@ -1307,16 +1326,15 @@
1326
1327 /* pull SERVERCODE PROJECTCODE
1328 ** push SERVERCODE PROJECTCODE
1329 **
1330 ** The client wants either send or receive. The server should
1331 ** verify that the project code matches. The server code is ignored.
1332 */
1333 if( xfer.nToken==3
1334 && (blob_eq(&xfer.aToken[0], "pull") || blob_eq(&xfer.aToken[0], "push"))
1335 && blob_is_hname(&xfer.aToken[2])
 
1336 ){
1337 const char *zPCode;
1338 zPCode = db_get("project-code", 0);
1339 if( zPCode==0 ){
1340 fossil_panic("missing project code");
@@ -1534,19 +1552,27 @@
1552 ** Send igot cards for all known artifacts.
1553 */
1554 if( blob_eq(&xfer.aToken[1], "send-catalog") ){
1555 xfer.resync = 0x7fffffff;
1556 }
1557
1558 /* pragma client-version VERSION
1559 **
1560 ** Let the server know what version of Fossil is running on the client.
1561 */
1562 if( xfer.nToken>=3 && blob_eq(&xfer.aToken[1], "client-version") ){
1563 xfer.clientVersion = atoi(blob_str(&xfer.aToken[2]));
1564 }
1565
1566 /* pragma uv-hash HASH
1567 **
1568 ** The client wants to make sure that unversioned files are all synced.
1569 ** If the HASH does not match, send a complete catalog of
1570 ** "uvigot" cards.
1571 */
1572 if( blob_eq(&xfer.aToken[1], "uv-hash")
1573 && blob_is_hname(&xfer.aToken[2])
1574 ){
1575 if( !uvCatalogSent ){
1576 if( g.perm.Read && g.perm.WrUnver ){
1577 @ pragma uv-push-ok
1578 send_unversioned_catalog(&xfer);
@@ -1742,10 +1768,11 @@
1768 memset(&xfer, 0, sizeof(xfer));
1769 xfer.pIn = &recv;
1770 xfer.pOut = &send;
1771 xfer.mxSend = db_get_int("max-upload", 250000);
1772 xfer.maxTime = -1;
1773 xfer.clientVersion = RELEASE_VERSION_NUMBER;
1774 if( syncFlags & SYNC_PRIVATE ){
1775 g.perm.Private = 1;
1776 xfer.syncPrivate = 1;
1777 }
1778
@@ -1783,10 +1810,11 @@
1810 }
1811
1812 /*
1813 ** Always begin with a clone, pull, or push message
1814 */
1815 blob_appendf(&send, "pragma client-version %d\n", RELEASE_VERSION_NUMBER);
1816 if( syncFlags & SYNC_CLONE ){
1817 blob_appendf(&send, "clone 3 %d\n", cloneSeqno);
1818 syncFlags &= ~(SYNC_PUSH|SYNC_PULL);
1819 nCardSent++;
1820 /* TBD: Request all transferable configuration values */
@@ -1819,10 +1847,11 @@
1847 db_record_repository_filename(0);
1848 db_multi_exec(
1849 "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
1850 );
1851 manifest_crosslink_begin();
1852
1853
1854 /* Send back the most recently received cookie. Let the server
1855 ** figure out if this is a cookie that it cares about.
1856 */
1857 zCookie = db_get("cookie", 0);
@@ -1976,10 +2005,11 @@
2005 xfer.nGimmeSent = 0;
2006 xfer.nIGotSent = 0;
2007
2008 lastPctDone = -1;
2009 blob_reset(&send);
2010 blob_appendf(&send, "pragma client-version %d\n", RELEASE_VERSION_NUMBER);
2011 rArrivalTime = db_double(0.0, "SELECT julianday('now')");
2012
2013 /* Send the send-private pragma if we are trying to sync private data */
2014 if( syncFlags & SYNC_PRIVATE ){
2015 blob_append(&send, "pragma send-private\n", -1);
@@ -2028,22 +2058,22 @@
2058 lastPctDone = pctDone;
2059 fflush(stdout);
2060 }
2061 }
2062
2063 /* file HASH SIZE \n CONTENT
2064 ** file HASH DELTASRC SIZE \n CONTENT
2065 **
2066 ** Receive a file transmitted from the server.
2067 */
2068 if( blob_eq(&xfer.aToken[0],"file") ){
2069 xfer_accept_file(&xfer, (syncFlags & SYNC_CLONE)!=0, 0, 0);
2070 nArtifactRcvd++;
2071 }else
2072
2073 /* cfile HASH USIZE CSIZE \n CONTENT
2074 ** cfile HASH DELTASRC USIZE CSIZE \n CONTENT
2075 **
2076 ** Receive a compressed file transmitted from the server.
2077 */
2078 if( blob_eq(&xfer.aToken[0],"cfile") ){
2079 xfer_accept_compressed_file(&xfer, 0, 0);
@@ -2062,27 +2092,27 @@
2092 fossil_print("\rUnversioned-file received: %s\n",
2093 blob_str(&xfer.aToken[1]));
2094 }
2095 }else
2096
2097 /* gimme HASH
2098 **
2099 ** Server is requesting a file. If the file is a manifest, assume
2100 ** that the server will also want to know all of the content files
2101 ** associated with the manifest and send those too.
2102 */
2103 if( blob_eq(&xfer.aToken[0], "gimme")
2104 && xfer.nToken==2
2105 && blob_is_hname(&xfer.aToken[1])
2106 ){
2107 if( syncFlags & SYNC_PUSH ){
2108 int rid = rid_from_uuid(&xfer.aToken[1], 0, 0);
2109 if( rid ) send_file(&xfer, rid, &xfer.aToken[1], 0);
2110 }
2111 }else
2112
2113 /* igot HASH ?PRIVATEFLAG?
2114 **
2115 ** Server announces that it has a particular file. If this is
2116 ** not a file that we have and we are pulling, then create a
2117 ** phantom to cause this file to be requested on the next cycle.
2118 ** Always remember that the server has this file so that we do
@@ -2092,11 +2122,11 @@
2122 ** private. Pretend it does not exists if we are not pulling
2123 ** private files.
2124 */
2125 if( xfer.nToken>=2
2126 && blob_eq(&xfer.aToken[0], "igot")
2127 && blob_is_hname(&xfer.aToken[1])
2128 ){
2129 int rid;
2130 int isPriv = xfer.nToken>=3 && blob_eq(&xfer.aToken[2],"1");
2131 rid = rid_from_uuid(&xfer.aToken[1], 0, 0);
2132 if( rid>0 ){
@@ -2126,11 +2156,11 @@
2156 if( xfer.nToken==5
2157 && blob_eq(&xfer.aToken[0], "uvigot")
2158 && blob_is_filename(&xfer.aToken[1])
2159 && blob_is_int64(&xfer.aToken[2], &mtime)
2160 && blob_is_int(&xfer.aToken[4], &size)
2161 && (blob_eq(&xfer.aToken[3],"-") || blob_is_hname(&xfer.aToken[3]))
2162 ){
2163 const char *zName = blob_str(&xfer.aToken[1]);
2164 const char *zHash = blob_str(&xfer.aToken[3]);
2165 int iStatus;
2166 iStatus = unversioned_status(zName, mtime, zHash);
@@ -2188,11 +2218,11 @@
2218 ** the client what product to use for the new database.
2219 */
2220 if( blob_eq(&xfer.aToken[0],"push")
2221 && xfer.nToken==3
2222 && (syncFlags & SYNC_CLONE)!=0
2223 && blob_is_hname(&xfer.aToken[2])
2224 ){
2225 if( zPCode==0 ){
2226 zPCode = mprintf("%b", &xfer.aToken[2]);
2227 db_set("project-code", zPCode, 0);
2228 }
2229
+2 -5
--- src/zip.c
+++ src/zip.c
@@ -339,11 +339,11 @@
339339
content_get(rid, &mfile);
340340
if( blob_size(&mfile)==0 ){
341341
blob_zero(pZip);
342342
return;
343343
}
344
- blob_zero(&hash);
344
+ blob_set_dynamic(&hash, rid_to_uuid(rid));
345345
blob_zero(&filename);
346346
zip_open();
347347
348348
if( zDir && zDir[0] ){
349349
blob_appendf(&filename, "%s/", zDir);
@@ -378,13 +378,10 @@
378378
if( eflg & MFESTFLG_RAW ){
379379
blob_append(&filename, "manifest", -1);
380380
zName = blob_str(&filename);
381381
zip_add_folders(zName);
382382
}
383
- if( eflg & MFESTFLG_UUID ){
384
- sha1sum_blob(&mfile, &hash);
385
- }
386383
if( eflg & MFESTFLG_RAW ){
387384
sterilize_manifest(&mfile);
388385
zip_add_file(zName, &mfile, 0);
389386
}
390387
}
@@ -394,11 +391,10 @@
394391
blob_resize(&filename, nPrefix);
395392
blob_append(&filename, "manifest.uuid", -1);
396393
zName = blob_str(&filename);
397394
zip_add_folders(zName);
398395
zip_add_file(zName, &hash, 0);
399
- blob_reset(&hash);
400396
}
401397
if( eflg & MFESTFLG_TAGS ){
402398
Blob tagslist;
403399
blob_zero(&tagslist);
404400
get_checkin_taglist(rid, &tagslist);
@@ -429,10 +425,11 @@
429425
}else{
430426
blob_reset(&mfile);
431427
}
432428
manifest_destroy(pManifest);
433429
blob_reset(&filename);
430
+ blob_reset(&hash);
434431
zip_close(pZip);
435432
}
436433
437434
/*
438435
** COMMAND: zip*
439436
--- src/zip.c
+++ src/zip.c
@@ -339,11 +339,11 @@
339 content_get(rid, &mfile);
340 if( blob_size(&mfile)==0 ){
341 blob_zero(pZip);
342 return;
343 }
344 blob_zero(&hash);
345 blob_zero(&filename);
346 zip_open();
347
348 if( zDir && zDir[0] ){
349 blob_appendf(&filename, "%s/", zDir);
@@ -378,13 +378,10 @@
378 if( eflg & MFESTFLG_RAW ){
379 blob_append(&filename, "manifest", -1);
380 zName = blob_str(&filename);
381 zip_add_folders(zName);
382 }
383 if( eflg & MFESTFLG_UUID ){
384 sha1sum_blob(&mfile, &hash);
385 }
386 if( eflg & MFESTFLG_RAW ){
387 sterilize_manifest(&mfile);
388 zip_add_file(zName, &mfile, 0);
389 }
390 }
@@ -394,11 +391,10 @@
394 blob_resize(&filename, nPrefix);
395 blob_append(&filename, "manifest.uuid", -1);
396 zName = blob_str(&filename);
397 zip_add_folders(zName);
398 zip_add_file(zName, &hash, 0);
399 blob_reset(&hash);
400 }
401 if( eflg & MFESTFLG_TAGS ){
402 Blob tagslist;
403 blob_zero(&tagslist);
404 get_checkin_taglist(rid, &tagslist);
@@ -429,10 +425,11 @@
429 }else{
430 blob_reset(&mfile);
431 }
432 manifest_destroy(pManifest);
433 blob_reset(&filename);
 
434 zip_close(pZip);
435 }
436
437 /*
438 ** COMMAND: zip*
439
--- src/zip.c
+++ src/zip.c
@@ -339,11 +339,11 @@
339 content_get(rid, &mfile);
340 if( blob_size(&mfile)==0 ){
341 blob_zero(pZip);
342 return;
343 }
344 blob_set_dynamic(&hash, rid_to_uuid(rid));
345 blob_zero(&filename);
346 zip_open();
347
348 if( zDir && zDir[0] ){
349 blob_appendf(&filename, "%s/", zDir);
@@ -378,13 +378,10 @@
378 if( eflg & MFESTFLG_RAW ){
379 blob_append(&filename, "manifest", -1);
380 zName = blob_str(&filename);
381 zip_add_folders(zName);
382 }
 
 
 
383 if( eflg & MFESTFLG_RAW ){
384 sterilize_manifest(&mfile);
385 zip_add_file(zName, &mfile, 0);
386 }
387 }
@@ -394,11 +391,10 @@
391 blob_resize(&filename, nPrefix);
392 blob_append(&filename, "manifest.uuid", -1);
393 zName = blob_str(&filename);
394 zip_add_folders(zName);
395 zip_add_file(zName, &hash, 0);
 
396 }
397 if( eflg & MFESTFLG_TAGS ){
398 Blob tagslist;
399 blob_zero(&tagslist);
400 get_checkin_taglist(rid, &tagslist);
@@ -429,10 +425,11 @@
425 }else{
426 blob_reset(&mfile);
427 }
428 manifest_destroy(pManifest);
429 blob_reset(&filename);
430 blob_reset(&hash);
431 zip_close(pZip);
432 }
433
434 /*
435 ** COMMAND: zip*
436
+22 -4
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
2828
2929
SQLITE_OPTIONS = -DNDEBUG=1 -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_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_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
3030
3131
SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
3232
33
-SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.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 report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.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 wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
33
+SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.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 report_.c rss_.c schema_.c search_.c setup_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.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 wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
3434
35
-OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$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)\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)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$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)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$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)\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
35
+OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$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)\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)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$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)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$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)\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
3636
3737
3838
RC=$(DMDIR)\bin\rcc
3939
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
4040
@@ -49,11 +49,11 @@
4949
5050
$(OBJDIR)\fossil.res: $B\win\fossil.rc
5151
$(RC) $(RCFLAGS) -o$@ $**
5252
5353
$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54
- +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd dispatch doc encode event export file finfo foci fshell fusefs glob graph gzip 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 report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
54
+ +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd dispatch doc encode event export file finfo foci fshell fusefs 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 report rss schema search setup sha1 sha1hard sha3 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
5555
+echo fossil >> $@
5656
+echo fossil >> $@
5757
+echo $(LIBS) >> $@
5858
+echo. >> $@
5959
+echo fossil >> $@
@@ -356,10 +356,16 @@
356356
$(OBJDIR)\gzip$O : gzip_.c gzip.h
357357
$(TCC) -o$@ -c gzip_.c
358358
359359
gzip_.c : $(SRCDIR)\gzip.c
360360
+translate$E $** > $@
361
+
362
+$(OBJDIR)\hname$O : hname_.c hname.h
363
+ $(TCC) -o$@ -c hname_.c
364
+
365
+hname_.c : $(SRCDIR)\hname.c
366
+ +translate$E $** > $@
361367
362368
$(OBJDIR)\http$O : http_.c http.h
363369
$(TCC) -o$@ -c http_.c
364370
365371
http_.c : $(SRCDIR)\http.c
@@ -656,10 +662,22 @@
656662
$(OBJDIR)\sha1$O : sha1_.c sha1.h
657663
$(TCC) -o$@ -c sha1_.c
658664
659665
sha1_.c : $(SRCDIR)\sha1.c
660666
+translate$E $** > $@
667
+
668
+$(OBJDIR)\sha1hard$O : sha1hard_.c sha1hard.h
669
+ $(TCC) -o$@ -c sha1hard_.c
670
+
671
+sha1hard_.c : $(SRCDIR)\sha1hard.c
672
+ +translate$E $** > $@
673
+
674
+$(OBJDIR)\sha3$O : sha3_.c sha3.h
675
+ $(TCC) -o$@ -c sha3_.c
676
+
677
+sha3_.c : $(SRCDIR)\sha3.c
678
+ +translate$E $** > $@
661679
662680
$(OBJDIR)\shun$O : shun_.c shun.h
663681
$(TCC) -o$@ -c shun_.c
664682
665683
shun_.c : $(SRCDIR)\shun.c
@@ -856,7 +874,7 @@
856874
857875
zip_.c : $(SRCDIR)\zip.c
858876
+translate$E $** > $@
859877
860878
headers: makeheaders$E page_index.h builtin_data.h VERSION.h
861
- +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.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 captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fshell_.c:fshell.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.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 report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.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 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
879
+ +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.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 captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fshell_.c:fshell.h fusefs_.c:fusefs.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 report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.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 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 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
862880
@copy /Y nul: headers
863881
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
28
29 SQLITE_OPTIONS = -DNDEBUG=1 -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_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_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
30
31 SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.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 report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.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 wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$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)\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)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$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)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$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)\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
36
37
38 RC=$(DMDIR)\bin\rcc
39 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
40
@@ -49,11 +49,11 @@
49
50 $(OBJDIR)\fossil.res: $B\win\fossil.rc
51 $(RC) $(RCFLAGS) -o$@ $**
52
53 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54 +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd dispatch doc encode event export file finfo foci fshell fusefs glob graph gzip 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 report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
55 +echo fossil >> $@
56 +echo fossil >> $@
57 +echo $(LIBS) >> $@
58 +echo. >> $@
59 +echo fossil >> $@
@@ -356,10 +356,16 @@
356 $(OBJDIR)\gzip$O : gzip_.c gzip.h
357 $(TCC) -o$@ -c gzip_.c
358
359 gzip_.c : $(SRCDIR)\gzip.c
360 +translate$E $** > $@
 
 
 
 
 
 
361
362 $(OBJDIR)\http$O : http_.c http.h
363 $(TCC) -o$@ -c http_.c
364
365 http_.c : $(SRCDIR)\http.c
@@ -656,10 +662,22 @@
656 $(OBJDIR)\sha1$O : sha1_.c sha1.h
657 $(TCC) -o$@ -c sha1_.c
658
659 sha1_.c : $(SRCDIR)\sha1.c
660 +translate$E $** > $@
 
 
 
 
 
 
 
 
 
 
 
 
661
662 $(OBJDIR)\shun$O : shun_.c shun.h
663 $(TCC) -o$@ -c shun_.c
664
665 shun_.c : $(SRCDIR)\shun.c
@@ -856,7 +874,7 @@
856
857 zip_.c : $(SRCDIR)\zip.c
858 +translate$E $** > $@
859
860 headers: makeheaders$E page_index.h builtin_data.h VERSION.h
861 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.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 captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fshell_.c:fshell.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.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 report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.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 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
862 @copy /Y nul: headers
863
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
28
29 SQLITE_OPTIONS = -DNDEBUG=1 -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_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_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
30
31 SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.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 report_.c rss_.c schema_.c search_.c setup_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.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 wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$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)\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)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$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)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$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)\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
36
37
38 RC=$(DMDIR)\bin\rcc
39 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
40
@@ -49,11 +49,11 @@
49
50 $(OBJDIR)\fossil.res: $B\win\fossil.rc
51 $(RC) $(RCFLAGS) -o$@ $**
52
53 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54 +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd dispatch doc encode event export file finfo foci fshell fusefs 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 report rss schema search setup sha1 sha1hard sha3 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
55 +echo fossil >> $@
56 +echo fossil >> $@
57 +echo $(LIBS) >> $@
58 +echo. >> $@
59 +echo fossil >> $@
@@ -356,10 +356,16 @@
356 $(OBJDIR)\gzip$O : gzip_.c gzip.h
357 $(TCC) -o$@ -c gzip_.c
358
359 gzip_.c : $(SRCDIR)\gzip.c
360 +translate$E $** > $@
361
362 $(OBJDIR)\hname$O : hname_.c hname.h
363 $(TCC) -o$@ -c hname_.c
364
365 hname_.c : $(SRCDIR)\hname.c
366 +translate$E $** > $@
367
368 $(OBJDIR)\http$O : http_.c http.h
369 $(TCC) -o$@ -c http_.c
370
371 http_.c : $(SRCDIR)\http.c
@@ -656,10 +662,22 @@
662 $(OBJDIR)\sha1$O : sha1_.c sha1.h
663 $(TCC) -o$@ -c sha1_.c
664
665 sha1_.c : $(SRCDIR)\sha1.c
666 +translate$E $** > $@
667
668 $(OBJDIR)\sha1hard$O : sha1hard_.c sha1hard.h
669 $(TCC) -o$@ -c sha1hard_.c
670
671 sha1hard_.c : $(SRCDIR)\sha1hard.c
672 +translate$E $** > $@
673
674 $(OBJDIR)\sha3$O : sha3_.c sha3.h
675 $(TCC) -o$@ -c sha3_.c
676
677 sha3_.c : $(SRCDIR)\sha3.c
678 +translate$E $** > $@
679
680 $(OBJDIR)\shun$O : shun_.c shun.h
681 $(TCC) -o$@ -c shun_.c
682
683 shun_.c : $(SRCDIR)\shun.c
@@ -856,7 +874,7 @@
874
875 zip_.c : $(SRCDIR)\zip.c
876 +translate$E $** > $@
877
878 headers: makeheaders$E page_index.h builtin_data.h VERSION.h
879 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.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 captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fshell_.c:fshell.h fusefs_.c:fusefs.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 report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.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 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 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
880 @copy /Y nul: headers
881
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -461,10 +461,11 @@
461461
$(SRCDIR)/fshell.c \
462462
$(SRCDIR)/fusefs.c \
463463
$(SRCDIR)/glob.c \
464464
$(SRCDIR)/graph.c \
465465
$(SRCDIR)/gzip.c \
466
+ $(SRCDIR)/hname.c \
466467
$(SRCDIR)/http.c \
467468
$(SRCDIR)/http_socket.c \
468469
$(SRCDIR)/http_ssl.c \
469470
$(SRCDIR)/http_transport.c \
470471
$(SRCDIR)/import.c \
@@ -511,10 +512,12 @@
511512
$(SRCDIR)/rss.c \
512513
$(SRCDIR)/schema.c \
513514
$(SRCDIR)/search.c \
514515
$(SRCDIR)/setup.c \
515516
$(SRCDIR)/sha1.c \
517
+ $(SRCDIR)/sha1hard.c \
518
+ $(SRCDIR)/sha3.c \
516519
$(SRCDIR)/shun.c \
517520
$(SRCDIR)/sitemap.c \
518521
$(SRCDIR)/skins.c \
519522
$(SRCDIR)/sqlcmd.c \
520523
$(SRCDIR)/stash.c \
@@ -636,10 +639,11 @@
636639
$(OBJDIR)/fshell_.c \
637640
$(OBJDIR)/fusefs_.c \
638641
$(OBJDIR)/glob_.c \
639642
$(OBJDIR)/graph_.c \
640643
$(OBJDIR)/gzip_.c \
644
+ $(OBJDIR)/hname_.c \
641645
$(OBJDIR)/http_.c \
642646
$(OBJDIR)/http_socket_.c \
643647
$(OBJDIR)/http_ssl_.c \
644648
$(OBJDIR)/http_transport_.c \
645649
$(OBJDIR)/import_.c \
@@ -686,10 +690,12 @@
686690
$(OBJDIR)/rss_.c \
687691
$(OBJDIR)/schema_.c \
688692
$(OBJDIR)/search_.c \
689693
$(OBJDIR)/setup_.c \
690694
$(OBJDIR)/sha1_.c \
695
+ $(OBJDIR)/sha1hard_.c \
696
+ $(OBJDIR)/sha3_.c \
691697
$(OBJDIR)/shun_.c \
692698
$(OBJDIR)/sitemap_.c \
693699
$(OBJDIR)/skins_.c \
694700
$(OBJDIR)/sqlcmd_.c \
695701
$(OBJDIR)/stash_.c \
@@ -760,10 +766,11 @@
760766
$(OBJDIR)/fshell.o \
761767
$(OBJDIR)/fusefs.o \
762768
$(OBJDIR)/glob.o \
763769
$(OBJDIR)/graph.o \
764770
$(OBJDIR)/gzip.o \
771
+ $(OBJDIR)/hname.o \
765772
$(OBJDIR)/http.o \
766773
$(OBJDIR)/http_socket.o \
767774
$(OBJDIR)/http_ssl.o \
768775
$(OBJDIR)/http_transport.o \
769776
$(OBJDIR)/import.o \
@@ -810,10 +817,12 @@
810817
$(OBJDIR)/rss.o \
811818
$(OBJDIR)/schema.o \
812819
$(OBJDIR)/search.o \
813820
$(OBJDIR)/setup.o \
814821
$(OBJDIR)/sha1.o \
822
+ $(OBJDIR)/sha1hard.o \
823
+ $(OBJDIR)/sha3.o \
815824
$(OBJDIR)/shun.o \
816825
$(OBJDIR)/sitemap.o \
817826
$(OBJDIR)/skins.o \
818827
$(OBJDIR)/sqlcmd.o \
819828
$(OBJDIR)/stash.o \
@@ -1095,10 +1104,11 @@
10951104
$(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
10961105
$(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
10971106
$(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \
10981107
$(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \
10991108
$(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \
1109
+ $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \
11001110
$(OBJDIR)/http_.c:$(OBJDIR)/http.h \
11011111
$(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \
11021112
$(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \
11031113
$(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \
11041114
$(OBJDIR)/import_.c:$(OBJDIR)/import.h \
@@ -1145,10 +1155,12 @@
11451155
$(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
11461156
$(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
11471157
$(OBJDIR)/search_.c:$(OBJDIR)/search.h \
11481158
$(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
11491159
$(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
1160
+ $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \
1161
+ $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \
11501162
$(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
11511163
$(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
11521164
$(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
11531165
$(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
11541166
$(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
@@ -1498,10 +1510,18 @@
14981510
14991511
$(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h
15001512
$(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c
15011513
15021514
$(OBJDIR)/gzip.h: $(OBJDIR)/headers
1515
+
1516
+$(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(TRANSLATE)
1517
+ $(TRANSLATE) $(SRCDIR)/hname.c >$@
1518
+
1519
+$(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h
1520
+ $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c
1521
+
1522
+$(OBJDIR)/hname.h: $(OBJDIR)/headers
15031523
15041524
$(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE)
15051525
$(TRANSLATE) $(SRCDIR)/http.c >$@
15061526
15071527
$(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h
@@ -1898,10 +1918,26 @@
18981918
18991919
$(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h
19001920
$(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c
19011921
19021922
$(OBJDIR)/sha1.h: $(OBJDIR)/headers
1923
+
1924
+$(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(TRANSLATE)
1925
+ $(TRANSLATE) $(SRCDIR)/sha1hard.c >$@
1926
+
1927
+$(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h
1928
+ $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c
1929
+
1930
+$(OBJDIR)/sha1hard.h: $(OBJDIR)/headers
1931
+
1932
+$(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(TRANSLATE)
1933
+ $(TRANSLATE) $(SRCDIR)/sha3.c >$@
1934
+
1935
+$(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h
1936
+ $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c
1937
+
1938
+$(OBJDIR)/sha3.h: $(OBJDIR)/headers
19031939
19041940
$(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE)
19051941
$(TRANSLATE) $(SRCDIR)/shun.c >$@
19061942
19071943
$(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
19081944
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -461,10 +461,11 @@
461 $(SRCDIR)/fshell.c \
462 $(SRCDIR)/fusefs.c \
463 $(SRCDIR)/glob.c \
464 $(SRCDIR)/graph.c \
465 $(SRCDIR)/gzip.c \
 
466 $(SRCDIR)/http.c \
467 $(SRCDIR)/http_socket.c \
468 $(SRCDIR)/http_ssl.c \
469 $(SRCDIR)/http_transport.c \
470 $(SRCDIR)/import.c \
@@ -511,10 +512,12 @@
511 $(SRCDIR)/rss.c \
512 $(SRCDIR)/schema.c \
513 $(SRCDIR)/search.c \
514 $(SRCDIR)/setup.c \
515 $(SRCDIR)/sha1.c \
 
 
516 $(SRCDIR)/shun.c \
517 $(SRCDIR)/sitemap.c \
518 $(SRCDIR)/skins.c \
519 $(SRCDIR)/sqlcmd.c \
520 $(SRCDIR)/stash.c \
@@ -636,10 +639,11 @@
636 $(OBJDIR)/fshell_.c \
637 $(OBJDIR)/fusefs_.c \
638 $(OBJDIR)/glob_.c \
639 $(OBJDIR)/graph_.c \
640 $(OBJDIR)/gzip_.c \
 
641 $(OBJDIR)/http_.c \
642 $(OBJDIR)/http_socket_.c \
643 $(OBJDIR)/http_ssl_.c \
644 $(OBJDIR)/http_transport_.c \
645 $(OBJDIR)/import_.c \
@@ -686,10 +690,12 @@
686 $(OBJDIR)/rss_.c \
687 $(OBJDIR)/schema_.c \
688 $(OBJDIR)/search_.c \
689 $(OBJDIR)/setup_.c \
690 $(OBJDIR)/sha1_.c \
 
 
691 $(OBJDIR)/shun_.c \
692 $(OBJDIR)/sitemap_.c \
693 $(OBJDIR)/skins_.c \
694 $(OBJDIR)/sqlcmd_.c \
695 $(OBJDIR)/stash_.c \
@@ -760,10 +766,11 @@
760 $(OBJDIR)/fshell.o \
761 $(OBJDIR)/fusefs.o \
762 $(OBJDIR)/glob.o \
763 $(OBJDIR)/graph.o \
764 $(OBJDIR)/gzip.o \
 
765 $(OBJDIR)/http.o \
766 $(OBJDIR)/http_socket.o \
767 $(OBJDIR)/http_ssl.o \
768 $(OBJDIR)/http_transport.o \
769 $(OBJDIR)/import.o \
@@ -810,10 +817,12 @@
810 $(OBJDIR)/rss.o \
811 $(OBJDIR)/schema.o \
812 $(OBJDIR)/search.o \
813 $(OBJDIR)/setup.o \
814 $(OBJDIR)/sha1.o \
 
 
815 $(OBJDIR)/shun.o \
816 $(OBJDIR)/sitemap.o \
817 $(OBJDIR)/skins.o \
818 $(OBJDIR)/sqlcmd.o \
819 $(OBJDIR)/stash.o \
@@ -1095,10 +1104,11 @@
1095 $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
1096 $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
1097 $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \
1098 $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \
1099 $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \
 
1100 $(OBJDIR)/http_.c:$(OBJDIR)/http.h \
1101 $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \
1102 $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \
1103 $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \
1104 $(OBJDIR)/import_.c:$(OBJDIR)/import.h \
@@ -1145,10 +1155,12 @@
1145 $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
1146 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
1147 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
1148 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
1149 $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
 
 
1150 $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
1151 $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
1152 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
1153 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
1154 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
@@ -1498,10 +1510,18 @@
1498
1499 $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h
1500 $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c
1501
1502 $(OBJDIR)/gzip.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1503
1504 $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE)
1505 $(TRANSLATE) $(SRCDIR)/http.c >$@
1506
1507 $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h
@@ -1898,10 +1918,26 @@
1898
1899 $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h
1900 $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c
1901
1902 $(OBJDIR)/sha1.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1903
1904 $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE)
1905 $(TRANSLATE) $(SRCDIR)/shun.c >$@
1906
1907 $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
1908
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -461,10 +461,11 @@
461 $(SRCDIR)/fshell.c \
462 $(SRCDIR)/fusefs.c \
463 $(SRCDIR)/glob.c \
464 $(SRCDIR)/graph.c \
465 $(SRCDIR)/gzip.c \
466 $(SRCDIR)/hname.c \
467 $(SRCDIR)/http.c \
468 $(SRCDIR)/http_socket.c \
469 $(SRCDIR)/http_ssl.c \
470 $(SRCDIR)/http_transport.c \
471 $(SRCDIR)/import.c \
@@ -511,10 +512,12 @@
512 $(SRCDIR)/rss.c \
513 $(SRCDIR)/schema.c \
514 $(SRCDIR)/search.c \
515 $(SRCDIR)/setup.c \
516 $(SRCDIR)/sha1.c \
517 $(SRCDIR)/sha1hard.c \
518 $(SRCDIR)/sha3.c \
519 $(SRCDIR)/shun.c \
520 $(SRCDIR)/sitemap.c \
521 $(SRCDIR)/skins.c \
522 $(SRCDIR)/sqlcmd.c \
523 $(SRCDIR)/stash.c \
@@ -636,10 +639,11 @@
639 $(OBJDIR)/fshell_.c \
640 $(OBJDIR)/fusefs_.c \
641 $(OBJDIR)/glob_.c \
642 $(OBJDIR)/graph_.c \
643 $(OBJDIR)/gzip_.c \
644 $(OBJDIR)/hname_.c \
645 $(OBJDIR)/http_.c \
646 $(OBJDIR)/http_socket_.c \
647 $(OBJDIR)/http_ssl_.c \
648 $(OBJDIR)/http_transport_.c \
649 $(OBJDIR)/import_.c \
@@ -686,10 +690,12 @@
690 $(OBJDIR)/rss_.c \
691 $(OBJDIR)/schema_.c \
692 $(OBJDIR)/search_.c \
693 $(OBJDIR)/setup_.c \
694 $(OBJDIR)/sha1_.c \
695 $(OBJDIR)/sha1hard_.c \
696 $(OBJDIR)/sha3_.c \
697 $(OBJDIR)/shun_.c \
698 $(OBJDIR)/sitemap_.c \
699 $(OBJDIR)/skins_.c \
700 $(OBJDIR)/sqlcmd_.c \
701 $(OBJDIR)/stash_.c \
@@ -760,10 +766,11 @@
766 $(OBJDIR)/fshell.o \
767 $(OBJDIR)/fusefs.o \
768 $(OBJDIR)/glob.o \
769 $(OBJDIR)/graph.o \
770 $(OBJDIR)/gzip.o \
771 $(OBJDIR)/hname.o \
772 $(OBJDIR)/http.o \
773 $(OBJDIR)/http_socket.o \
774 $(OBJDIR)/http_ssl.o \
775 $(OBJDIR)/http_transport.o \
776 $(OBJDIR)/import.o \
@@ -810,10 +817,12 @@
817 $(OBJDIR)/rss.o \
818 $(OBJDIR)/schema.o \
819 $(OBJDIR)/search.o \
820 $(OBJDIR)/setup.o \
821 $(OBJDIR)/sha1.o \
822 $(OBJDIR)/sha1hard.o \
823 $(OBJDIR)/sha3.o \
824 $(OBJDIR)/shun.o \
825 $(OBJDIR)/sitemap.o \
826 $(OBJDIR)/skins.o \
827 $(OBJDIR)/sqlcmd.o \
828 $(OBJDIR)/stash.o \
@@ -1095,10 +1104,11 @@
1104 $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
1105 $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
1106 $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \
1107 $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \
1108 $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \
1109 $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \
1110 $(OBJDIR)/http_.c:$(OBJDIR)/http.h \
1111 $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \
1112 $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \
1113 $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \
1114 $(OBJDIR)/import_.c:$(OBJDIR)/import.h \
@@ -1145,10 +1155,12 @@
1155 $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
1156 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
1157 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
1158 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
1159 $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
1160 $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \
1161 $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \
1162 $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
1163 $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
1164 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
1165 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
1166 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
@@ -1498,10 +1510,18 @@
1510
1511 $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h
1512 $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c
1513
1514 $(OBJDIR)/gzip.h: $(OBJDIR)/headers
1515
1516 $(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(TRANSLATE)
1517 $(TRANSLATE) $(SRCDIR)/hname.c >$@
1518
1519 $(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h
1520 $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c
1521
1522 $(OBJDIR)/hname.h: $(OBJDIR)/headers
1523
1524 $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE)
1525 $(TRANSLATE) $(SRCDIR)/http.c >$@
1526
1527 $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h
@@ -1898,10 +1918,26 @@
1918
1919 $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h
1920 $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c
1921
1922 $(OBJDIR)/sha1.h: $(OBJDIR)/headers
1923
1924 $(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(TRANSLATE)
1925 $(TRANSLATE) $(SRCDIR)/sha1hard.c >$@
1926
1927 $(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h
1928 $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c
1929
1930 $(OBJDIR)/sha1hard.h: $(OBJDIR)/headers
1931
1932 $(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(TRANSLATE)
1933 $(TRANSLATE) $(SRCDIR)/sha3.c >$@
1934
1935 $(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h
1936 $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c
1937
1938 $(OBJDIR)/sha3.h: $(OBJDIR)/headers
1939
1940 $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE)
1941 $(TRANSLATE) $(SRCDIR)/shun.c >$@
1942
1943 $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
1944
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -461,10 +461,11 @@
461461
$(SRCDIR)/fshell.c \
462462
$(SRCDIR)/fusefs.c \
463463
$(SRCDIR)/glob.c \
464464
$(SRCDIR)/graph.c \
465465
$(SRCDIR)/gzip.c \
466
+ $(SRCDIR)/hname.c \
466467
$(SRCDIR)/http.c \
467468
$(SRCDIR)/http_socket.c \
468469
$(SRCDIR)/http_ssl.c \
469470
$(SRCDIR)/http_transport.c \
470471
$(SRCDIR)/import.c \
@@ -511,10 +512,12 @@
511512
$(SRCDIR)/rss.c \
512513
$(SRCDIR)/schema.c \
513514
$(SRCDIR)/search.c \
514515
$(SRCDIR)/setup.c \
515516
$(SRCDIR)/sha1.c \
517
+ $(SRCDIR)/sha1hard.c \
518
+ $(SRCDIR)/sha3.c \
516519
$(SRCDIR)/shun.c \
517520
$(SRCDIR)/sitemap.c \
518521
$(SRCDIR)/skins.c \
519522
$(SRCDIR)/sqlcmd.c \
520523
$(SRCDIR)/stash.c \
@@ -636,10 +639,11 @@
636639
$(OBJDIR)/fshell_.c \
637640
$(OBJDIR)/fusefs_.c \
638641
$(OBJDIR)/glob_.c \
639642
$(OBJDIR)/graph_.c \
640643
$(OBJDIR)/gzip_.c \
644
+ $(OBJDIR)/hname_.c \
641645
$(OBJDIR)/http_.c \
642646
$(OBJDIR)/http_socket_.c \
643647
$(OBJDIR)/http_ssl_.c \
644648
$(OBJDIR)/http_transport_.c \
645649
$(OBJDIR)/import_.c \
@@ -686,10 +690,12 @@
686690
$(OBJDIR)/rss_.c \
687691
$(OBJDIR)/schema_.c \
688692
$(OBJDIR)/search_.c \
689693
$(OBJDIR)/setup_.c \
690694
$(OBJDIR)/sha1_.c \
695
+ $(OBJDIR)/sha1hard_.c \
696
+ $(OBJDIR)/sha3_.c \
691697
$(OBJDIR)/shun_.c \
692698
$(OBJDIR)/sitemap_.c \
693699
$(OBJDIR)/skins_.c \
694700
$(OBJDIR)/sqlcmd_.c \
695701
$(OBJDIR)/stash_.c \
@@ -760,10 +766,11 @@
760766
$(OBJDIR)/fshell.o \
761767
$(OBJDIR)/fusefs.o \
762768
$(OBJDIR)/glob.o \
763769
$(OBJDIR)/graph.o \
764770
$(OBJDIR)/gzip.o \
771
+ $(OBJDIR)/hname.o \
765772
$(OBJDIR)/http.o \
766773
$(OBJDIR)/http_socket.o \
767774
$(OBJDIR)/http_ssl.o \
768775
$(OBJDIR)/http_transport.o \
769776
$(OBJDIR)/import.o \
@@ -810,10 +817,12 @@
810817
$(OBJDIR)/rss.o \
811818
$(OBJDIR)/schema.o \
812819
$(OBJDIR)/search.o \
813820
$(OBJDIR)/setup.o \
814821
$(OBJDIR)/sha1.o \
822
+ $(OBJDIR)/sha1hard.o \
823
+ $(OBJDIR)/sha3.o \
815824
$(OBJDIR)/shun.o \
816825
$(OBJDIR)/sitemap.o \
817826
$(OBJDIR)/skins.o \
818827
$(OBJDIR)/sqlcmd.o \
819828
$(OBJDIR)/stash.o \
@@ -1095,10 +1104,11 @@
10951104
$(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
10961105
$(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
10971106
$(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \
10981107
$(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \
10991108
$(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \
1109
+ $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \
11001110
$(OBJDIR)/http_.c:$(OBJDIR)/http.h \
11011111
$(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \
11021112
$(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \
11031113
$(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \
11041114
$(OBJDIR)/import_.c:$(OBJDIR)/import.h \
@@ -1145,10 +1155,12 @@
11451155
$(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
11461156
$(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
11471157
$(OBJDIR)/search_.c:$(OBJDIR)/search.h \
11481158
$(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
11491159
$(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
1160
+ $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \
1161
+ $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \
11501162
$(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
11511163
$(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
11521164
$(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
11531165
$(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
11541166
$(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
@@ -1498,10 +1510,18 @@
14981510
14991511
$(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h
15001512
$(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c
15011513
15021514
$(OBJDIR)/gzip.h: $(OBJDIR)/headers
1515
+
1516
+$(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(TRANSLATE)
1517
+ $(TRANSLATE) $(SRCDIR)/hname.c >$@
1518
+
1519
+$(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h
1520
+ $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c
1521
+
1522
+$(OBJDIR)/hname.h: $(OBJDIR)/headers
15031523
15041524
$(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE)
15051525
$(TRANSLATE) $(SRCDIR)/http.c >$@
15061526
15071527
$(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h
@@ -1898,10 +1918,26 @@
18981918
18991919
$(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h
19001920
$(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c
19011921
19021922
$(OBJDIR)/sha1.h: $(OBJDIR)/headers
1923
+
1924
+$(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(TRANSLATE)
1925
+ $(TRANSLATE) $(SRCDIR)/sha1hard.c >$@
1926
+
1927
+$(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h
1928
+ $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c
1929
+
1930
+$(OBJDIR)/sha1hard.h: $(OBJDIR)/headers
1931
+
1932
+$(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(TRANSLATE)
1933
+ $(TRANSLATE) $(SRCDIR)/sha3.c >$@
1934
+
1935
+$(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h
1936
+ $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c
1937
+
1938
+$(OBJDIR)/sha3.h: $(OBJDIR)/headers
19031939
19041940
$(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE)
19051941
$(TRANSLATE) $(SRCDIR)/shun.c >$@
19061942
19071943
$(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
19081944
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -461,10 +461,11 @@
461 $(SRCDIR)/fshell.c \
462 $(SRCDIR)/fusefs.c \
463 $(SRCDIR)/glob.c \
464 $(SRCDIR)/graph.c \
465 $(SRCDIR)/gzip.c \
 
466 $(SRCDIR)/http.c \
467 $(SRCDIR)/http_socket.c \
468 $(SRCDIR)/http_ssl.c \
469 $(SRCDIR)/http_transport.c \
470 $(SRCDIR)/import.c \
@@ -511,10 +512,12 @@
511 $(SRCDIR)/rss.c \
512 $(SRCDIR)/schema.c \
513 $(SRCDIR)/search.c \
514 $(SRCDIR)/setup.c \
515 $(SRCDIR)/sha1.c \
 
 
516 $(SRCDIR)/shun.c \
517 $(SRCDIR)/sitemap.c \
518 $(SRCDIR)/skins.c \
519 $(SRCDIR)/sqlcmd.c \
520 $(SRCDIR)/stash.c \
@@ -636,10 +639,11 @@
636 $(OBJDIR)/fshell_.c \
637 $(OBJDIR)/fusefs_.c \
638 $(OBJDIR)/glob_.c \
639 $(OBJDIR)/graph_.c \
640 $(OBJDIR)/gzip_.c \
 
641 $(OBJDIR)/http_.c \
642 $(OBJDIR)/http_socket_.c \
643 $(OBJDIR)/http_ssl_.c \
644 $(OBJDIR)/http_transport_.c \
645 $(OBJDIR)/import_.c \
@@ -686,10 +690,12 @@
686 $(OBJDIR)/rss_.c \
687 $(OBJDIR)/schema_.c \
688 $(OBJDIR)/search_.c \
689 $(OBJDIR)/setup_.c \
690 $(OBJDIR)/sha1_.c \
 
 
691 $(OBJDIR)/shun_.c \
692 $(OBJDIR)/sitemap_.c \
693 $(OBJDIR)/skins_.c \
694 $(OBJDIR)/sqlcmd_.c \
695 $(OBJDIR)/stash_.c \
@@ -760,10 +766,11 @@
760 $(OBJDIR)/fshell.o \
761 $(OBJDIR)/fusefs.o \
762 $(OBJDIR)/glob.o \
763 $(OBJDIR)/graph.o \
764 $(OBJDIR)/gzip.o \
 
765 $(OBJDIR)/http.o \
766 $(OBJDIR)/http_socket.o \
767 $(OBJDIR)/http_ssl.o \
768 $(OBJDIR)/http_transport.o \
769 $(OBJDIR)/import.o \
@@ -810,10 +817,12 @@
810 $(OBJDIR)/rss.o \
811 $(OBJDIR)/schema.o \
812 $(OBJDIR)/search.o \
813 $(OBJDIR)/setup.o \
814 $(OBJDIR)/sha1.o \
 
 
815 $(OBJDIR)/shun.o \
816 $(OBJDIR)/sitemap.o \
817 $(OBJDIR)/skins.o \
818 $(OBJDIR)/sqlcmd.o \
819 $(OBJDIR)/stash.o \
@@ -1095,10 +1104,11 @@
1095 $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
1096 $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
1097 $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \
1098 $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \
1099 $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \
 
1100 $(OBJDIR)/http_.c:$(OBJDIR)/http.h \
1101 $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \
1102 $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \
1103 $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \
1104 $(OBJDIR)/import_.c:$(OBJDIR)/import.h \
@@ -1145,10 +1155,12 @@
1145 $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
1146 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
1147 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
1148 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
1149 $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
 
 
1150 $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
1151 $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
1152 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
1153 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
1154 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
@@ -1498,10 +1510,18 @@
1498
1499 $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h
1500 $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c
1501
1502 $(OBJDIR)/gzip.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1503
1504 $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE)
1505 $(TRANSLATE) $(SRCDIR)/http.c >$@
1506
1507 $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h
@@ -1898,10 +1918,26 @@
1898
1899 $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h
1900 $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c
1901
1902 $(OBJDIR)/sha1.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1903
1904 $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE)
1905 $(TRANSLATE) $(SRCDIR)/shun.c >$@
1906
1907 $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
1908
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -461,10 +461,11 @@
461 $(SRCDIR)/fshell.c \
462 $(SRCDIR)/fusefs.c \
463 $(SRCDIR)/glob.c \
464 $(SRCDIR)/graph.c \
465 $(SRCDIR)/gzip.c \
466 $(SRCDIR)/hname.c \
467 $(SRCDIR)/http.c \
468 $(SRCDIR)/http_socket.c \
469 $(SRCDIR)/http_ssl.c \
470 $(SRCDIR)/http_transport.c \
471 $(SRCDIR)/import.c \
@@ -511,10 +512,12 @@
512 $(SRCDIR)/rss.c \
513 $(SRCDIR)/schema.c \
514 $(SRCDIR)/search.c \
515 $(SRCDIR)/setup.c \
516 $(SRCDIR)/sha1.c \
517 $(SRCDIR)/sha1hard.c \
518 $(SRCDIR)/sha3.c \
519 $(SRCDIR)/shun.c \
520 $(SRCDIR)/sitemap.c \
521 $(SRCDIR)/skins.c \
522 $(SRCDIR)/sqlcmd.c \
523 $(SRCDIR)/stash.c \
@@ -636,10 +639,11 @@
639 $(OBJDIR)/fshell_.c \
640 $(OBJDIR)/fusefs_.c \
641 $(OBJDIR)/glob_.c \
642 $(OBJDIR)/graph_.c \
643 $(OBJDIR)/gzip_.c \
644 $(OBJDIR)/hname_.c \
645 $(OBJDIR)/http_.c \
646 $(OBJDIR)/http_socket_.c \
647 $(OBJDIR)/http_ssl_.c \
648 $(OBJDIR)/http_transport_.c \
649 $(OBJDIR)/import_.c \
@@ -686,10 +690,12 @@
690 $(OBJDIR)/rss_.c \
691 $(OBJDIR)/schema_.c \
692 $(OBJDIR)/search_.c \
693 $(OBJDIR)/setup_.c \
694 $(OBJDIR)/sha1_.c \
695 $(OBJDIR)/sha1hard_.c \
696 $(OBJDIR)/sha3_.c \
697 $(OBJDIR)/shun_.c \
698 $(OBJDIR)/sitemap_.c \
699 $(OBJDIR)/skins_.c \
700 $(OBJDIR)/sqlcmd_.c \
701 $(OBJDIR)/stash_.c \
@@ -760,10 +766,11 @@
766 $(OBJDIR)/fshell.o \
767 $(OBJDIR)/fusefs.o \
768 $(OBJDIR)/glob.o \
769 $(OBJDIR)/graph.o \
770 $(OBJDIR)/gzip.o \
771 $(OBJDIR)/hname.o \
772 $(OBJDIR)/http.o \
773 $(OBJDIR)/http_socket.o \
774 $(OBJDIR)/http_ssl.o \
775 $(OBJDIR)/http_transport.o \
776 $(OBJDIR)/import.o \
@@ -810,10 +817,12 @@
817 $(OBJDIR)/rss.o \
818 $(OBJDIR)/schema.o \
819 $(OBJDIR)/search.o \
820 $(OBJDIR)/setup.o \
821 $(OBJDIR)/sha1.o \
822 $(OBJDIR)/sha1hard.o \
823 $(OBJDIR)/sha3.o \
824 $(OBJDIR)/shun.o \
825 $(OBJDIR)/sitemap.o \
826 $(OBJDIR)/skins.o \
827 $(OBJDIR)/sqlcmd.o \
828 $(OBJDIR)/stash.o \
@@ -1095,10 +1104,11 @@
1104 $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
1105 $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
1106 $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \
1107 $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \
1108 $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \
1109 $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \
1110 $(OBJDIR)/http_.c:$(OBJDIR)/http.h \
1111 $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \
1112 $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \
1113 $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \
1114 $(OBJDIR)/import_.c:$(OBJDIR)/import.h \
@@ -1145,10 +1155,12 @@
1155 $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
1156 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
1157 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
1158 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
1159 $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
1160 $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \
1161 $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \
1162 $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
1163 $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
1164 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
1165 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
1166 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
@@ -1498,10 +1510,18 @@
1510
1511 $(OBJDIR)/gzip.o: $(OBJDIR)/gzip_.c $(OBJDIR)/gzip.h $(SRCDIR)/config.h
1512 $(XTCC) -o $(OBJDIR)/gzip.o -c $(OBJDIR)/gzip_.c
1513
1514 $(OBJDIR)/gzip.h: $(OBJDIR)/headers
1515
1516 $(OBJDIR)/hname_.c: $(SRCDIR)/hname.c $(TRANSLATE)
1517 $(TRANSLATE) $(SRCDIR)/hname.c >$@
1518
1519 $(OBJDIR)/hname.o: $(OBJDIR)/hname_.c $(OBJDIR)/hname.h $(SRCDIR)/config.h
1520 $(XTCC) -o $(OBJDIR)/hname.o -c $(OBJDIR)/hname_.c
1521
1522 $(OBJDIR)/hname.h: $(OBJDIR)/headers
1523
1524 $(OBJDIR)/http_.c: $(SRCDIR)/http.c $(TRANSLATE)
1525 $(TRANSLATE) $(SRCDIR)/http.c >$@
1526
1527 $(OBJDIR)/http.o: $(OBJDIR)/http_.c $(OBJDIR)/http.h $(SRCDIR)/config.h
@@ -1898,10 +1918,26 @@
1918
1919 $(OBJDIR)/sha1.o: $(OBJDIR)/sha1_.c $(OBJDIR)/sha1.h $(SRCDIR)/config.h
1920 $(XTCC) -o $(OBJDIR)/sha1.o -c $(OBJDIR)/sha1_.c
1921
1922 $(OBJDIR)/sha1.h: $(OBJDIR)/headers
1923
1924 $(OBJDIR)/sha1hard_.c: $(SRCDIR)/sha1hard.c $(TRANSLATE)
1925 $(TRANSLATE) $(SRCDIR)/sha1hard.c >$@
1926
1927 $(OBJDIR)/sha1hard.o: $(OBJDIR)/sha1hard_.c $(OBJDIR)/sha1hard.h $(SRCDIR)/config.h
1928 $(XTCC) -o $(OBJDIR)/sha1hard.o -c $(OBJDIR)/sha1hard_.c
1929
1930 $(OBJDIR)/sha1hard.h: $(OBJDIR)/headers
1931
1932 $(OBJDIR)/sha3_.c: $(SRCDIR)/sha3.c $(TRANSLATE)
1933 $(TRANSLATE) $(SRCDIR)/sha3.c >$@
1934
1935 $(OBJDIR)/sha3.o: $(OBJDIR)/sha3_.c $(OBJDIR)/sha3.h $(SRCDIR)/config.h
1936 $(XTCC) -o $(OBJDIR)/sha3.o -c $(OBJDIR)/sha3_.c
1937
1938 $(OBJDIR)/sha3.h: $(OBJDIR)/headers
1939
1940 $(OBJDIR)/shun_.c: $(SRCDIR)/shun.c $(TRANSLATE)
1941 $(TRANSLATE) $(SRCDIR)/shun.c >$@
1942
1943 $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
1944
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -386,10 +386,11 @@
386386
fshell_.c \
387387
fusefs_.c \
388388
glob_.c \
389389
graph_.c \
390390
gzip_.c \
391
+ hname_.c \
391392
http_.c \
392393
http_socket_.c \
393394
http_ssl_.c \
394395
http_transport_.c \
395396
import_.c \
@@ -436,10 +437,12 @@
436437
rss_.c \
437438
schema_.c \
438439
search_.c \
439440
setup_.c \
440441
sha1_.c \
442
+ sha1hard_.c \
443
+ sha3_.c \
441444
shun_.c \
442445
sitemap_.c \
443446
skins_.c \
444447
sqlcmd_.c \
445448
stash_.c \
@@ -560,10 +563,11 @@
560563
$(OX)\fshell$O \
561564
$(OX)\fusefs$O \
562565
$(OX)\glob$O \
563566
$(OX)\graph$O \
564567
$(OX)\gzip$O \
568
+ $(OX)\hname$O \
565569
$(OX)\http$O \
566570
$(OX)\http_socket$O \
567571
$(OX)\http_ssl$O \
568572
$(OX)\http_transport$O \
569573
$(OX)\import$O \
@@ -610,10 +614,12 @@
610614
$(OX)\rss$O \
611615
$(OX)\schema$O \
612616
$(OX)\search$O \
613617
$(OX)\setup$O \
614618
$(OX)\sha1$O \
619
+ $(OX)\sha1hard$O \
620
+ $(OX)\sha3$O \
615621
$(OX)\shell$O \
616622
$(OX)\shun$O \
617623
$(OX)\sitemap$O \
618624
$(OX)\skins$O \
619625
$(OX)\sqlcmd$O \
@@ -743,10 +749,11 @@
743749
echo $(OX)\fshell.obj >> $@
744750
echo $(OX)\fusefs.obj >> $@
745751
echo $(OX)\glob.obj >> $@
746752
echo $(OX)\graph.obj >> $@
747753
echo $(OX)\gzip.obj >> $@
754
+ echo $(OX)\hname.obj >> $@
748755
echo $(OX)\http.obj >> $@
749756
echo $(OX)\http_socket.obj >> $@
750757
echo $(OX)\http_ssl.obj >> $@
751758
echo $(OX)\http_transport.obj >> $@
752759
echo $(OX)\import.obj >> $@
@@ -793,10 +800,12 @@
793800
echo $(OX)\rss.obj >> $@
794801
echo $(OX)\schema.obj >> $@
795802
echo $(OX)\search.obj >> $@
796803
echo $(OX)\setup.obj >> $@
797804
echo $(OX)\sha1.obj >> $@
805
+ echo $(OX)\sha1hard.obj >> $@
806
+ echo $(OX)\sha3.obj >> $@
798807
echo $(OX)\shell.obj >> $@
799808
echo $(OX)\shun.obj >> $@
800809
echo $(OX)\sitemap.obj >> $@
801810
echo $(OX)\skins.obj >> $@
802811
echo $(OX)\sqlcmd.obj >> $@
@@ -1175,10 +1184,16 @@
11751184
$(OX)\gzip$O : gzip_.c gzip.h
11761185
$(TCC) /Fo$@ -c gzip_.c
11771186
11781187
gzip_.c : $(SRCDIR)\gzip.c
11791188
translate$E $** > $@
1189
+
1190
+$(OX)\hname$O : hname_.c hname.h
1191
+ $(TCC) /Fo$@ -c hname_.c
1192
+
1193
+hname_.c : $(SRCDIR)\hname.c
1194
+ translate$E $** > $@
11801195
11811196
$(OX)\http$O : http_.c http.h
11821197
$(TCC) /Fo$@ -c http_.c
11831198
11841199
http_.c : $(SRCDIR)\http.c
@@ -1475,10 +1490,22 @@
14751490
$(OX)\sha1$O : sha1_.c sha1.h
14761491
$(TCC) /Fo$@ -c sha1_.c
14771492
14781493
sha1_.c : $(SRCDIR)\sha1.c
14791494
translate$E $** > $@
1495
+
1496
+$(OX)\sha1hard$O : sha1hard_.c sha1hard.h
1497
+ $(TCC) /Fo$@ -c sha1hard_.c
1498
+
1499
+sha1hard_.c : $(SRCDIR)\sha1hard.c
1500
+ translate$E $** > $@
1501
+
1502
+$(OX)\sha3$O : sha3_.c sha3.h
1503
+ $(TCC) /Fo$@ -c sha3_.c
1504
+
1505
+sha3_.c : $(SRCDIR)\sha3.c
1506
+ translate$E $** > $@
14801507
14811508
$(OX)\shun$O : shun_.c shun.h
14821509
$(TCC) /Fo$@ -c shun_.c
14831510
14841511
shun_.c : $(SRCDIR)\shun.c
@@ -1717,10 +1744,11 @@
17171744
fshell_.c:fshell.h \
17181745
fusefs_.c:fusefs.h \
17191746
glob_.c:glob.h \
17201747
graph_.c:graph.h \
17211748
gzip_.c:gzip.h \
1749
+ hname_.c:hname.h \
17221750
http_.c:http.h \
17231751
http_socket_.c:http_socket.h \
17241752
http_ssl_.c:http_ssl.h \
17251753
http_transport_.c:http_transport.h \
17261754
import_.c:import.h \
@@ -1767,10 +1795,12 @@
17671795
rss_.c:rss.h \
17681796
schema_.c:schema.h \
17691797
search_.c:search.h \
17701798
setup_.c:setup.h \
17711799
sha1_.c:sha1.h \
1800
+ sha1hard_.c:sha1hard.h \
1801
+ sha3_.c:sha3.h \
17721802
shun_.c:shun.h \
17731803
sitemap_.c:sitemap.h \
17741804
skins_.c:skins.h \
17751805
sqlcmd_.c:sqlcmd.h \
17761806
stash_.c:stash.h \
17771807
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -386,10 +386,11 @@
386 fshell_.c \
387 fusefs_.c \
388 glob_.c \
389 graph_.c \
390 gzip_.c \
 
391 http_.c \
392 http_socket_.c \
393 http_ssl_.c \
394 http_transport_.c \
395 import_.c \
@@ -436,10 +437,12 @@
436 rss_.c \
437 schema_.c \
438 search_.c \
439 setup_.c \
440 sha1_.c \
 
 
441 shun_.c \
442 sitemap_.c \
443 skins_.c \
444 sqlcmd_.c \
445 stash_.c \
@@ -560,10 +563,11 @@
560 $(OX)\fshell$O \
561 $(OX)\fusefs$O \
562 $(OX)\glob$O \
563 $(OX)\graph$O \
564 $(OX)\gzip$O \
 
565 $(OX)\http$O \
566 $(OX)\http_socket$O \
567 $(OX)\http_ssl$O \
568 $(OX)\http_transport$O \
569 $(OX)\import$O \
@@ -610,10 +614,12 @@
610 $(OX)\rss$O \
611 $(OX)\schema$O \
612 $(OX)\search$O \
613 $(OX)\setup$O \
614 $(OX)\sha1$O \
 
 
615 $(OX)\shell$O \
616 $(OX)\shun$O \
617 $(OX)\sitemap$O \
618 $(OX)\skins$O \
619 $(OX)\sqlcmd$O \
@@ -743,10 +749,11 @@
743 echo $(OX)\fshell.obj >> $@
744 echo $(OX)\fusefs.obj >> $@
745 echo $(OX)\glob.obj >> $@
746 echo $(OX)\graph.obj >> $@
747 echo $(OX)\gzip.obj >> $@
 
748 echo $(OX)\http.obj >> $@
749 echo $(OX)\http_socket.obj >> $@
750 echo $(OX)\http_ssl.obj >> $@
751 echo $(OX)\http_transport.obj >> $@
752 echo $(OX)\import.obj >> $@
@@ -793,10 +800,12 @@
793 echo $(OX)\rss.obj >> $@
794 echo $(OX)\schema.obj >> $@
795 echo $(OX)\search.obj >> $@
796 echo $(OX)\setup.obj >> $@
797 echo $(OX)\sha1.obj >> $@
 
 
798 echo $(OX)\shell.obj >> $@
799 echo $(OX)\shun.obj >> $@
800 echo $(OX)\sitemap.obj >> $@
801 echo $(OX)\skins.obj >> $@
802 echo $(OX)\sqlcmd.obj >> $@
@@ -1175,10 +1184,16 @@
1175 $(OX)\gzip$O : gzip_.c gzip.h
1176 $(TCC) /Fo$@ -c gzip_.c
1177
1178 gzip_.c : $(SRCDIR)\gzip.c
1179 translate$E $** > $@
 
 
 
 
 
 
1180
1181 $(OX)\http$O : http_.c http.h
1182 $(TCC) /Fo$@ -c http_.c
1183
1184 http_.c : $(SRCDIR)\http.c
@@ -1475,10 +1490,22 @@
1475 $(OX)\sha1$O : sha1_.c sha1.h
1476 $(TCC) /Fo$@ -c sha1_.c
1477
1478 sha1_.c : $(SRCDIR)\sha1.c
1479 translate$E $** > $@
 
 
 
 
 
 
 
 
 
 
 
 
1480
1481 $(OX)\shun$O : shun_.c shun.h
1482 $(TCC) /Fo$@ -c shun_.c
1483
1484 shun_.c : $(SRCDIR)\shun.c
@@ -1717,10 +1744,11 @@
1717 fshell_.c:fshell.h \
1718 fusefs_.c:fusefs.h \
1719 glob_.c:glob.h \
1720 graph_.c:graph.h \
1721 gzip_.c:gzip.h \
 
1722 http_.c:http.h \
1723 http_socket_.c:http_socket.h \
1724 http_ssl_.c:http_ssl.h \
1725 http_transport_.c:http_transport.h \
1726 import_.c:import.h \
@@ -1767,10 +1795,12 @@
1767 rss_.c:rss.h \
1768 schema_.c:schema.h \
1769 search_.c:search.h \
1770 setup_.c:setup.h \
1771 sha1_.c:sha1.h \
 
 
1772 shun_.c:shun.h \
1773 sitemap_.c:sitemap.h \
1774 skins_.c:skins.h \
1775 sqlcmd_.c:sqlcmd.h \
1776 stash_.c:stash.h \
1777
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -386,10 +386,11 @@
386 fshell_.c \
387 fusefs_.c \
388 glob_.c \
389 graph_.c \
390 gzip_.c \
391 hname_.c \
392 http_.c \
393 http_socket_.c \
394 http_ssl_.c \
395 http_transport_.c \
396 import_.c \
@@ -436,10 +437,12 @@
437 rss_.c \
438 schema_.c \
439 search_.c \
440 setup_.c \
441 sha1_.c \
442 sha1hard_.c \
443 sha3_.c \
444 shun_.c \
445 sitemap_.c \
446 skins_.c \
447 sqlcmd_.c \
448 stash_.c \
@@ -560,10 +563,11 @@
563 $(OX)\fshell$O \
564 $(OX)\fusefs$O \
565 $(OX)\glob$O \
566 $(OX)\graph$O \
567 $(OX)\gzip$O \
568 $(OX)\hname$O \
569 $(OX)\http$O \
570 $(OX)\http_socket$O \
571 $(OX)\http_ssl$O \
572 $(OX)\http_transport$O \
573 $(OX)\import$O \
@@ -610,10 +614,12 @@
614 $(OX)\rss$O \
615 $(OX)\schema$O \
616 $(OX)\search$O \
617 $(OX)\setup$O \
618 $(OX)\sha1$O \
619 $(OX)\sha1hard$O \
620 $(OX)\sha3$O \
621 $(OX)\shell$O \
622 $(OX)\shun$O \
623 $(OX)\sitemap$O \
624 $(OX)\skins$O \
625 $(OX)\sqlcmd$O \
@@ -743,10 +749,11 @@
749 echo $(OX)\fshell.obj >> $@
750 echo $(OX)\fusefs.obj >> $@
751 echo $(OX)\glob.obj >> $@
752 echo $(OX)\graph.obj >> $@
753 echo $(OX)\gzip.obj >> $@
754 echo $(OX)\hname.obj >> $@
755 echo $(OX)\http.obj >> $@
756 echo $(OX)\http_socket.obj >> $@
757 echo $(OX)\http_ssl.obj >> $@
758 echo $(OX)\http_transport.obj >> $@
759 echo $(OX)\import.obj >> $@
@@ -793,10 +800,12 @@
800 echo $(OX)\rss.obj >> $@
801 echo $(OX)\schema.obj >> $@
802 echo $(OX)\search.obj >> $@
803 echo $(OX)\setup.obj >> $@
804 echo $(OX)\sha1.obj >> $@
805 echo $(OX)\sha1hard.obj >> $@
806 echo $(OX)\sha3.obj >> $@
807 echo $(OX)\shell.obj >> $@
808 echo $(OX)\shun.obj >> $@
809 echo $(OX)\sitemap.obj >> $@
810 echo $(OX)\skins.obj >> $@
811 echo $(OX)\sqlcmd.obj >> $@
@@ -1175,10 +1184,16 @@
1184 $(OX)\gzip$O : gzip_.c gzip.h
1185 $(TCC) /Fo$@ -c gzip_.c
1186
1187 gzip_.c : $(SRCDIR)\gzip.c
1188 translate$E $** > $@
1189
1190 $(OX)\hname$O : hname_.c hname.h
1191 $(TCC) /Fo$@ -c hname_.c
1192
1193 hname_.c : $(SRCDIR)\hname.c
1194 translate$E $** > $@
1195
1196 $(OX)\http$O : http_.c http.h
1197 $(TCC) /Fo$@ -c http_.c
1198
1199 http_.c : $(SRCDIR)\http.c
@@ -1475,10 +1490,22 @@
1490 $(OX)\sha1$O : sha1_.c sha1.h
1491 $(TCC) /Fo$@ -c sha1_.c
1492
1493 sha1_.c : $(SRCDIR)\sha1.c
1494 translate$E $** > $@
1495
1496 $(OX)\sha1hard$O : sha1hard_.c sha1hard.h
1497 $(TCC) /Fo$@ -c sha1hard_.c
1498
1499 sha1hard_.c : $(SRCDIR)\sha1hard.c
1500 translate$E $** > $@
1501
1502 $(OX)\sha3$O : sha3_.c sha3.h
1503 $(TCC) /Fo$@ -c sha3_.c
1504
1505 sha3_.c : $(SRCDIR)\sha3.c
1506 translate$E $** > $@
1507
1508 $(OX)\shun$O : shun_.c shun.h
1509 $(TCC) /Fo$@ -c shun_.c
1510
1511 shun_.c : $(SRCDIR)\shun.c
@@ -1717,10 +1744,11 @@
1744 fshell_.c:fshell.h \
1745 fusefs_.c:fusefs.h \
1746 glob_.c:glob.h \
1747 graph_.c:graph.h \
1748 gzip_.c:gzip.h \
1749 hname_.c:hname.h \
1750 http_.c:http.h \
1751 http_socket_.c:http_socket.h \
1752 http_ssl_.c:http_ssl.h \
1753 http_transport_.c:http_transport.h \
1754 import_.c:import.h \
@@ -1767,10 +1795,12 @@
1795 rss_.c:rss.h \
1796 schema_.c:schema.h \
1797 search_.c:search.h \
1798 setup_.c:setup.h \
1799 sha1_.c:sha1.h \
1800 sha1hard_.c:sha1hard.h \
1801 sha3_.c:sha3.h \
1802 shun_.c:shun.h \
1803 sitemap_.c:sitemap.h \
1804 skins_.c:skins.h \
1805 sqlcmd_.c:sqlcmd.h \
1806 stash_.c:stash.h \
1807
--- www/branching.wiki
+++ www/branching.wiki
@@ -10,14 +10,14 @@
1010
Figure 1
1111
</td></tr></table>
1212
1313
Each circle represents a check-in. For the sake of clarity, the check-ins
1414
are given small consecutive numbers. In a real system, of course, the
15
-check-in numbers would be 40-character SHA1 hashes since it is not possible
15
+check-in numbers would be long hexadecimal hashes since it is not possible
1616
to allocate collision-free sequential numbers in a distributed system.
1717
But as sequential numbers are easier to read, we will substitute them for
18
-the 40-character SHA1 hashes in this document.
18
+the long hashes in this document.
1919
2020
The arrows in figure 1 show the evolution of a project. The initial
2121
check-in is 1. Check-in 2 is derived from 1. In other words, check-in 2
2222
was created by making edits to check-in 1 and then committing those edits.
2323
We say that 2 is a <i>child</i> of 1
@@ -193,11 +193,11 @@
193193
figure 5, that initial check-in is check-in 1. The <b>branch</b> tag
194194
tells (by its value) what branch the check-in is a member of.
195195
The default branch is called "trunk." All tags that begin with "<b>sym-</b>"
196196
are symbolic name tags. When a symbolic name tag is attached to a
197197
check-in, that allows you to refer to that check-in by its symbolic
198
-name rather than by its 40-character SHA1 hash name. When a symbolic name
198
+name rather than by its hexadecimal hash name. When a symbolic name
199199
tag propagates (as does the <b>sym-trunk</b> tag) then referring to that
200200
name is the same as referring to the most recent check-in with that name.
201201
Thus the two tags on check-in 1 cause all descendants to be in the
202202
"trunk" branch and to have the symbolic name "trunk."
203203
204204
--- www/branching.wiki
+++ www/branching.wiki
@@ -10,14 +10,14 @@
10 Figure 1
11 </td></tr></table>
12
13 Each circle represents a check-in. For the sake of clarity, the check-ins
14 are given small consecutive numbers. In a real system, of course, the
15 check-in numbers would be 40-character SHA1 hashes since it is not possible
16 to allocate collision-free sequential numbers in a distributed system.
17 But as sequential numbers are easier to read, we will substitute them for
18 the 40-character SHA1 hashes in this document.
19
20 The arrows in figure 1 show the evolution of a project. The initial
21 check-in is 1. Check-in 2 is derived from 1. In other words, check-in 2
22 was created by making edits to check-in 1 and then committing those edits.
23 We say that 2 is a <i>child</i> of 1
@@ -193,11 +193,11 @@
193 figure 5, that initial check-in is check-in 1. The <b>branch</b> tag
194 tells (by its value) what branch the check-in is a member of.
195 The default branch is called "trunk." All tags that begin with "<b>sym-</b>"
196 are symbolic name tags. When a symbolic name tag is attached to a
197 check-in, that allows you to refer to that check-in by its symbolic
198 name rather than by its 40-character SHA1 hash name. When a symbolic name
199 tag propagates (as does the <b>sym-trunk</b> tag) then referring to that
200 name is the same as referring to the most recent check-in with that name.
201 Thus the two tags on check-in 1 cause all descendants to be in the
202 "trunk" branch and to have the symbolic name "trunk."
203
204
--- www/branching.wiki
+++ www/branching.wiki
@@ -10,14 +10,14 @@
10 Figure 1
11 </td></tr></table>
12
13 Each circle represents a check-in. For the sake of clarity, the check-ins
14 are given small consecutive numbers. In a real system, of course, the
15 check-in numbers would be long hexadecimal hashes since it is not possible
16 to allocate collision-free sequential numbers in a distributed system.
17 But as sequential numbers are easier to read, we will substitute them for
18 the long hashes in this document.
19
20 The arrows in figure 1 show the evolution of a project. The initial
21 check-in is 1. Check-in 2 is derived from 1. In other words, check-in 2
22 was created by making edits to check-in 1 and then committing those edits.
23 We say that 2 is a <i>child</i> of 1
@@ -193,11 +193,11 @@
193 figure 5, that initial check-in is check-in 1. The <b>branch</b> tag
194 tells (by its value) what branch the check-in is a member of.
195 The default branch is called "trunk." All tags that begin with "<b>sym-</b>"
196 are symbolic name tags. When a symbolic name tag is attached to a
197 check-in, that allows you to refer to that check-in by its symbolic
198 name rather than by its hexadecimal hash name. When a symbolic name
199 tag propagates (as does the <b>sym-trunk</b> tag) then referring to that
200 name is the same as referring to the most recent check-in with that name.
201 Thus the two tags on check-in 1 cause all descendants to be in the
202 "trunk" branch and to have the symbolic name "trunk."
203
204
+20 -2
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,10 +1,28 @@
11
<title>Change Log</title>
22
3
-<a name='v1_38'></a>
4
-<h2>Changes for Version 1.38 (2017-??-??)</h2>
3
+<a name='v2_1'></a>
4
+<h2>Changes for Version 2.1 (2017-03-??)</h2>
5
+
6
+ * Add support for [./hashpolicy.wiki|hash policies] that control which
7
+ of the Hardened-SHA1 or SHA3-256 algorithms is used to name new
8
+ artifacts.
9
+ * Add the "gshow" and "gcat" subcommands to [/help?cmd=stash|fossil stash].
10
+ * Add the [/help?cmd=/juvlist|/juvlist] web page and use it to construct
11
+ the [/uv/download.html|Download Page] of the Fossil self-hosting website
12
+ using Ajax.
13
+
14
+<a name='v2_0'></a>
15
+<h2>Changes for Version 2.0 (2017-03-03)</h2>
516
17
+ * Use the
18
+ [https://github.com/cr-marcstevens/sha1collisiondetection|hardened SHA1]
19
+ implemenation by Marc Stevens and Dan Shumow.
20
+ * Add the ability to read and understand
21
+ [./fileformat.wiki#names|artifact names] that are based on SHA3-256
22
+ rather than SHA1, but do not actually generate any such names.
23
+ * Added the [/help?cmd=sha3sum|sha3sum] command.
624
* Update the built-in SQLite to version 3.17.0.
725
826
<a name='v1_37'></a>
927
<h2>Changes for Version 1.37 (2017-01-16)</h2>
1028
1129
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,10 +1,28 @@
1 <title>Change Log</title>
2
3 <a name='v1_38'></a>
4 <h2>Changes for Version 1.38 (2017-??-??)</h2>
 
 
 
 
 
 
 
 
 
 
 
5
 
 
 
 
 
 
 
6 * Update the built-in SQLite to version 3.17.0.
7
8 <a name='v1_37'></a>
9 <h2>Changes for Version 1.37 (2017-01-16)</h2>
10
11
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,10 +1,28 @@
1 <title>Change Log</title>
2
3 <a name='v2_1'></a>
4 <h2>Changes for Version 2.1 (2017-03-??)</h2>
5
6 * Add support for [./hashpolicy.wiki|hash policies] that control which
7 of the Hardened-SHA1 or SHA3-256 algorithms is used to name new
8 artifacts.
9 * Add the "gshow" and "gcat" subcommands to [/help?cmd=stash|fossil stash].
10 * Add the [/help?cmd=/juvlist|/juvlist] web page and use it to construct
11 the [/uv/download.html|Download Page] of the Fossil self-hosting website
12 using Ajax.
13
14 <a name='v2_0'></a>
15 <h2>Changes for Version 2.0 (2017-03-03)</h2>
16
17 * Use the
18 [https://github.com/cr-marcstevens/sha1collisiondetection|hardened SHA1]
19 implemenation by Marc Stevens and Dan Shumow.
20 * Add the ability to read and understand
21 [./fileformat.wiki#names|artifact names] that are based on SHA3-256
22 rather than SHA1, but do not actually generate any such names.
23 * Added the [/help?cmd=sha3sum|sha3sum] command.
24 * Update the built-in SQLite to version 3.17.0.
25
26 <a name='v1_37'></a>
27 <h2>Changes for Version 1.37 (2017-01-16)</h2>
28
29
--- www/checkin_names.wiki
+++ www/checkin_names.wiki
@@ -4,11 +4,11 @@
44
<tr><td>
55
<h3>Executive Summary</h3>
66
<p>A check-in can be identified using any of the following
77
names:
88
<ul>
9
-<li> SHA1 hash prefix
9
+<li> Cryptographic hash prefix
1010
<li> Tag or branchname
1111
<li> Timestamp: <i>YYYY-MM-DD HH:MM:SS</i>
1212
<li> <i>tag-name</i> <big><b>:</b></big> <i>timestamp</i>
1313
<li> <b>root :</b> <i>branchname</i>
1414
<li> Special names:
@@ -44,19 +44,19 @@
4444
Fossil provides a variety of ways to specify a check-in. This
4545
document describes the various methods.
4646
4747
<h2>Canonical Check-in Name</h2>
4848
49
-The canonical name of a check-in is the SHA1 hash of its
50
-[./fileformat.wiki#manifest | manifest] expressed as a 40-character
49
+The canonical name of a check-in is the hash of its
50
+[./fileformat.wiki#manifest | manifest] expressed as a 40-or-more character
5151
lowercase hexadecimal number. For example:
5252
5353
<blockquote><pre>
5454
fossil info e5a734a19a9826973e1d073b49dc2a16aa2308f9
5555
</pre></blockquote>
5656
57
-The full 40-character SHA1 hash is unwieldy to remember and type, though,
57
+The full 40+ character hash is unwieldy to remember and type, though,
5858
so Fossil also accepts a unique prefix of the hash, using any combination
5959
of upper and lower case letters, as long as the prefix is at least 4
6060
characters long. Hence the following commands all
6161
accomplish the same thing as the above:
6262
6363
--- www/checkin_names.wiki
+++ www/checkin_names.wiki
@@ -4,11 +4,11 @@
4 <tr><td>
5 <h3>Executive Summary</h3>
6 <p>A check-in can be identified using any of the following
7 names:
8 <ul>
9 <li> SHA1 hash prefix
10 <li> Tag or branchname
11 <li> Timestamp: <i>YYYY-MM-DD HH:MM:SS</i>
12 <li> <i>tag-name</i> <big><b>:</b></big> <i>timestamp</i>
13 <li> <b>root :</b> <i>branchname</i>
14 <li> Special names:
@@ -44,19 +44,19 @@
44 Fossil provides a variety of ways to specify a check-in. This
45 document describes the various methods.
46
47 <h2>Canonical Check-in Name</h2>
48
49 The canonical name of a check-in is the SHA1 hash of its
50 [./fileformat.wiki#manifest | manifest] expressed as a 40-character
51 lowercase hexadecimal number. For example:
52
53 <blockquote><pre>
54 fossil info e5a734a19a9826973e1d073b49dc2a16aa2308f9
55 </pre></blockquote>
56
57 The full 40-character SHA1 hash is unwieldy to remember and type, though,
58 so Fossil also accepts a unique prefix of the hash, using any combination
59 of upper and lower case letters, as long as the prefix is at least 4
60 characters long. Hence the following commands all
61 accomplish the same thing as the above:
62
63
--- www/checkin_names.wiki
+++ www/checkin_names.wiki
@@ -4,11 +4,11 @@
4 <tr><td>
5 <h3>Executive Summary</h3>
6 <p>A check-in can be identified using any of the following
7 names:
8 <ul>
9 <li> Cryptographic hash prefix
10 <li> Tag or branchname
11 <li> Timestamp: <i>YYYY-MM-DD HH:MM:SS</i>
12 <li> <i>tag-name</i> <big><b>:</b></big> <i>timestamp</i>
13 <li> <b>root :</b> <i>branchname</i>
14 <li> Special names:
@@ -44,19 +44,19 @@
44 Fossil provides a variety of ways to specify a check-in. This
45 document describes the various methods.
46
47 <h2>Canonical Check-in Name</h2>
48
49 The canonical name of a check-in is the hash of its
50 [./fileformat.wiki#manifest | manifest] expressed as a 40-or-more character
51 lowercase hexadecimal number. For example:
52
53 <blockquote><pre>
54 fossil info e5a734a19a9826973e1d073b49dc2a16aa2308f9
55 </pre></blockquote>
56
57 The full 40+ character hash is unwieldy to remember and type, though,
58 so Fossil also accepts a unique prefix of the hash, using any combination
59 of upper and lower case letters, as long as the prefix is at least 4
60 characters long. Hence the following commands all
61 accomplish the same thing as the above:
62
63
--- www/customskin.md
+++ www/customskin.md
@@ -177,11 +177,11 @@
177177
178178
* **csrf_token** - A token used to prevent cross-site request forgery.
179179
180180
* **release_version** - The release version of Fossil. Ex: "1.31"
181181
182
- * **manifest_version** - A prefix on the SHA1 check-in hash of the
182
+ * **manifest_version** - A prefix on the check-in hash of the
183183
specific version of fossil that is running. Ex: "\[47bb6432a1\]"
184184
185185
* **manifest_date** - The date of the source-code check-in for the
186186
version of fossil that is running.
187187
188188
--- www/customskin.md
+++ www/customskin.md
@@ -177,11 +177,11 @@
177
178 * **csrf_token** - A token used to prevent cross-site request forgery.
179
180 * **release_version** - The release version of Fossil. Ex: "1.31"
181
182 * **manifest_version** - A prefix on the SHA1 check-in hash of the
183 specific version of fossil that is running. Ex: "\[47bb6432a1\]"
184
185 * **manifest_date** - The date of the source-code check-in for the
186 version of fossil that is running.
187
188
--- www/customskin.md
+++ www/customskin.md
@@ -177,11 +177,11 @@
177
178 * **csrf_token** - A token used to prevent cross-site request forgery.
179
180 * **release_version** - The release version of Fossil. Ex: "1.31"
181
182 * **manifest_version** - A prefix on the check-in hash of the
183 specific version of fossil that is running. Ex: "\[47bb6432a1\]"
184
185 * **manifest_date** - The date of the source-code check-in for the
186 version of fossil that is running.
187
188
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -9,14 +9,19 @@
99
searchable, and extensible by people not yet born.
1010
1111
The global state of a fossil repository is an unordered
1212
set of <i>artifacts</i>.
1313
An artifact might be a source code file, the text of a wiki page,
14
-part of a trouble ticket, or one of several special control artifacts
15
-used to show the relationships between other artifacts within the
16
-project. Each artifact is normally represented on disk as a separate
17
-file. Artifacts can be text or binary.
14
+part of a trouble ticket, a description of a check-in including all
15
+the files in that check-in with the check-in comment and so forth.
16
+Artifacts are broadly grouped into two types: content artifacts and
17
+structural artifacts. Content artifacts are the raw project source-code
18
+files that are checked into the repository. Structural artifacts have
19
+special formatting rules and are used to show the relationships between
20
+other artifacts in the repository. It is possible for an artifact to
21
+be both a structure artifact and a content artifact, though this is
22
+rare. Artifacts can be text or binary.
1823
1924
In addition to the global state,
2025
each fossil repository also contains local state.
2126
The local state consists of web-page formatting
2227
preferences, authorized users, ticket display and reporting formats,
@@ -27,18 +32,40 @@
2732
with the global state.
2833
The local state is not composed of artifacts and is not intended to be enduring.
2934
This document is concerned with global state only. Local state is only
3035
mentioned here in order to distinguish it from global state.
3136
32
-Each artifact in the repository is named by its SHA1 hash.
33
-No prefixes or meta information is added to an artifact before
34
-its hash is computed. The name of an artifact in the repository
35
-is exactly the same SHA1 hash that is computed by sha1sum
36
-on the file as it exists in your source tree.</p>
37
-
38
-Some artifacts have a particular format which gives them special
39
-meaning to fossil. Fossil recognizes:
37
+<a name="names"></a>
38
+<h2>1.0 Artifact Names</h2>
39
+
40
+Each artifact in the repository is named by a hash of its content.
41
+No prefixes, suffixes, or other information is added to an artifact before
42
+the hash is computed. The artifact name is just the (lower-case
43
+hexadecimal) hash of the raw artifact.
44
+
45
+Fossil currently computes artifact names using either SHA1 or SHA3-256. It
46
+is relatively easy to add new algorithms in the future, but there are no
47
+plans to do so at this time.
48
+
49
+When referring to artifacts in using tty commands or webpage URLs, it is
50
+sufficient to specify a unique prefix for the artifact name. If the input
51
+prefix is not unique, Fossil will show an error. Within a structural
52
+artifact, however, all references to other artifacts must be the complete
53
+hash.
54
+
55
+Prior to Fossil version 2.0, all names were formed from the SHA1 hash of
56
+the artifact. The key innovation in Fossil 2.0 was adding support for
57
+alternative hash algorithms.
58
+
59
+<a name="structural"></a>
60
+<h2>2.0 Structural Artifacts</h2>
61
+
62
+A structural artifact is an artifact with a particular format
63
+that is used to define the relationships between other artifacts in the
64
+repository.
65
+Fossil recognizes the following kinds of structural
66
+artifacts:
4067
4168
<ul>
4269
<li> [#manifest | Manifests] </li>
4370
<li> [#cluster | Clusters] </li>
4471
<li> [#ctrl | Control Artifacts] </li>
@@ -46,66 +73,55 @@
4673
<li> [#tktchng | Ticket Changes] </li>
4774
<li> [#attachment | Attachments] </li>
4875
<li> [#event | TechNotes] </li>
4976
</ul>
5077
51
-These seven artifact types are described in the following sections.
78
+These seven structural artifact types are described in subsections below.
5279
53
-In the current implementation (as of 2009-01-25) the artifacts that
80
+Structural artifacts are ASCII text. The artifact may be PGP clearsigned.
81
+After removal of the PGP clearsign header and suffix (if any) a structural
82
+artifact consists of one or more "cards" separated by a single newline
83
+(ASCII: 0x0a) character. Each card begins with a single
84
+character "card type". Zero or more arguments may follow
85
+the card type. All arguments are separated from each other
86
+and from the card-type character by a single space
87
+character. There is no surplus white space between arguments
88
+and no leading or trailing whitespace except for the newline
89
+character that acts as the card separator. All cards must be in strict
90
+lexicographical order. There may not be any duplicate cards.
91
+
92
+In the current implementation (as of 2017-02-27) the artifacts that
5493
make up a fossil repository are stored as delta- and zlib-compressed
5594
blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This
5695
is an implementation detail and might change in a future release. For
5796
the purpose of this article "file format" means the format of the artifacts,
5897
not how the artifacts are stored on disk. It is the artifact format that
5998
is intended to be enduring. The specifics of how artifacts are stored on
6099
disk, though stable, is not intended to live as long as the
61100
artifact format.
62101
63
-All of the artifacts can be extracted from a Fossil repository using
64
-the "fossil deconstruct" command.
65
-
66102
<a name="manifest"></a>
67
-<h2>1.0 The Manifest</h2>
103
+<h3>2.1 The Manifest</h3>
68104
69
-A manifest defines a check-in or version of the project
70
-source tree. The manifest contains a list of artifacts for
105
+A manifest defines a check-in.
106
+A manifest contains a list of artifacts for
71107
each file in the project and the corresponding filenames, as
72
-well as information such as parent check-ins, the name of the
108
+well as information such as parent check-ins, the username of the
73109
programmer who created the check-in, the date and time when
74110
the check-in was created, and any check-in comments associated
75111
with the check-in.
76112
77
-Any artifact in the repository that follows the syntactic rules
78
-of a manifest is a manifest. Note that a manifest can
79
-be both a real manifest and also a content file, though this
80
-is rare.
81
-
82
-A manifest is a text file. Newline characters
83
-(ASCII 0x0a) separate the file into "cards".
84
-Each card begins with a single
85
-character "card type". Zero or more arguments may follow
86
-the card type. All arguments are separated from each other
87
-and from the card-type character by a single space
88
-character. There is no surplus white space between arguments
89
-and no leading or trailing whitespace except for the newline
90
-character that acts as the card separator.
91
-
92
-All cards of the manifest occur in strict sorted lexicographical order.
93
-No card may be duplicated.
94
-The entire manifest may be PGP clear-signed, but otherwise it
95
-may contain no additional text or data beyond what is described here.
96
-
97113
Allowed cards in the manifest are as follows:
98114
99115
<blockquote>
100116
<b>B</b> <i>baseline-manifest</i><br>
101117
<b>C</b> <i>checkin-comment</i><br>
102118
<b>D</b> <i>time-and-date-stamp</i><br>
103
-<b>F</b> <i>filename</i> ?<i>SHA1-hash</i>? ?<i>permissions</i>? ?<i>old-name</i>?<br>
119
+<b>F</b> <i>filename</i> ?<i>hash</i>? ?<i>permissions</i>? ?<i>old-name</i>?<br>
104120
<b>N</b> <i>mimetype</i><br>
105
-<b>P</b> <i>SHA1-hash</i>+<br>
106
-<b>Q</b> (<b>+</b>|<b>-</b>)<i>SHA1-hash</i> ?<i>SHA1-hash</i>?<br>
121
+<b>P</b> <i>artifact-hash</i>+<br>
122
+<b>Q</b> (<b>+</b>|<b>-</b>)<i>artifact-hash</i> ?<i>artifact-hash</i>?<br>
107123
<b>R</b> <i>repository-checksum</i><br>
108124
<b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <b>*</b> ?<i>value</i>?<br>
109125
<b>U</b> <i>user-login</i><br>
110126
<b>Z</b> <i>manifest-checksum</i>
111127
</blockquote>
@@ -145,11 +161,11 @@
145161
check-in relative to the root of the project file hierarchy. No ".."
146162
or "." directories are allowed within the filename. Space characters
147163
are escaped as in C-card comment text. Backslash characters and
148164
newlines are not allowed within filenames. The directory separator
149165
character is a forward slash (ASCII 0x2F). The second argument to the
150
-F-card is the full 40-character lower-case hexadecimal SHA1 hash of
166
+F-card is the lower-case hexadecimal artifact hash of
151167
the content artifact. The second argument is required for baseline
152168
manifests but is optional for delta manifests. When the second
153169
argument to the F-card is omitted, it means that the file has been
154170
deleted relative to the baseline (files removed in baseline manifests
155171
versions are <em>not</em> added as F-cards). The optional 3rd argument
@@ -167,14 +183,14 @@
167183
is used.
168184
169185
A manifest has zero or one P-cards. Most manifests have one P-card.
170186
The P-card has a varying number of arguments that
171187
define other manifests from which the current manifest
172
-is derived. Each argument is a 40-character lowercase
173
-hexadecimal SHA1 of a predecessor manifest. All arguments
188
+is derived. Each argument is a lowercase
189
+hexadecimal artifact hash of a predecessor manifest. All arguments
174190
to the P-card must be unique within that card.
175
-The first argument is the SHA1 of the direct ancestor of the manifest.
191
+The first argument is the artifact hash of the direct ancestor of the manifest.
176192
Other arguments define manifests with which the first was
177193
merged to yield the current manifest. Most manifests have
178194
a P-card with a single argument. The first manifest in the
179195
project has no ancestors and thus has no P-card or (depending
180196
on the Fossil version) an empty P-card (no arguments).
@@ -229,41 +245,27 @@
229245
check-in comment argument to the C-card.
230246
231247
A manifest must have a single Z-card as its last line. The argument
232248
to the Z-card is a 32-character lowercase hexadecimal MD5 hash
233249
of all prior lines of the manifest up to and including the newline
234
-character that immediately precedes the "Z". The Z-card is
250
+character that immediately precedes the "Z", excluding any PGP
251
+clear-signing prefix. The Z-card is
235252
a sanity check to prove that the manifest is well-formed and
236253
consistent.
237254
238255
A sample manifest from Fossil itself can be seen
239256
[/artifact/28987096ac | here].
240257
241258
<a name="cluster"></a>
242
-<h2>2.0 Clusters</h2>
259
+<h3>2.2 Clusters</h3>
243260
244261
A cluster is an artifact that declares the existence of other artifacts.
245262
Clusters are used during repository synchronization to help
246263
reduce network traffic. As such, clusters are an optimization and
247264
may be removed from a repository without loss or damage to the
248265
underlying project code.
249266
250
-Clusters follow a syntax that is very similar to manifests.
251
-A cluster is a line-oriented text file. Newline characters
252
-(ASCII 0x0a) separate the artifact into cards. Each card begins with a single
253
-character "card type". Zero or more arguments may follow
254
-the card type. All arguments are separated from each other
255
-and from the card-type character by a single space
256
-character. There is no surplus white space between arguments
257
-and no leading or trailing whitespace except for the newline
258
-character that acts as the card separator.
259
-All cards of a cluster occur in strict sorted lexicographical order.
260
-No card may be duplicated.
261
-The cluster may not contain additional text or data beyond
262
-what is described here.
263
-Unlike manifests, clusters are never PGP signed.
264
-
265267
Allowed cards in the cluster are as follows:
266268
267269
<blockquote>
268270
<b>M</b> <i>artifact-id</i><br />
269271
<b>Z</b> <i>checksum</i>
@@ -278,20 +280,14 @@
278280
279281
An example cluster from Fossil can be seen
280282
[/artifact/d03dbdd73a2a8 | here].
281283
282284
<a name="ctrl"></a>
283
-<h2>3.0 Control Artifacts</h2>
285
+<h3>2.3 Control Artifacts</h3>
284286
285287
Control artifacts are used to assign properties to other artifacts
286
-within the repository. The basic format of a control artifact is
287
-the same as a manifest or cluster. A control artifact is a text
288
-file divided into cards by newline characters. Each card has a
289
-single-character card type followed by arguments. Spaces separate
290
-the card type and the arguments. No surplus whitespace is allowed.
291
-All cards must occur in strict lexicographical order.
292
-
288
+within the repository.
293289
Allowed cards in a control artifact are as follows:
294290
295291
<blockquote>
296292
<b>D</b> <i>time-and-date-stamp</i><br />
297293
<b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <i>artifact-id</i> ?<i>value</i>?<br />
@@ -338,16 +334,15 @@
338334
339335
An example control artifacts can be seen [/info/9d302ccda8 | here].
340336
341337
342338
<a name="wikichng"></a>
343
-<h2>4.0 Wiki Pages</h2>
339
+<h3>2.4 Wiki Pages</h3>
344340
345
-A wiki page is an artifact with a format similar to manifests,
346
-clusters, and control artifacts. The artifact is divided into
347
-cards by newline characters. The format of each card is as in
348
-manifests, clusters, and control artifacts. Wiki artifacts accept
341
+A wiki artifact defines a single version of a
342
+single wiki page.
343
+Wiki artifacts accept
349344
the following card types:
350345
351346
<blockquote>
352347
<b>D</b> <i>time-and-date-stamp</i><br />
353348
<b>L</b> <i>wiki-title</i><br />
@@ -375,11 +370,11 @@
375370
376371
An example wiki artifact can be seen
377372
[/artifact?name=7b2f5fd0e0&txt=1 | here].
378373
379374
<a name="tktchng"></a>
380
-<h2>5.0 Ticket Changes</h2>
375
+<h3>2.5 Ticket Changes</h3>
381376
382377
A ticket-change artifact represents a change to a trouble ticket.
383378
The following cards are allowed on a ticket change artifact:
384379
385380
<blockquote>
@@ -421,11 +416,11 @@
421416
422417
An example ticket-change artifact can be seen
423418
[/artifact/91f1ec6af053 | here].
424419
425420
<a name="attachment"></a>
426
-<h2>6.0 Attachments</h2>
421
+<h3>2.6 Attachments</h3>
427422
428423
An attachment artifact associates some other artifact that is the
429424
attachment (the source artifact) with a ticket or wiki page or
430425
technical note to which
431426
the attachment is connected (the target artifact).
@@ -463,11 +458,11 @@
463458
The Z card is the usual checksum over the rest of the attachment artifact.
464459
The Z card is required.
465460
466461
467462
<a name="event"></a>
468
-<h2>7.0 Technical Notes</h2>
463
+<h3>2.7 Technical Notes</h3>
469464
470465
A technical note or "technote" artifact (formerly known as an "event" artifact)
471466
associates a timeline comment and a page of text
472467
(similar to a wiki page) with a point in time. Technotes can be used
473468
to record project milestones, release notes, blog entries, process
@@ -532,11 +527,11 @@
532527
533528
The Z card is the required checksum over the rest of the artifact.
534529
535530
536531
<a name="summary"></a>
537
-<h2>8.0 Card Summary</h2>
532
+<h2>3.0 Card Summary</h2>
538533
539534
The following table summarizes the various kinds of cards that appear
540535
on Fossil artifacts. A blank entry means that combination of card and
541536
artifact is not legal. A number or range of numbers indicates the number
542537
of times a card may (or must) appear in the corresponding artifact type.
@@ -739,16 +734,16 @@
739734
</tr>
740735
</table>
741736
742737
743738
<a name="addenda"></a>
744
-<h2>9.0 Addenda</h2>
739
+<h2>4.0 Addenda</h2>
745740
746741
This section contains additional information which may be useful when
747742
implementing algorithms described above.
748743
749
-<h3>R Card Hash Calculation</h3>
744
+<h3>4.1 R-Card Hash Calculation</h3>
750745
751746
Given a manifest file named <tt>MF</tt>, the following Bash shell code
752747
demonstrates how to compute the value of the R card in that manifest.
753748
This example uses manifest [28987096ac]. Lines starting with <tt>#</tt> are
754749
shell input and other lines are output. This demonstration assumes that the
755750
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -9,14 +9,19 @@
9 searchable, and extensible by people not yet born.
10
11 The global state of a fossil repository is an unordered
12 set of <i>artifacts</i>.
13 An artifact might be a source code file, the text of a wiki page,
14 part of a trouble ticket, or one of several special control artifacts
15 used to show the relationships between other artifacts within the
16 project. Each artifact is normally represented on disk as a separate
17 file. Artifacts can be text or binary.
 
 
 
 
 
18
19 In addition to the global state,
20 each fossil repository also contains local state.
21 The local state consists of web-page formatting
22 preferences, authorized users, ticket display and reporting formats,
@@ -27,18 +32,40 @@
27 with the global state.
28 The local state is not composed of artifacts and is not intended to be enduring.
29 This document is concerned with global state only. Local state is only
30 mentioned here in order to distinguish it from global state.
31
32 Each artifact in the repository is named by its SHA1 hash.
33 No prefixes or meta information is added to an artifact before
34 its hash is computed. The name of an artifact in the repository
35 is exactly the same SHA1 hash that is computed by sha1sum
36 on the file as it exists in your source tree.</p>
37
38 Some artifacts have a particular format which gives them special
39 meaning to fossil. Fossil recognizes:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
41 <ul>
42 <li> [#manifest | Manifests] </li>
43 <li> [#cluster | Clusters] </li>
44 <li> [#ctrl | Control Artifacts] </li>
@@ -46,66 +73,55 @@
46 <li> [#tktchng | Ticket Changes] </li>
47 <li> [#attachment | Attachments] </li>
48 <li> [#event | TechNotes] </li>
49 </ul>
50
51 These seven artifact types are described in the following sections.
52
53 In the current implementation (as of 2009-01-25) the artifacts that
 
 
 
 
 
 
 
 
 
 
 
 
54 make up a fossil repository are stored as delta- and zlib-compressed
55 blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This
56 is an implementation detail and might change in a future release. For
57 the purpose of this article "file format" means the format of the artifacts,
58 not how the artifacts are stored on disk. It is the artifact format that
59 is intended to be enduring. The specifics of how artifacts are stored on
60 disk, though stable, is not intended to live as long as the
61 artifact format.
62
63 All of the artifacts can be extracted from a Fossil repository using
64 the "fossil deconstruct" command.
65
66 <a name="manifest"></a>
67 <h2>1.0 The Manifest</h2>
68
69 A manifest defines a check-in or version of the project
70 source tree. The manifest contains a list of artifacts for
71 each file in the project and the corresponding filenames, as
72 well as information such as parent check-ins, the name of the
73 programmer who created the check-in, the date and time when
74 the check-in was created, and any check-in comments associated
75 with the check-in.
76
77 Any artifact in the repository that follows the syntactic rules
78 of a manifest is a manifest. Note that a manifest can
79 be both a real manifest and also a content file, though this
80 is rare.
81
82 A manifest is a text file. Newline characters
83 (ASCII 0x0a) separate the file into "cards".
84 Each card begins with a single
85 character "card type". Zero or more arguments may follow
86 the card type. All arguments are separated from each other
87 and from the card-type character by a single space
88 character. There is no surplus white space between arguments
89 and no leading or trailing whitespace except for the newline
90 character that acts as the card separator.
91
92 All cards of the manifest occur in strict sorted lexicographical order.
93 No card may be duplicated.
94 The entire manifest may be PGP clear-signed, but otherwise it
95 may contain no additional text or data beyond what is described here.
96
97 Allowed cards in the manifest are as follows:
98
99 <blockquote>
100 <b>B</b> <i>baseline-manifest</i><br>
101 <b>C</b> <i>checkin-comment</i><br>
102 <b>D</b> <i>time-and-date-stamp</i><br>
103 <b>F</b> <i>filename</i> ?<i>SHA1-hash</i>? ?<i>permissions</i>? ?<i>old-name</i>?<br>
104 <b>N</b> <i>mimetype</i><br>
105 <b>P</b> <i>SHA1-hash</i>+<br>
106 <b>Q</b> (<b>+</b>|<b>-</b>)<i>SHA1-hash</i> ?<i>SHA1-hash</i>?<br>
107 <b>R</b> <i>repository-checksum</i><br>
108 <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <b>*</b> ?<i>value</i>?<br>
109 <b>U</b> <i>user-login</i><br>
110 <b>Z</b> <i>manifest-checksum</i>
111 </blockquote>
@@ -145,11 +161,11 @@
145 check-in relative to the root of the project file hierarchy. No ".."
146 or "." directories are allowed within the filename. Space characters
147 are escaped as in C-card comment text. Backslash characters and
148 newlines are not allowed within filenames. The directory separator
149 character is a forward slash (ASCII 0x2F). The second argument to the
150 F-card is the full 40-character lower-case hexadecimal SHA1 hash of
151 the content artifact. The second argument is required for baseline
152 manifests but is optional for delta manifests. When the second
153 argument to the F-card is omitted, it means that the file has been
154 deleted relative to the baseline (files removed in baseline manifests
155 versions are <em>not</em> added as F-cards). The optional 3rd argument
@@ -167,14 +183,14 @@
167 is used.
168
169 A manifest has zero or one P-cards. Most manifests have one P-card.
170 The P-card has a varying number of arguments that
171 define other manifests from which the current manifest
172 is derived. Each argument is a 40-character lowercase
173 hexadecimal SHA1 of a predecessor manifest. All arguments
174 to the P-card must be unique within that card.
175 The first argument is the SHA1 of the direct ancestor of the manifest.
176 Other arguments define manifests with which the first was
177 merged to yield the current manifest. Most manifests have
178 a P-card with a single argument. The first manifest in the
179 project has no ancestors and thus has no P-card or (depending
180 on the Fossil version) an empty P-card (no arguments).
@@ -229,41 +245,27 @@
229 check-in comment argument to the C-card.
230
231 A manifest must have a single Z-card as its last line. The argument
232 to the Z-card is a 32-character lowercase hexadecimal MD5 hash
233 of all prior lines of the manifest up to and including the newline
234 character that immediately precedes the "Z". The Z-card is
 
235 a sanity check to prove that the manifest is well-formed and
236 consistent.
237
238 A sample manifest from Fossil itself can be seen
239 [/artifact/28987096ac | here].
240
241 <a name="cluster"></a>
242 <h2>2.0 Clusters</h2>
243
244 A cluster is an artifact that declares the existence of other artifacts.
245 Clusters are used during repository synchronization to help
246 reduce network traffic. As such, clusters are an optimization and
247 may be removed from a repository without loss or damage to the
248 underlying project code.
249
250 Clusters follow a syntax that is very similar to manifests.
251 A cluster is a line-oriented text file. Newline characters
252 (ASCII 0x0a) separate the artifact into cards. Each card begins with a single
253 character "card type". Zero or more arguments may follow
254 the card type. All arguments are separated from each other
255 and from the card-type character by a single space
256 character. There is no surplus white space between arguments
257 and no leading or trailing whitespace except for the newline
258 character that acts as the card separator.
259 All cards of a cluster occur in strict sorted lexicographical order.
260 No card may be duplicated.
261 The cluster may not contain additional text or data beyond
262 what is described here.
263 Unlike manifests, clusters are never PGP signed.
264
265 Allowed cards in the cluster are as follows:
266
267 <blockquote>
268 <b>M</b> <i>artifact-id</i><br />
269 <b>Z</b> <i>checksum</i>
@@ -278,20 +280,14 @@
278
279 An example cluster from Fossil can be seen
280 [/artifact/d03dbdd73a2a8 | here].
281
282 <a name="ctrl"></a>
283 <h2>3.0 Control Artifacts</h2>
284
285 Control artifacts are used to assign properties to other artifacts
286 within the repository. The basic format of a control artifact is
287 the same as a manifest or cluster. A control artifact is a text
288 file divided into cards by newline characters. Each card has a
289 single-character card type followed by arguments. Spaces separate
290 the card type and the arguments. No surplus whitespace is allowed.
291 All cards must occur in strict lexicographical order.
292
293 Allowed cards in a control artifact are as follows:
294
295 <blockquote>
296 <b>D</b> <i>time-and-date-stamp</i><br />
297 <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <i>artifact-id</i> ?<i>value</i>?<br />
@@ -338,16 +334,15 @@
338
339 An example control artifacts can be seen [/info/9d302ccda8 | here].
340
341
342 <a name="wikichng"></a>
343 <h2>4.0 Wiki Pages</h2>
344
345 A wiki page is an artifact with a format similar to manifests,
346 clusters, and control artifacts. The artifact is divided into
347 cards by newline characters. The format of each card is as in
348 manifests, clusters, and control artifacts. Wiki artifacts accept
349 the following card types:
350
351 <blockquote>
352 <b>D</b> <i>time-and-date-stamp</i><br />
353 <b>L</b> <i>wiki-title</i><br />
@@ -375,11 +370,11 @@
375
376 An example wiki artifact can be seen
377 [/artifact?name=7b2f5fd0e0&txt=1 | here].
378
379 <a name="tktchng"></a>
380 <h2>5.0 Ticket Changes</h2>
381
382 A ticket-change artifact represents a change to a trouble ticket.
383 The following cards are allowed on a ticket change artifact:
384
385 <blockquote>
@@ -421,11 +416,11 @@
421
422 An example ticket-change artifact can be seen
423 [/artifact/91f1ec6af053 | here].
424
425 <a name="attachment"></a>
426 <h2>6.0 Attachments</h2>
427
428 An attachment artifact associates some other artifact that is the
429 attachment (the source artifact) with a ticket or wiki page or
430 technical note to which
431 the attachment is connected (the target artifact).
@@ -463,11 +458,11 @@
463 The Z card is the usual checksum over the rest of the attachment artifact.
464 The Z card is required.
465
466
467 <a name="event"></a>
468 <h2>7.0 Technical Notes</h2>
469
470 A technical note or "technote" artifact (formerly known as an "event" artifact)
471 associates a timeline comment and a page of text
472 (similar to a wiki page) with a point in time. Technotes can be used
473 to record project milestones, release notes, blog entries, process
@@ -532,11 +527,11 @@
532
533 The Z card is the required checksum over the rest of the artifact.
534
535
536 <a name="summary"></a>
537 <h2>8.0 Card Summary</h2>
538
539 The following table summarizes the various kinds of cards that appear
540 on Fossil artifacts. A blank entry means that combination of card and
541 artifact is not legal. A number or range of numbers indicates the number
542 of times a card may (or must) appear in the corresponding artifact type.
@@ -739,16 +734,16 @@
739 </tr>
740 </table>
741
742
743 <a name="addenda"></a>
744 <h2>9.0 Addenda</h2>
745
746 This section contains additional information which may be useful when
747 implementing algorithms described above.
748
749 <h3>R Card Hash Calculation</h3>
750
751 Given a manifest file named <tt>MF</tt>, the following Bash shell code
752 demonstrates how to compute the value of the R card in that manifest.
753 This example uses manifest [28987096ac]. Lines starting with <tt>#</tt> are
754 shell input and other lines are output. This demonstration assumes that the
755
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -9,14 +9,19 @@
9 searchable, and extensible by people not yet born.
10
11 The global state of a fossil repository is an unordered
12 set of <i>artifacts</i>.
13 An artifact might be a source code file, the text of a wiki page,
14 part of a trouble ticket, a description of a check-in including all
15 the files in that check-in with the check-in comment and so forth.
16 Artifacts are broadly grouped into two types: content artifacts and
17 structural artifacts. Content artifacts are the raw project source-code
18 files that are checked into the repository. Structural artifacts have
19 special formatting rules and are used to show the relationships between
20 other artifacts in the repository. It is possible for an artifact to
21 be both a structure artifact and a content artifact, though this is
22 rare. Artifacts can be text or binary.
23
24 In addition to the global state,
25 each fossil repository also contains local state.
26 The local state consists of web-page formatting
27 preferences, authorized users, ticket display and reporting formats,
@@ -27,18 +32,40 @@
32 with the global state.
33 The local state is not composed of artifacts and is not intended to be enduring.
34 This document is concerned with global state only. Local state is only
35 mentioned here in order to distinguish it from global state.
36
37 <a name="names"></a>
38 <h2>1.0 Artifact Names</h2>
39
40 Each artifact in the repository is named by a hash of its content.
41 No prefixes, suffixes, or other information is added to an artifact before
42 the hash is computed. The artifact name is just the (lower-case
43 hexadecimal) hash of the raw artifact.
44
45 Fossil currently computes artifact names using either SHA1 or SHA3-256. It
46 is relatively easy to add new algorithms in the future, but there are no
47 plans to do so at this time.
48
49 When referring to artifacts in using tty commands or webpage URLs, it is
50 sufficient to specify a unique prefix for the artifact name. If the input
51 prefix is not unique, Fossil will show an error. Within a structural
52 artifact, however, all references to other artifacts must be the complete
53 hash.
54
55 Prior to Fossil version 2.0, all names were formed from the SHA1 hash of
56 the artifact. The key innovation in Fossil 2.0 was adding support for
57 alternative hash algorithms.
58
59 <a name="structural"></a>
60 <h2>2.0 Structural Artifacts</h2>
61
62 A structural artifact is an artifact with a particular format
63 that is used to define the relationships between other artifacts in the
64 repository.
65 Fossil recognizes the following kinds of structural
66 artifacts:
67
68 <ul>
69 <li> [#manifest | Manifests] </li>
70 <li> [#cluster | Clusters] </li>
71 <li> [#ctrl | Control Artifacts] </li>
@@ -46,66 +73,55 @@
73 <li> [#tktchng | Ticket Changes] </li>
74 <li> [#attachment | Attachments] </li>
75 <li> [#event | TechNotes] </li>
76 </ul>
77
78 These seven structural artifact types are described in subsections below.
79
80 Structural artifacts are ASCII text. The artifact may be PGP clearsigned.
81 After removal of the PGP clearsign header and suffix (if any) a structural
82 artifact consists of one or more "cards" separated by a single newline
83 (ASCII: 0x0a) character. Each card begins with a single
84 character "card type". Zero or more arguments may follow
85 the card type. All arguments are separated from each other
86 and from the card-type character by a single space
87 character. There is no surplus white space between arguments
88 and no leading or trailing whitespace except for the newline
89 character that acts as the card separator. All cards must be in strict
90 lexicographical order. There may not be any duplicate cards.
91
92 In the current implementation (as of 2017-02-27) the artifacts that
93 make up a fossil repository are stored as delta- and zlib-compressed
94 blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This
95 is an implementation detail and might change in a future release. For
96 the purpose of this article "file format" means the format of the artifacts,
97 not how the artifacts are stored on disk. It is the artifact format that
98 is intended to be enduring. The specifics of how artifacts are stored on
99 disk, though stable, is not intended to live as long as the
100 artifact format.
101
 
 
 
102 <a name="manifest"></a>
103 <h3>2.1 The Manifest</h3>
104
105 A manifest defines a check-in.
106 A manifest contains a list of artifacts for
107 each file in the project and the corresponding filenames, as
108 well as information such as parent check-ins, the username of the
109 programmer who created the check-in, the date and time when
110 the check-in was created, and any check-in comments associated
111 with the check-in.
112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113 Allowed cards in the manifest are as follows:
114
115 <blockquote>
116 <b>B</b> <i>baseline-manifest</i><br>
117 <b>C</b> <i>checkin-comment</i><br>
118 <b>D</b> <i>time-and-date-stamp</i><br>
119 <b>F</b> <i>filename</i> ?<i>hash</i>? ?<i>permissions</i>? ?<i>old-name</i>?<br>
120 <b>N</b> <i>mimetype</i><br>
121 <b>P</b> <i>artifact-hash</i>+<br>
122 <b>Q</b> (<b>+</b>|<b>-</b>)<i>artifact-hash</i> ?<i>artifact-hash</i>?<br>
123 <b>R</b> <i>repository-checksum</i><br>
124 <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <b>*</b> ?<i>value</i>?<br>
125 <b>U</b> <i>user-login</i><br>
126 <b>Z</b> <i>manifest-checksum</i>
127 </blockquote>
@@ -145,11 +161,11 @@
161 check-in relative to the root of the project file hierarchy. No ".."
162 or "." directories are allowed within the filename. Space characters
163 are escaped as in C-card comment text. Backslash characters and
164 newlines are not allowed within filenames. The directory separator
165 character is a forward slash (ASCII 0x2F). The second argument to the
166 F-card is the lower-case hexadecimal artifact hash of
167 the content artifact. The second argument is required for baseline
168 manifests but is optional for delta manifests. When the second
169 argument to the F-card is omitted, it means that the file has been
170 deleted relative to the baseline (files removed in baseline manifests
171 versions are <em>not</em> added as F-cards). The optional 3rd argument
@@ -167,14 +183,14 @@
183 is used.
184
185 A manifest has zero or one P-cards. Most manifests have one P-card.
186 The P-card has a varying number of arguments that
187 define other manifests from which the current manifest
188 is derived. Each argument is a lowercase
189 hexadecimal artifact hash of a predecessor manifest. All arguments
190 to the P-card must be unique within that card.
191 The first argument is the artifact hash of the direct ancestor of the manifest.
192 Other arguments define manifests with which the first was
193 merged to yield the current manifest. Most manifests have
194 a P-card with a single argument. The first manifest in the
195 project has no ancestors and thus has no P-card or (depending
196 on the Fossil version) an empty P-card (no arguments).
@@ -229,41 +245,27 @@
245 check-in comment argument to the C-card.
246
247 A manifest must have a single Z-card as its last line. The argument
248 to the Z-card is a 32-character lowercase hexadecimal MD5 hash
249 of all prior lines of the manifest up to and including the newline
250 character that immediately precedes the "Z", excluding any PGP
251 clear-signing prefix. The Z-card is
252 a sanity check to prove that the manifest is well-formed and
253 consistent.
254
255 A sample manifest from Fossil itself can be seen
256 [/artifact/28987096ac | here].
257
258 <a name="cluster"></a>
259 <h3>2.2 Clusters</h3>
260
261 A cluster is an artifact that declares the existence of other artifacts.
262 Clusters are used during repository synchronization to help
263 reduce network traffic. As such, clusters are an optimization and
264 may be removed from a repository without loss or damage to the
265 underlying project code.
266
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267 Allowed cards in the cluster are as follows:
268
269 <blockquote>
270 <b>M</b> <i>artifact-id</i><br />
271 <b>Z</b> <i>checksum</i>
@@ -278,20 +280,14 @@
280
281 An example cluster from Fossil can be seen
282 [/artifact/d03dbdd73a2a8 | here].
283
284 <a name="ctrl"></a>
285 <h3>2.3 Control Artifacts</h3>
286
287 Control artifacts are used to assign properties to other artifacts
288 within the repository.
 
 
 
 
 
 
289 Allowed cards in a control artifact are as follows:
290
291 <blockquote>
292 <b>D</b> <i>time-and-date-stamp</i><br />
293 <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <i>artifact-id</i> ?<i>value</i>?<br />
@@ -338,16 +334,15 @@
334
335 An example control artifacts can be seen [/info/9d302ccda8 | here].
336
337
338 <a name="wikichng"></a>
339 <h3>2.4 Wiki Pages</h3>
340
341 A wiki artifact defines a single version of a
342 single wiki page.
343 Wiki artifacts accept
 
344 the following card types:
345
346 <blockquote>
347 <b>D</b> <i>time-and-date-stamp</i><br />
348 <b>L</b> <i>wiki-title</i><br />
@@ -375,11 +370,11 @@
370
371 An example wiki artifact can be seen
372 [/artifact?name=7b2f5fd0e0&txt=1 | here].
373
374 <a name="tktchng"></a>
375 <h3>2.5 Ticket Changes</h3>
376
377 A ticket-change artifact represents a change to a trouble ticket.
378 The following cards are allowed on a ticket change artifact:
379
380 <blockquote>
@@ -421,11 +416,11 @@
416
417 An example ticket-change artifact can be seen
418 [/artifact/91f1ec6af053 | here].
419
420 <a name="attachment"></a>
421 <h3>2.6 Attachments</h3>
422
423 An attachment artifact associates some other artifact that is the
424 attachment (the source artifact) with a ticket or wiki page or
425 technical note to which
426 the attachment is connected (the target artifact).
@@ -463,11 +458,11 @@
458 The Z card is the usual checksum over the rest of the attachment artifact.
459 The Z card is required.
460
461
462 <a name="event"></a>
463 <h3>2.7 Technical Notes</h3>
464
465 A technical note or "technote" artifact (formerly known as an "event" artifact)
466 associates a timeline comment and a page of text
467 (similar to a wiki page) with a point in time. Technotes can be used
468 to record project milestones, release notes, blog entries, process
@@ -532,11 +527,11 @@
527
528 The Z card is the required checksum over the rest of the artifact.
529
530
531 <a name="summary"></a>
532 <h2>3.0 Card Summary</h2>
533
534 The following table summarizes the various kinds of cards that appear
535 on Fossil artifacts. A blank entry means that combination of card and
536 artifact is not legal. A number or range of numbers indicates the number
537 of times a card may (or must) appear in the corresponding artifact type.
@@ -739,16 +734,16 @@
734 </tr>
735 </table>
736
737
738 <a name="addenda"></a>
739 <h2>4.0 Addenda</h2>
740
741 This section contains additional information which may be useful when
742 implementing algorithms described above.
743
744 <h3>4.1 R-Card Hash Calculation</h3>
745
746 Given a manifest file named <tt>MF</tt>, the following Bash shell code
747 demonstrates how to compute the value of the R card in that manifest.
748 This example uses manifest [28987096ac]. Lines starting with <tt>#</tt> are
749 shell input and other lines are output. This demonstration assumes that the
750
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -67,11 +67,12 @@
6767
6868
<h3>3.2 Database</h3>
6969
7070
The baseline data structures for Fossil and Git are the same (modulo
7171
formatting details). Both systems store check-ins as immutable
72
-objects referencing their immediate ancestors and named by their SHA1 hash.
72
+objects referencing their immediate ancestors and named by a
73
+cryptographic hash of the check-in content.
7374
7475
The difference is that Git stores its objects as individual files
7576
in the ".git" folder or compressed into
7677
bespoke "pack-files", whereas Fossil stores its objects in a
7778
relational ([https://www.sqlite.org/|SQLite]) database file. To put it
7879
7980
ADDED www/hashpolicy.wiki
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -67,11 +67,12 @@
67
68 <h3>3.2 Database</h3>
69
70 The baseline data structures for Fossil and Git are the same (modulo
71 formatting details). Both systems store check-ins as immutable
72 objects referencing their immediate ancestors and named by their SHA1 hash.
 
73
74 The difference is that Git stores its objects as individual files
75 in the ".git" folder or compressed into
76 bespoke "pack-files", whereas Fossil stores its objects in a
77 relational ([https://www.sqlite.org/|SQLite]) database file. To put it
78
79 DDED www/hashpolicy.wiki
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -67,11 +67,12 @@
67
68 <h3>3.2 Database</h3>
69
70 The baseline data structures for Fossil and Git are the same (modulo
71 formatting details). Both systems store check-ins as immutable
72 objects referencing their immediate ancestors and named by a
73 cryptographic hash of the check-in content.
74
75 The difference is that Git stores its objects as individual files
76 in the ".git" folder or compressed into
77 bespoke "pack-files", whereas Fossil stores its objects in a
78 relational ([https://www.sqlite.org/|SQLite]) database file. To put it
79
80 DDED www/hashpolicy.wiki
--- a/www/hashpolicy.wiki
+++ b/www/hashpolicy.wiki
@@ -0,0 +1,20 @@
1
+<title>Hash Policy</title>
2
+
3
+<h2> Executive Summary, Orcutive Summary</h2>
4
+
5
+<b>Or: How To </h2>
6
+
7
+There i This Article</b>
8
+
9
+Thham now
10
+upgraded to
11
+change texpected to be
12
+replaced ot expected to be
13
+replaced until Ma
14
+out o
15
+Debian 9 is implement0 or later
16
+
17
+work and
18
+Hash Policy</title>
19
+
20
+<h2>< Introduction ha", not generic SHA1sequel
--- a/www/hashpolicy.wiki
+++ b/www/hashpolicy.wiki
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/www/hashpolicy.wiki
+++ b/www/hashpolicy.wiki
@@ -0,0 +1,20 @@
1 <title>Hash Policy</title>
2
3 <h2> Executive Summary, Orcutive Summary</h2>
4
5 <b>Or: How To </h2>
6
7 There i This Article</b>
8
9 Thham now
10 upgraded to
11 change texpected to be
12 replaced ot expected to be
13 replaced until Ma
14 out o
15 Debian 9 is implement0 or later
16
17 work and
18 Hash Policy</title>
19
20 <h2>< Introduction ha", not generic SHA1sequel
--- www/mkdownload.tcl
+++ www/mkdownload.tcl
@@ -37,12 +37,12 @@
3737
set avers($version) 1
3838
}
3939
}
4040
close $in
4141
42
+set vdate(2.0) 2017-03-03
4243
set vdate(1.37) 2017-01-15
43
-set vdate(1.36) 2016-10-24
4444
4545
# Do all versions from newest to oldest
4646
#
4747
foreach vers [lsort -decr -real [array names avers]] {
4848
# set hr "../timeline?c=version-$vers;y=ci"
@@ -57,11 +57,11 @@
5757
puts $out "</b></center>"
5858
puts $out "</td></tr>"
5959
puts $out "<tr>"
6060
6161
foreach {prefix img desc} {
62
- fossil-linux-x86 linux.gif {Linux 3.x x86}
62
+ fossil-linux linux.gif {Linux 3.x x64}
6363
fossil-macosx mac.gif {Mac 10.x x86}
6464
fossil-openbsd-x86 openbsd.gif {OpenBSD 5.x x86}
6565
fossil-w32 win32.gif {Windows}
6666
fossil-src src.gif {Source Tarball}
6767
} {
6868
--- www/mkdownload.tcl
+++ www/mkdownload.tcl
@@ -37,12 +37,12 @@
37 set avers($version) 1
38 }
39 }
40 close $in
41
 
42 set vdate(1.37) 2017-01-15
43 set vdate(1.36) 2016-10-24
44
45 # Do all versions from newest to oldest
46 #
47 foreach vers [lsort -decr -real [array names avers]] {
48 # set hr "../timeline?c=version-$vers;y=ci"
@@ -57,11 +57,11 @@
57 puts $out "</b></center>"
58 puts $out "</td></tr>"
59 puts $out "<tr>"
60
61 foreach {prefix img desc} {
62 fossil-linux-x86 linux.gif {Linux 3.x x86}
63 fossil-macosx mac.gif {Mac 10.x x86}
64 fossil-openbsd-x86 openbsd.gif {OpenBSD 5.x x86}
65 fossil-w32 win32.gif {Windows}
66 fossil-src src.gif {Source Tarball}
67 } {
68
--- www/mkdownload.tcl
+++ www/mkdownload.tcl
@@ -37,12 +37,12 @@
37 set avers($version) 1
38 }
39 }
40 close $in
41
42 set vdate(2.0) 2017-03-03
43 set vdate(1.37) 2017-01-15
 
44
45 # Do all versions from newest to oldest
46 #
47 foreach vers [lsort -decr -real [array names avers]] {
48 # set hr "../timeline?c=version-$vers;y=ci"
@@ -57,11 +57,11 @@
57 puts $out "</b></center>"
58 puts $out "</td></tr>"
59 puts $out "<tr>"
60
61 foreach {prefix img desc} {
62 fossil-linux linux.gif {Linux 3.x x64}
63 fossil-macosx mac.gif {Mac 10.x x86}
64 fossil-openbsd-x86 openbsd.gif {OpenBSD 5.x x86}
65 fossil-w32 win32.gif {Windows}
66 fossil-src src.gif {Source Tarball}
67 } {
68
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -36,10 +36,11 @@
3636
fiveminutes.wiki {Update and Running in 5 Minutes as a Single User}
3737
foss-cklist.wiki {Checklist For Successful Open-Source Projects}
3838
fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE}
3939
fossil-v-git.wiki {Fossil Versus Git}
4040
hacker-howto.wiki {Hacker How-To}
41
+ hashpolicy.wiki {Hash Policy: Choosing Between SHA1 and SHA3-256}
4142
/help {Lists of Commands and Webpages}
4243
hints.wiki {Fossil Tips And Usage Hints}
4344
index.wiki {Home Page}
4445
inout.wiki {Import And Export To And From Git}
4546
makefile.wiki {The Fossil Build Process}
4647
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -36,10 +36,11 @@
36 fiveminutes.wiki {Update and Running in 5 Minutes as a Single User}
37 foss-cklist.wiki {Checklist For Successful Open-Source Projects}
38 fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE}
39 fossil-v-git.wiki {Fossil Versus Git}
40 hacker-howto.wiki {Hacker How-To}
 
41 /help {Lists of Commands and Webpages}
42 hints.wiki {Fossil Tips And Usage Hints}
43 index.wiki {Home Page}
44 inout.wiki {Import And Export To And From Git}
45 makefile.wiki {The Fossil Build Process}
46
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -36,10 +36,11 @@
36 fiveminutes.wiki {Update and Running in 5 Minutes as a Single User}
37 foss-cklist.wiki {Checklist For Successful Open-Source Projects}
38 fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE}
39 fossil-v-git.wiki {Fossil Versus Git}
40 hacker-howto.wiki {Hacker How-To}
41 hashpolicy.wiki {Hash Policy: Choosing Between SHA1 and SHA3-256}
42 /help {Lists of Commands and Webpages}
43 hints.wiki {Fossil Tips And Usage Hints}
44 index.wiki {Home Page}
45 inout.wiki {Import And Export To And From Git}
46 makefile.wiki {The Fossil Build Process}
47
--- www/permutedindex.html
+++ www/permutedindex.html
@@ -29,10 +29,11 @@
2929
<li><a href="blame.wiki">Annotate/Blame Algorithm Of Fossil &mdash; The</a></li>
3030
<li><a href="customskin.md">Appearance of Web Pages &mdash; Theming: Customizing The</a></li>
3131
<li><a href="faq.wiki">Asked Questions &mdash; Frequently</a></li>
3232
<li><a href="password.wiki">Authentication &mdash; Password Management And</a></li>
3333
<li><a href="whyusefossil.wiki"><b>Benefits Of Version Control</b></a></li>
34
+<li><a href="hashpolicy.wiki">Between SHA1 and SHA3-256 &mdash; Hash Policy: Choosing</a></li>
3435
<li><a href="antibot.wiki">Bots &mdash; Defense against Spiders and</a></li>
3536
<li><a href="private.wiki">Branches &mdash; Creating, Syncing, and Deleting Private</a></li>
3637
<li><a href="branching.wiki"><b>Branching, Forking, Merging, and Tagging</b></a></li>
3738
<li><a href="bugtheory.wiki"><b>Bug Tracking In Fossil</b></a></li>
3839
<li><a href="makefile.wiki">Build Process &mdash; The Fossil</a></li>
@@ -43,10 +44,11 @@
4344
<li><a href="checkin.wiki">Checklist &mdash; Check-in</a></li>
4445
<li><a href="../test/release-checklist.wiki">Checklist &mdash; Pre-Release Testing</a></li>
4546
<li><a href="foss-cklist.wiki"><b>Checklist For Successful Open-Source Projects</b></a></li>
4647
<li><a href="selfcheck.wiki">Checks &mdash; Fossil Repository Integrity Self</a></li>
4748
<li><a href="childprojects.wiki"><b>Child Projects</b></a></li>
49
+<li><a href="hashpolicy.wiki">Choosing Between SHA1 and SHA3-256 &mdash; Hash Policy:</a></li>
4850
<li><a href="contribute.wiki">Code or Documentation To The Fossil Project &mdash; Contributing</a></li>
4951
<li><a href="style.wiki">Code Style Guidelines &mdash; Source</a></li>
5052
<li><a href="../../../help">Commands and Webpages &mdash; Lists of</a></li>
5153
<li><a href="build.wiki"><b>Compiling and Installing Fossil</b></a></li>
5254
<li><a href="concepts.wiki">Concepts &mdash; Fossil Core</a></li>
@@ -111,10 +113,11 @@
111113
<li><a href="customgraph.md">Graph &mdash; Theming: Customizing the Timeline</a></li>
112114
<li><a href="quickstart.wiki">Guide &mdash; Fossil Quick Start</a></li>
113115
<li><a href="style.wiki">Guidelines &mdash; Source Code Style</a></li>
114116
<li><a href="hacker-howto.wiki"><b>Hacker How-To</b></a></li>
115117
<li><a href="adding_code.wiki"><b>Hacking Fossil</b></a></li>
118
+<li><a href="hashpolicy.wiki"><b>Hash Policy: Choosing Between SHA1 and SHA3-256</b></a></li>
116119
<li><a href="hints.wiki">Hints &mdash; Fossil Tips And Usage</a></li>
117120
<li><a href="index.wiki"><b>Home Page</b></a></li>
118121
<li><a href="selfhost.wiki">Hosting Repositories &mdash; Fossil Self</a></li>
119122
<li><a href="aboutcgi.wiki"><b>How CGI Works In Fossil</b></a></li>
120123
<li><a href="server.wiki"><b>How To Configure A Fossil Server</b></a></li>
@@ -147,10 +150,11 @@
147150
<li><a href="index.wiki">Page &mdash; Home</a></li>
148151
<li><a href="customskin.md">Pages &mdash; Theming: Customizing The Appearance of Web</a></li>
149152
<li><a href="password.wiki"><b>Password Management And Authentication</b></a></li>
150153
<li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General &mdash; Quotes: What</a></li>
151154
<li><a href="stats.wiki"><b>Performance Statistics</b></a></li>
155
+<li><a href="hashpolicy.wiki">Policy: Choosing Between SHA1 and SHA3-256 &mdash; Hash</a></li>
152156
<li><a href="../test/release-checklist.wiki"><b>Pre-Release Testing Checklist</b></a></li>
153157
<li><a href="pop.wiki"><b>Principles Of Operation</b></a></li>
154158
<li><a href="private.wiki">Private Branches &mdash; Creating, Syncing, and Deleting</a></li>
155159
<li><a href="makefile.wiki">Process &mdash; The Fossil Build</a></li>
156160
<li><a href="contribute.wiki">Project &mdash; Contributing Code or Documentation To The Fossil</a></li>
@@ -174,10 +178,12 @@
174178
<li><a href="th1.md">Scripting Language &mdash; The TH1</a></li>
175179
<li><a href="selfcheck.wiki">Self Checks &mdash; Fossil Repository Integrity</a></li>
176180
<li><a href="selfhost.wiki">Self Hosting Repositories &mdash; Fossil</a></li>
177181
<li><a href="server.wiki">Server &mdash; How To Configure A Fossil</a></li>
178182
<li><a href="settings.wiki">Settings &mdash; Fossil</a></li>
183
+<li><a href="hashpolicy.wiki">SHA1 and SHA3-256 &mdash; Hash Policy: Choosing Between</a></li>
184
+<li><a href="hashpolicy.wiki">SHA3-256 &mdash; Hash Policy: Choosing Between SHA1 and</a></li>
179185
<li><a href="shunning.wiki"><b>Shunning: Deleting Content From Fossil</b></a></li>
180186
<li><a href="fiveminutes.wiki">Single User &mdash; Update and Running in 5 Minutes as a</a></li>
181187
<li><a href="../../../sitemap"><b>Site Map</b></a></li>
182188
<li><a href="style.wiki"><b>Source Code Style Guidelines</b></a></li>
183189
<li><a href="antibot.wiki">Spiders and Bots &mdash; Defense against</a></li>
184190
--- www/permutedindex.html
+++ www/permutedindex.html
@@ -29,10 +29,11 @@
29 <li><a href="blame.wiki">Annotate/Blame Algorithm Of Fossil &mdash; The</a></li>
30 <li><a href="customskin.md">Appearance of Web Pages &mdash; Theming: Customizing The</a></li>
31 <li><a href="faq.wiki">Asked Questions &mdash; Frequently</a></li>
32 <li><a href="password.wiki">Authentication &mdash; Password Management And</a></li>
33 <li><a href="whyusefossil.wiki"><b>Benefits Of Version Control</b></a></li>
 
34 <li><a href="antibot.wiki">Bots &mdash; Defense against Spiders and</a></li>
35 <li><a href="private.wiki">Branches &mdash; Creating, Syncing, and Deleting Private</a></li>
36 <li><a href="branching.wiki"><b>Branching, Forking, Merging, and Tagging</b></a></li>
37 <li><a href="bugtheory.wiki"><b>Bug Tracking In Fossil</b></a></li>
38 <li><a href="makefile.wiki">Build Process &mdash; The Fossil</a></li>
@@ -43,10 +44,11 @@
43 <li><a href="checkin.wiki">Checklist &mdash; Check-in</a></li>
44 <li><a href="../test/release-checklist.wiki">Checklist &mdash; Pre-Release Testing</a></li>
45 <li><a href="foss-cklist.wiki"><b>Checklist For Successful Open-Source Projects</b></a></li>
46 <li><a href="selfcheck.wiki">Checks &mdash; Fossil Repository Integrity Self</a></li>
47 <li><a href="childprojects.wiki"><b>Child Projects</b></a></li>
 
48 <li><a href="contribute.wiki">Code or Documentation To The Fossil Project &mdash; Contributing</a></li>
49 <li><a href="style.wiki">Code Style Guidelines &mdash; Source</a></li>
50 <li><a href="../../../help">Commands and Webpages &mdash; Lists of</a></li>
51 <li><a href="build.wiki"><b>Compiling and Installing Fossil</b></a></li>
52 <li><a href="concepts.wiki">Concepts &mdash; Fossil Core</a></li>
@@ -111,10 +113,11 @@
111 <li><a href="customgraph.md">Graph &mdash; Theming: Customizing the Timeline</a></li>
112 <li><a href="quickstart.wiki">Guide &mdash; Fossil Quick Start</a></li>
113 <li><a href="style.wiki">Guidelines &mdash; Source Code Style</a></li>
114 <li><a href="hacker-howto.wiki"><b>Hacker How-To</b></a></li>
115 <li><a href="adding_code.wiki"><b>Hacking Fossil</b></a></li>
 
116 <li><a href="hints.wiki">Hints &mdash; Fossil Tips And Usage</a></li>
117 <li><a href="index.wiki"><b>Home Page</b></a></li>
118 <li><a href="selfhost.wiki">Hosting Repositories &mdash; Fossil Self</a></li>
119 <li><a href="aboutcgi.wiki"><b>How CGI Works In Fossil</b></a></li>
120 <li><a href="server.wiki"><b>How To Configure A Fossil Server</b></a></li>
@@ -147,10 +150,11 @@
147 <li><a href="index.wiki">Page &mdash; Home</a></li>
148 <li><a href="customskin.md">Pages &mdash; Theming: Customizing The Appearance of Web</a></li>
149 <li><a href="password.wiki"><b>Password Management And Authentication</b></a></li>
150 <li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General &mdash; Quotes: What</a></li>
151 <li><a href="stats.wiki"><b>Performance Statistics</b></a></li>
 
152 <li><a href="../test/release-checklist.wiki"><b>Pre-Release Testing Checklist</b></a></li>
153 <li><a href="pop.wiki"><b>Principles Of Operation</b></a></li>
154 <li><a href="private.wiki">Private Branches &mdash; Creating, Syncing, and Deleting</a></li>
155 <li><a href="makefile.wiki">Process &mdash; The Fossil Build</a></li>
156 <li><a href="contribute.wiki">Project &mdash; Contributing Code or Documentation To The Fossil</a></li>
@@ -174,10 +178,12 @@
174 <li><a href="th1.md">Scripting Language &mdash; The TH1</a></li>
175 <li><a href="selfcheck.wiki">Self Checks &mdash; Fossil Repository Integrity</a></li>
176 <li><a href="selfhost.wiki">Self Hosting Repositories &mdash; Fossil</a></li>
177 <li><a href="server.wiki">Server &mdash; How To Configure A Fossil</a></li>
178 <li><a href="settings.wiki">Settings &mdash; Fossil</a></li>
 
 
179 <li><a href="shunning.wiki"><b>Shunning: Deleting Content From Fossil</b></a></li>
180 <li><a href="fiveminutes.wiki">Single User &mdash; Update and Running in 5 Minutes as a</a></li>
181 <li><a href="../../../sitemap"><b>Site Map</b></a></li>
182 <li><a href="style.wiki"><b>Source Code Style Guidelines</b></a></li>
183 <li><a href="antibot.wiki">Spiders and Bots &mdash; Defense against</a></li>
184
--- www/permutedindex.html
+++ www/permutedindex.html
@@ -29,10 +29,11 @@
29 <li><a href="blame.wiki">Annotate/Blame Algorithm Of Fossil &mdash; The</a></li>
30 <li><a href="customskin.md">Appearance of Web Pages &mdash; Theming: Customizing The</a></li>
31 <li><a href="faq.wiki">Asked Questions &mdash; Frequently</a></li>
32 <li><a href="password.wiki">Authentication &mdash; Password Management And</a></li>
33 <li><a href="whyusefossil.wiki"><b>Benefits Of Version Control</b></a></li>
34 <li><a href="hashpolicy.wiki">Between SHA1 and SHA3-256 &mdash; Hash Policy: Choosing</a></li>
35 <li><a href="antibot.wiki">Bots &mdash; Defense against Spiders and</a></li>
36 <li><a href="private.wiki">Branches &mdash; Creating, Syncing, and Deleting Private</a></li>
37 <li><a href="branching.wiki"><b>Branching, Forking, Merging, and Tagging</b></a></li>
38 <li><a href="bugtheory.wiki"><b>Bug Tracking In Fossil</b></a></li>
39 <li><a href="makefile.wiki">Build Process &mdash; The Fossil</a></li>
@@ -43,10 +44,11 @@
44 <li><a href="checkin.wiki">Checklist &mdash; Check-in</a></li>
45 <li><a href="../test/release-checklist.wiki">Checklist &mdash; Pre-Release Testing</a></li>
46 <li><a href="foss-cklist.wiki"><b>Checklist For Successful Open-Source Projects</b></a></li>
47 <li><a href="selfcheck.wiki">Checks &mdash; Fossil Repository Integrity Self</a></li>
48 <li><a href="childprojects.wiki"><b>Child Projects</b></a></li>
49 <li><a href="hashpolicy.wiki">Choosing Between SHA1 and SHA3-256 &mdash; Hash Policy:</a></li>
50 <li><a href="contribute.wiki">Code or Documentation To The Fossil Project &mdash; Contributing</a></li>
51 <li><a href="style.wiki">Code Style Guidelines &mdash; Source</a></li>
52 <li><a href="../../../help">Commands and Webpages &mdash; Lists of</a></li>
53 <li><a href="build.wiki"><b>Compiling and Installing Fossil</b></a></li>
54 <li><a href="concepts.wiki">Concepts &mdash; Fossil Core</a></li>
@@ -111,10 +113,11 @@
113 <li><a href="customgraph.md">Graph &mdash; Theming: Customizing the Timeline</a></li>
114 <li><a href="quickstart.wiki">Guide &mdash; Fossil Quick Start</a></li>
115 <li><a href="style.wiki">Guidelines &mdash; Source Code Style</a></li>
116 <li><a href="hacker-howto.wiki"><b>Hacker How-To</b></a></li>
117 <li><a href="adding_code.wiki"><b>Hacking Fossil</b></a></li>
118 <li><a href="hashpolicy.wiki"><b>Hash Policy: Choosing Between SHA1 and SHA3-256</b></a></li>
119 <li><a href="hints.wiki">Hints &mdash; Fossil Tips And Usage</a></li>
120 <li><a href="index.wiki"><b>Home Page</b></a></li>
121 <li><a href="selfhost.wiki">Hosting Repositories &mdash; Fossil Self</a></li>
122 <li><a href="aboutcgi.wiki"><b>How CGI Works In Fossil</b></a></li>
123 <li><a href="server.wiki"><b>How To Configure A Fossil Server</b></a></li>
@@ -147,10 +150,11 @@
150 <li><a href="index.wiki">Page &mdash; Home</a></li>
151 <li><a href="customskin.md">Pages &mdash; Theming: Customizing The Appearance of Web</a></li>
152 <li><a href="password.wiki"><b>Password Management And Authentication</b></a></li>
153 <li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General &mdash; Quotes: What</a></li>
154 <li><a href="stats.wiki"><b>Performance Statistics</b></a></li>
155 <li><a href="hashpolicy.wiki">Policy: Choosing Between SHA1 and SHA3-256 &mdash; Hash</a></li>
156 <li><a href="../test/release-checklist.wiki"><b>Pre-Release Testing Checklist</b></a></li>
157 <li><a href="pop.wiki"><b>Principles Of Operation</b></a></li>
158 <li><a href="private.wiki">Private Branches &mdash; Creating, Syncing, and Deleting</a></li>
159 <li><a href="makefile.wiki">Process &mdash; The Fossil Build</a></li>
160 <li><a href="contribute.wiki">Project &mdash; Contributing Code or Documentation To The Fossil</a></li>
@@ -174,10 +178,12 @@
178 <li><a href="th1.md">Scripting Language &mdash; The TH1</a></li>
179 <li><a href="selfcheck.wiki">Self Checks &mdash; Fossil Repository Integrity</a></li>
180 <li><a href="selfhost.wiki">Self Hosting Repositories &mdash; Fossil</a></li>
181 <li><a href="server.wiki">Server &mdash; How To Configure A Fossil</a></li>
182 <li><a href="settings.wiki">Settings &mdash; Fossil</a></li>
183 <li><a href="hashpolicy.wiki">SHA1 and SHA3-256 &mdash; Hash Policy: Choosing Between</a></li>
184 <li><a href="hashpolicy.wiki">SHA3-256 &mdash; Hash Policy: Choosing Between SHA1 and</a></li>
185 <li><a href="shunning.wiki"><b>Shunning: Deleting Content From Fossil</b></a></li>
186 <li><a href="fiveminutes.wiki">Single User &mdash; Update and Running in 5 Minutes as a</a></li>
187 <li><a href="../../../sitemap"><b>Site Map</b></a></li>
188 <li><a href="style.wiki"><b>Source Code Style Guidelines</b></a></li>
189 <li><a href="antibot.wiki">Spiders and Bots &mdash; Defense against</a></li>
190
+7 -6
--- www/pop.wiki
+++ www/pop.wiki
@@ -25,17 +25,18 @@
2525
The global state represents the content of the project.
2626
The local state identifies the authorized users and
2727
access policies for a particular repository.</p></li>
2828
2929
<li><p>The global state of a repository is an unordered
30
-collection of artifacts. Each artifact is named by
31
-its SHA1 hash encoded in lowercase hexadecimal.
30
+collection of artifacts. Each artifact is named by a
31
+cryptographic hash (SHA1 or SHA3-256) encoded in
32
+lowercase hexadecimal.
3233
In many contexts, the name can be
3334
abbreviated to a unique prefix. A five- or six-character
3435
prefix usually suffices to uniquely identify a file.</p></li>
3536
36
-<li><p>Because artifacts are named by their SHA1 hash, all artifacts
37
+<li><p>Because artifacts are named by a cryptographic hash, all artifacts
3738
are immutable. Any change to the content of an artifact also
3839
changes the hash that forms the artifacts name, thus
3940
creating a new artifact. Both the old original version of the
4041
artifact and the new change are preserved under different names.</p></li>
4142
@@ -42,16 +43,16 @@
4243
<li><p>It is theoretically possible for two artifacts with different
4344
content to share the same hash. But finding two such
4445
artifacts is so incredibly difficult and unlikely that we
4546
consider it to be an impossibility.</p></li>
4647
47
-<li><p>The signature of an artifact is the SHA1 hash of the
48
+<li><p>The signature of an artifact is the cryptographic hash of the
4849
artifact itself, exactly as it would appear in a disk file. No prefix
4950
or meta-information about the artifact is added before computing
5051
the hash. So you can
51
-always find the SHA1 signature of a file by using the
52
-"sha1sum" command-line utility.</p></li>
52
+always find the signature of a file by using the
53
+"sha1sum" or "sha3sum" or similar command-line utilities.</p></li>
5354
5455
<li><p>The artifacts that comprise the global state of a repository
5556
are the complete global state of that repository. The SQLite
5657
database that holds the repository contains additional information
5758
about linkages between artifacts, but all of that added information
5859
--- www/pop.wiki
+++ www/pop.wiki
@@ -25,17 +25,18 @@
25 The global state represents the content of the project.
26 The local state identifies the authorized users and
27 access policies for a particular repository.</p></li>
28
29 <li><p>The global state of a repository is an unordered
30 collection of artifacts. Each artifact is named by
31 its SHA1 hash encoded in lowercase hexadecimal.
 
32 In many contexts, the name can be
33 abbreviated to a unique prefix. A five- or six-character
34 prefix usually suffices to uniquely identify a file.</p></li>
35
36 <li><p>Because artifacts are named by their SHA1 hash, all artifacts
37 are immutable. Any change to the content of an artifact also
38 changes the hash that forms the artifacts name, thus
39 creating a new artifact. Both the old original version of the
40 artifact and the new change are preserved under different names.</p></li>
41
@@ -42,16 +43,16 @@
42 <li><p>It is theoretically possible for two artifacts with different
43 content to share the same hash. But finding two such
44 artifacts is so incredibly difficult and unlikely that we
45 consider it to be an impossibility.</p></li>
46
47 <li><p>The signature of an artifact is the SHA1 hash of the
48 artifact itself, exactly as it would appear in a disk file. No prefix
49 or meta-information about the artifact is added before computing
50 the hash. So you can
51 always find the SHA1 signature of a file by using the
52 "sha1sum" command-line utility.</p></li>
53
54 <li><p>The artifacts that comprise the global state of a repository
55 are the complete global state of that repository. The SQLite
56 database that holds the repository contains additional information
57 about linkages between artifacts, but all of that added information
58
--- www/pop.wiki
+++ www/pop.wiki
@@ -25,17 +25,18 @@
25 The global state represents the content of the project.
26 The local state identifies the authorized users and
27 access policies for a particular repository.</p></li>
28
29 <li><p>The global state of a repository is an unordered
30 collection of artifacts. Each artifact is named by a
31 cryptographic hash (SHA1 or SHA3-256) encoded in
32 lowercase hexadecimal.
33 In many contexts, the name can be
34 abbreviated to a unique prefix. A five- or six-character
35 prefix usually suffices to uniquely identify a file.</p></li>
36
37 <li><p>Because artifacts are named by a cryptographic hash, all artifacts
38 are immutable. Any change to the content of an artifact also
39 changes the hash that forms the artifacts name, thus
40 creating a new artifact. Both the old original version of the
41 artifact and the new change are preserved under different names.</p></li>
42
@@ -42,16 +43,16 @@
43 <li><p>It is theoretically possible for two artifacts with different
44 content to share the same hash. But finding two such
45 artifacts is so incredibly difficult and unlikely that we
46 consider it to be an impossibility.</p></li>
47
48 <li><p>The signature of an artifact is the cryptographic hash of the
49 artifact itself, exactly as it would appear in a disk file. No prefix
50 or meta-information about the artifact is added before computing
51 the hash. So you can
52 always find the signature of a file by using the
53 "sha1sum" or "sha3sum" or similar command-line utilities.</p></li>
54
55 <li><p>The artifacts that comprise the global state of a repository
56 are the complete global state of that repository. The SQLite
57 database that holds the repository contains additional information
58 about linkages between artifacts, but all of that added information
59
--- www/selfcheck.wiki
+++ www/selfcheck.wiki
@@ -51,14 +51,14 @@
5151
commit. So during the course of check-in (or other repository
5252
operation) many different files
5353
in the repository might be modified. Some files are simply
5454
compressed. Other files are delta encoded and then compressed.
5555
While all this is going on, fossil makes a record of every file
56
-that is encoded and the SHA1 hash of the original content of that
56
+and the SHA1 or SHA3-256 hash of the original content of that
5757
file. Then just before transaction commit, fossil re-extracts
58
-the original content of all files that were written, computes
59
-the SHA1 checksum again, and verifies that the checksums match.
58
+the original content of all files that were written, recomputes
59
+the hash, and verifies that the recomputed hash still matches.
6060
If anything does not match up, an error
6161
message is printed and the transaction rolls back.
6262
6363
So, in other words, fossil always checks to make sure it can
6464
re-extract a file before it commits a change to that file.
@@ -73,12 +73,12 @@
7373
and of all other files in the manifest. Prior to any check-in
7474
commit, these checksums are verified to ensure that the check-in
7575
agrees exactly with what is on disk. Similarly,
7676
the repository checksum is verified after a checkout to make
7777
sure that the entire repository was checked out correctly.
78
-Note that these added checks use a different hash (MD5 instead
79
-of SHA1) in order to avoid common-mode failures in the hash
78
+Note that these added checks use a different hash algorithm (MD5)
79
+in order to avoid common-mode failures in the hash
8080
algorithm implementation.
8181
8282
8383
<h2>Checksums On Control Artifacts And Deltas</h2>
8484
8585
--- www/selfcheck.wiki
+++ www/selfcheck.wiki
@@ -51,14 +51,14 @@
51 commit. So during the course of check-in (or other repository
52 operation) many different files
53 in the repository might be modified. Some files are simply
54 compressed. Other files are delta encoded and then compressed.
55 While all this is going on, fossil makes a record of every file
56 that is encoded and the SHA1 hash of the original content of that
57 file. Then just before transaction commit, fossil re-extracts
58 the original content of all files that were written, computes
59 the SHA1 checksum again, and verifies that the checksums match.
60 If anything does not match up, an error
61 message is printed and the transaction rolls back.
62
63 So, in other words, fossil always checks to make sure it can
64 re-extract a file before it commits a change to that file.
@@ -73,12 +73,12 @@
73 and of all other files in the manifest. Prior to any check-in
74 commit, these checksums are verified to ensure that the check-in
75 agrees exactly with what is on disk. Similarly,
76 the repository checksum is verified after a checkout to make
77 sure that the entire repository was checked out correctly.
78 Note that these added checks use a different hash (MD5 instead
79 of SHA1) in order to avoid common-mode failures in the hash
80 algorithm implementation.
81
82
83 <h2>Checksums On Control Artifacts And Deltas</h2>
84
85
--- www/selfcheck.wiki
+++ www/selfcheck.wiki
@@ -51,14 +51,14 @@
51 commit. So during the course of check-in (or other repository
52 operation) many different files
53 in the repository might be modified. Some files are simply
54 compressed. Other files are delta encoded and then compressed.
55 While all this is going on, fossil makes a record of every file
56 and the SHA1 or SHA3-256 hash of the original content of that
57 file. Then just before transaction commit, fossil re-extracts
58 the original content of all files that were written, recomputes
59 the hash, and verifies that the recomputed hash still matches.
60 If anything does not match up, an error
61 message is printed and the transaction rolls back.
62
63 So, in other words, fossil always checks to make sure it can
64 re-extract a file before it commits a change to that file.
@@ -73,12 +73,12 @@
73 and of all other files in the manifest. Prior to any check-in
74 commit, these checksums are verified to ensure that the check-in
75 agrees exactly with what is on disk. Similarly,
76 the repository checksum is verified after a checkout to make
77 sure that the entire repository was checked out correctly.
78 Note that these added checks use a different hash algorithm (MD5)
79 in order to avoid common-mode failures in the hash
80 algorithm implementation.
81
82
83 <h2>Checksums On Control Artifacts And Deltas</h2>
84
85
--- www/shunning.wiki
+++ www/shunning.wiki
@@ -23,11 +23,11 @@
2323
<h2>Shunning</h2>
2424
2525
Fossil provides a mechanism called "shunning" for removing content from
2626
a repository.
2727
28
-Every Fossil repository maintains a list of the SHA1 hash names of
28
+Every Fossil repository maintains a list of the hash names of
2929
"shunned" artifacts.
3030
Fossil will refuse to push or pull any shunned artifact.
3131
Furthermore, all shunned artifacts (but not the shunning list
3232
itself) are removed from the
3333
repository whenever the repository is reconstructed using the
3434
--- www/shunning.wiki
+++ www/shunning.wiki
@@ -23,11 +23,11 @@
23 <h2>Shunning</h2>
24
25 Fossil provides a mechanism called "shunning" for removing content from
26 a repository.
27
28 Every Fossil repository maintains a list of the SHA1 hash names of
29 "shunned" artifacts.
30 Fossil will refuse to push or pull any shunned artifact.
31 Furthermore, all shunned artifacts (but not the shunning list
32 itself) are removed from the
33 repository whenever the repository is reconstructed using the
34
--- www/shunning.wiki
+++ www/shunning.wiki
@@ -23,11 +23,11 @@
23 <h2>Shunning</h2>
24
25 Fossil provides a mechanism called "shunning" for removing content from
26 a repository.
27
28 Every Fossil repository maintains a list of the hash names of
29 "shunned" artifacts.
30 Fossil will refuse to push or pull any shunned artifact.
31 Furthermore, all shunned artifacts (but not the shunning list
32 itself) are removed from the
33 repository whenever the repository is reconstructed using the
34
+14 -14
--- www/sync.wiki
+++ www/sync.wiki
@@ -4,23 +4,23 @@
44
content between two Fossil repositories.</p>
55
66
<h2>1.0 Overview</h2>
77
88
<p>The global state of a fossil repository consists of an unordered
9
-collection of artifacts. Each artifact is identified by its SHA1 hash
10
-expressed as a 40-character lower-case hexadecimal string.
9
+collection of artifacts. Each artifact is identified by a cryptographic
10
+hash of its content, expressed as a lower-case hexadecimal string.
1111
Synchronization is the process of sharing artifacts between
1212
servers so that all servers have copies of all artifacts. Because
1313
artifacts are unordered, the order in which artifacts are received
14
-at a server is inconsequential. It is assumed that the SHA1 hashes
15
-of artifacts are unique - that every artifact has a different SHA1 hash.
14
+at a server is inconsequential. It is assumed that the hash names
15
+of artifacts are unique - that every artifact has a different hash.
1616
To a first approximation, synchronization proceeds by sharing lists
17
-SHA1 hashes of available artifacts, then sharing those artifacts that
18
-are not found on one side or the other of the connection. In practice,
19
-a repository might contain millions of artifacts. The list of
20
-SHA1 hashes for this many artifacts can be large. So optimizations are
21
-employed that usually reduce the number of SHA1 hashes that need to be
17
+hash values for available artifacts, then sharing the content of artifacts
18
+whose names are missing from one side or the other of the connection.
19
+In practice, a repository might contain millions of artifacts. The list of
20
+hash names for this many artifacts can be large. So optimizations are
21
+employed that usually reduce the number of hashes that need to be
2222
shared to a few hundred.</p>
2323
2424
<p>Each repository also has local state. The local state determines
2525
the web-page formatting preferences, authorized users, ticket formats,
2626
and similar information that varies from one repository to another.
@@ -198,11 +198,11 @@
198198
terminates the file card.
199199
</p>
200200
201201
<p>The first argument of a file card is the ID of the artifact that
202202
is being transferred. The artifact ID is the lower-case hexadecimal
203
-representation of the SHA1 hash of the artifact.
203
+representation of the name hash for the artifact.
204204
The last argument of the file card is the number of bytes of
205205
payload that immediately follow the file card. If the file
206206
card has only two arguments, that means the payload is the
207207
complete content of the artifact. If the file card has three
208208
arguments, then the payload is a delta and second argument is
@@ -231,11 +231,11 @@
231231
<b>cfile</b> <i>artifact-id delta-artifact-id usize csize</i> <b>\n</b> <i>content</i><br>
232232
</blockquote>
233233
234234
<p>The first argument of the cfile card is the ID of the artifact that
235235
is being transferred. The artifact ID is the lower-case hexadecimal
236
-representation of the SHA1 hash of the artifact. The second argument of
236
+representation of the name hash for the artifact. The second argument of
237237
the cfile card is the original size in bytes of the artifact. The last
238238
argument of the cfile card is the number of compressed bytes of payload
239239
that immediately follow the cfile card. If the cfile card has only
240240
three arguments, that means the payload is the complete content of the
241241
artifact. If the cfile card has four arguments, then the payload is a
@@ -271,11 +271,11 @@
271271
<b>uvfile</b> <i>name mtime hash size flags</i> <b>\n</b> <i>content</i>
272272
</blockquote>
273273
274274
<p>The <i>name</i> field is the name of the unversioned file. The
275275
<i>mtime</i> is the last modification time of the file in seconds
276
-since 1970. The <i>hash</i> field is the SHA1 hash of the content
276
+since 1970. The <i>hash</i> field is the hash of the content
277277
for the unversioned file, or "<b>-</b>" for deleted content.
278278
The <i>size</i> field is the (uncompressed) size of the content
279279
in bytes. The <i>flags</i> field is an integer which is interpreted
280280
as an array of bits. The 0x0004 bit of <i>flags</i> indicates that
281281
the <i>content</i> is to be omitted. The content might be omitted if
@@ -409,12 +409,12 @@
409409
</blockquote>
410410
411411
<p>The <i>name</i> argument is the name of an unversioned file.
412412
The <i>mtime</i> is the last modification time of the unversioned file
413413
in seconds since 1970.
414
-The <i>hash</i> is the SHA1 hash of the unversioned file content, or
415
-"<b>-</b>" if the file has been deleted.
414
+The <i>hash</i> is the SHA1 or SHA3-256 hash of the unversioned file
415
+content, or "<b>-</b>" if the file has been deleted.
416416
The <i>size</i> is the uncompressed size of the file in bytes.
417417
418418
<p>When the server sees a "pragma uv-hash" card for which the hash
419419
does not match, it sends uvigot cards for every unversioned file that it
420420
holds. The client will use this information to figure out which
421421
--- www/sync.wiki
+++ www/sync.wiki
@@ -4,23 +4,23 @@
4 content between two Fossil repositories.</p>
5
6 <h2>1.0 Overview</h2>
7
8 <p>The global state of a fossil repository consists of an unordered
9 collection of artifacts. Each artifact is identified by its SHA1 hash
10 expressed as a 40-character lower-case hexadecimal string.
11 Synchronization is the process of sharing artifacts between
12 servers so that all servers have copies of all artifacts. Because
13 artifacts are unordered, the order in which artifacts are received
14 at a server is inconsequential. It is assumed that the SHA1 hashes
15 of artifacts are unique - that every artifact has a different SHA1 hash.
16 To a first approximation, synchronization proceeds by sharing lists
17 SHA1 hashes of available artifacts, then sharing those artifacts that
18 are not found on one side or the other of the connection. In practice,
19 a repository might contain millions of artifacts. The list of
20 SHA1 hashes for this many artifacts can be large. So optimizations are
21 employed that usually reduce the number of SHA1 hashes that need to be
22 shared to a few hundred.</p>
23
24 <p>Each repository also has local state. The local state determines
25 the web-page formatting preferences, authorized users, ticket formats,
26 and similar information that varies from one repository to another.
@@ -198,11 +198,11 @@
198 terminates the file card.
199 </p>
200
201 <p>The first argument of a file card is the ID of the artifact that
202 is being transferred. The artifact ID is the lower-case hexadecimal
203 representation of the SHA1 hash of the artifact.
204 The last argument of the file card is the number of bytes of
205 payload that immediately follow the file card. If the file
206 card has only two arguments, that means the payload is the
207 complete content of the artifact. If the file card has three
208 arguments, then the payload is a delta and second argument is
@@ -231,11 +231,11 @@
231 <b>cfile</b> <i>artifact-id delta-artifact-id usize csize</i> <b>\n</b> <i>content</i><br>
232 </blockquote>
233
234 <p>The first argument of the cfile card is the ID of the artifact that
235 is being transferred. The artifact ID is the lower-case hexadecimal
236 representation of the SHA1 hash of the artifact. The second argument of
237 the cfile card is the original size in bytes of the artifact. The last
238 argument of the cfile card is the number of compressed bytes of payload
239 that immediately follow the cfile card. If the cfile card has only
240 three arguments, that means the payload is the complete content of the
241 artifact. If the cfile card has four arguments, then the payload is a
@@ -271,11 +271,11 @@
271 <b>uvfile</b> <i>name mtime hash size flags</i> <b>\n</b> <i>content</i>
272 </blockquote>
273
274 <p>The <i>name</i> field is the name of the unversioned file. The
275 <i>mtime</i> is the last modification time of the file in seconds
276 since 1970. The <i>hash</i> field is the SHA1 hash of the content
277 for the unversioned file, or "<b>-</b>" for deleted content.
278 The <i>size</i> field is the (uncompressed) size of the content
279 in bytes. The <i>flags</i> field is an integer which is interpreted
280 as an array of bits. The 0x0004 bit of <i>flags</i> indicates that
281 the <i>content</i> is to be omitted. The content might be omitted if
@@ -409,12 +409,12 @@
409 </blockquote>
410
411 <p>The <i>name</i> argument is the name of an unversioned file.
412 The <i>mtime</i> is the last modification time of the unversioned file
413 in seconds since 1970.
414 The <i>hash</i> is the SHA1 hash of the unversioned file content, or
415 "<b>-</b>" if the file has been deleted.
416 The <i>size</i> is the uncompressed size of the file in bytes.
417
418 <p>When the server sees a "pragma uv-hash" card for which the hash
419 does not match, it sends uvigot cards for every unversioned file that it
420 holds. The client will use this information to figure out which
421
--- www/sync.wiki
+++ www/sync.wiki
@@ -4,23 +4,23 @@
4 content between two Fossil repositories.</p>
5
6 <h2>1.0 Overview</h2>
7
8 <p>The global state of a fossil repository consists of an unordered
9 collection of artifacts. Each artifact is identified by a cryptographic
10 hash of its content, expressed as a lower-case hexadecimal string.
11 Synchronization is the process of sharing artifacts between
12 servers so that all servers have copies of all artifacts. Because
13 artifacts are unordered, the order in which artifacts are received
14 at a server is inconsequential. It is assumed that the hash names
15 of artifacts are unique - that every artifact has a different hash.
16 To a first approximation, synchronization proceeds by sharing lists
17 hash values for available artifacts, then sharing the content of artifacts
18 whose names are missing from one side or the other of the connection.
19 In practice, a repository might contain millions of artifacts. The list of
20 hash names for this many artifacts can be large. So optimizations are
21 employed that usually reduce the number of hashes that need to be
22 shared to a few hundred.</p>
23
24 <p>Each repository also has local state. The local state determines
25 the web-page formatting preferences, authorized users, ticket formats,
26 and similar information that varies from one repository to another.
@@ -198,11 +198,11 @@
198 terminates the file card.
199 </p>
200
201 <p>The first argument of a file card is the ID of the artifact that
202 is being transferred. The artifact ID is the lower-case hexadecimal
203 representation of the name hash for the artifact.
204 The last argument of the file card is the number of bytes of
205 payload that immediately follow the file card. If the file
206 card has only two arguments, that means the payload is the
207 complete content of the artifact. If the file card has three
208 arguments, then the payload is a delta and second argument is
@@ -231,11 +231,11 @@
231 <b>cfile</b> <i>artifact-id delta-artifact-id usize csize</i> <b>\n</b> <i>content</i><br>
232 </blockquote>
233
234 <p>The first argument of the cfile card is the ID of the artifact that
235 is being transferred. The artifact ID is the lower-case hexadecimal
236 representation of the name hash for the artifact. The second argument of
237 the cfile card is the original size in bytes of the artifact. The last
238 argument of the cfile card is the number of compressed bytes of payload
239 that immediately follow the cfile card. If the cfile card has only
240 three arguments, that means the payload is the complete content of the
241 artifact. If the cfile card has four arguments, then the payload is a
@@ -271,11 +271,11 @@
271 <b>uvfile</b> <i>name mtime hash size flags</i> <b>\n</b> <i>content</i>
272 </blockquote>
273
274 <p>The <i>name</i> field is the name of the unversioned file. The
275 <i>mtime</i> is the last modification time of the file in seconds
276 since 1970. The <i>hash</i> field is the hash of the content
277 for the unversioned file, or "<b>-</b>" for deleted content.
278 The <i>size</i> field is the (uncompressed) size of the content
279 in bytes. The <i>flags</i> field is an integer which is interpreted
280 as an array of bits. The 0x0004 bit of <i>flags</i> indicates that
281 the <i>content</i> is to be omitted. The content might be omitted if
@@ -409,12 +409,12 @@
409 </blockquote>
410
411 <p>The <i>name</i> argument is the name of an unversioned file.
412 The <i>mtime</i> is the last modification time of the unversioned file
413 in seconds since 1970.
414 The <i>hash</i> is the SHA1 or SHA3-256 hash of the unversioned file
415 content, or "<b>-</b>" if the file has been deleted.
416 The <i>size</i> is the uncompressed size of the file in bytes.
417
418 <p>When the server sees a "pragma uv-hash" card for which the hash
419 does not match, it sends uvigot cards for every unversioned file that it
420 holds. The client will use this information to figure out which
421
--- www/tech_overview.wiki
+++ www/tech_overview.wiki
@@ -173,11 +173,12 @@
173173
the [/help/deconstruct | fossil deconstruct]
174174
command. Individual artifacts can be extracted using the
175175
[/help/artifact | fossil artifact] command.
176176
When accessing the repository database using raw SQL and the
177177
[/help/sqlite3 | fossil sql] command, the extension function
178
-"<tt>content()</tt>" with a single argument which is the SHA1 hash
178
+"<tt>content()</tt>" with a single argument which is the SHA1 or
179
+SHA3-256 hash
179180
of an artifact will return the complete undeleted and uncompressed
180181
content of that artifact.
181182
182183
Going the other way, the [/help/reconstruct | fossil reconstruct]
183184
command will scan a directory hierarchy and add all files found to
@@ -278,11 +279,11 @@
278279
project - is intended to be an append-only database. In other words,
279280
new artifacts can be added but artifacts can never be removed. But
280281
it sometimes happens that inappropriate content is mistakenly or
281282
maliciously added to a repository. The only way to get rid of
282283
the undesired content is to [./shunning.wiki | "shun"] it.
283
-The "shun" table in the repository database records the SHA1 hash of
284
+The "shun" table in the repository database records the hash values for
284285
all shunned artifacts.
285286
286287
The shun table can be pushed or pulled using
287288
the [/help/config | fossil config] command with the "shun" AREA argument.
288289
The shun table is also copied during a [/help/clone | clone].
289290
--- www/tech_overview.wiki
+++ www/tech_overview.wiki
@@ -173,11 +173,12 @@
173 the [/help/deconstruct | fossil deconstruct]
174 command. Individual artifacts can be extracted using the
175 [/help/artifact | fossil artifact] command.
176 When accessing the repository database using raw SQL and the
177 [/help/sqlite3 | fossil sql] command, the extension function
178 "<tt>content()</tt>" with a single argument which is the SHA1 hash
 
179 of an artifact will return the complete undeleted and uncompressed
180 content of that artifact.
181
182 Going the other way, the [/help/reconstruct | fossil reconstruct]
183 command will scan a directory hierarchy and add all files found to
@@ -278,11 +279,11 @@
278 project - is intended to be an append-only database. In other words,
279 new artifacts can be added but artifacts can never be removed. But
280 it sometimes happens that inappropriate content is mistakenly or
281 maliciously added to a repository. The only way to get rid of
282 the undesired content is to [./shunning.wiki | "shun"] it.
283 The "shun" table in the repository database records the SHA1 hash of
284 all shunned artifacts.
285
286 The shun table can be pushed or pulled using
287 the [/help/config | fossil config] command with the "shun" AREA argument.
288 The shun table is also copied during a [/help/clone | clone].
289
--- www/tech_overview.wiki
+++ www/tech_overview.wiki
@@ -173,11 +173,12 @@
173 the [/help/deconstruct | fossil deconstruct]
174 command. Individual artifacts can be extracted using the
175 [/help/artifact | fossil artifact] command.
176 When accessing the repository database using raw SQL and the
177 [/help/sqlite3 | fossil sql] command, the extension function
178 "<tt>content()</tt>" with a single argument which is the SHA1 or
179 SHA3-256 hash
180 of an artifact will return the complete undeleted and uncompressed
181 content of that artifact.
182
183 Going the other way, the [/help/reconstruct | fossil reconstruct]
184 command will scan a directory hierarchy and add all files found to
@@ -278,11 +279,11 @@
279 project - is intended to be an append-only database. In other words,
280 new artifacts can be added but artifacts can never be removed. But
281 it sometimes happens that inappropriate content is mistakenly or
282 maliciously added to a repository. The only way to get rid of
283 the undesired content is to [./shunning.wiki | "shun"] it.
284 The "shun" table in the repository database records the hash values for
285 all shunned artifacts.
286
287 The shun table can be pushed or pulled using
288 the [/help/config | fossil config] command with the "shun" AREA argument.
289 The shun table is also copied during a [/help/clone | clone].
290
--- www/theory1.wiki
+++ www/theory1.wiki
@@ -38,11 +38,12 @@
3838
been checked into the Fossil repository. Call these "content artifacts".
3939
Other artifacts, known as
4040
"control artifacts", contain ASCII text in a particular format that
4141
defines relationships between other artifacts, such as which
4242
content artifacts that go together to form a particular version of the
43
-project. Each artifact is named by its SHA1 hash and is thus immutable.
43
+project. Each artifact is named by its SHA1 or SHA3-256 hash and is
44
+thus immutable.
4445
Artifacts can be added to the database but not removed (if we ignore
4546
the exceptional case of [./shunning.wiki | shunning].) Repositories
4647
synchronize by computing the union of their artifact sets. SQL and
4748
relation theory play no role in any of this.
4849
4950
--- www/theory1.wiki
+++ www/theory1.wiki
@@ -38,11 +38,12 @@
38 been checked into the Fossil repository. Call these "content artifacts".
39 Other artifacts, known as
40 "control artifacts", contain ASCII text in a particular format that
41 defines relationships between other artifacts, such as which
42 content artifacts that go together to form a particular version of the
43 project. Each artifact is named by its SHA1 hash and is thus immutable.
 
44 Artifacts can be added to the database but not removed (if we ignore
45 the exceptional case of [./shunning.wiki | shunning].) Repositories
46 synchronize by computing the union of their artifact sets. SQL and
47 relation theory play no role in any of this.
48
49
--- www/theory1.wiki
+++ www/theory1.wiki
@@ -38,11 +38,12 @@
38 been checked into the Fossil repository. Call these "content artifacts".
39 Other artifacts, known as
40 "control artifacts", contain ASCII text in a particular format that
41 defines relationships between other artifacts, such as which
42 content artifacts that go together to form a particular version of the
43 project. Each artifact is named by its SHA1 or SHA3-256 hash and is
44 thus immutable.
45 Artifacts can be added to the database but not removed (if we ignore
46 the exceptional case of [./shunning.wiki | shunning].) Repositories
47 synchronize by computing the union of their artifact sets. SQL and
48 relation theory play no role in any of this.
49
50
--- www/webpage-ex.md
+++ www/webpage-ex.md
@@ -123,10 +123,10 @@
123123
href='$ROOT/bigbloblist'>Example</a>
124124
The largest objects in the repository.
125125
126126
* <a target='_blank' class='exbtn'
127127
href='$ROOT/hash-collisions'>Example</a>
128
- SHA1 prefix collisions
128
+ Hash prefix collisions
129129
130130
* <a target='_blank' class='exbtn'
131131
href='$ROOT/sitemap'>Example</a>
132132
The "sitemap" containing links to many other pages
133133
--- www/webpage-ex.md
+++ www/webpage-ex.md
@@ -123,10 +123,10 @@
123 href='$ROOT/bigbloblist'>Example</a>
124 The largest objects in the repository.
125
126 * <a target='_blank' class='exbtn'
127 href='$ROOT/hash-collisions'>Example</a>
128 SHA1 prefix collisions
129
130 * <a target='_blank' class='exbtn'
131 href='$ROOT/sitemap'>Example</a>
132 The "sitemap" containing links to many other pages
133
--- www/webpage-ex.md
+++ www/webpage-ex.md
@@ -123,10 +123,10 @@
123 href='$ROOT/bigbloblist'>Example</a>
124 The largest objects in the repository.
125
126 * <a target='_blank' class='exbtn'
127 href='$ROOT/hash-collisions'>Example</a>
128 Hash prefix collisions
129
130 * <a target='_blank' class='exbtn'
131 href='$ROOT/sitemap'>Example</a>
132 The "sitemap" containing links to many other pages
133
--- www/whyusefossil.wiki
+++ www/whyusefossil.wiki
@@ -232,18 +232,19 @@
232232
</ul>
233233
</ul>
234234
<li><p><b>Why version control is important (reprise)</b>
235235
<ol type="A">
236236
<li><p>Every check-in and every individual file has a unique name - its
237
- SHA1 hash. Team members can unambiguously identify any specific
237
+ SHA1 or SHA3-256 hash. Team members can unambiguously identify
238
+ any specific
238239
version of the overall project or any specific version of an
239240
individual file.
240241
<li><p>Any historical version of the whole project or of any individual
241242
file can be easily recreated at any time and by any team member.
242243
<li><p>Accidental changes to files can be detected by recomputing their
243
- SHA1 hash.
244
- <li><p>Files of unknown origin can be identified using their SHA1 hash.
244
+ cryptographic hash.
245
+ <li><p>Files of unknown origin can be identified using their hash.
245246
<li><p>Developers are able to work in parallel, review each others work,
246247
and easily merge their changes together. External revisions to
247248
the baseline can be easily incorporated into the latest changes.
248249
<li><p>Developers can follow experimental lines of development, then
249250
revert back to an earlier stable version if the experiment does
250251
--- www/whyusefossil.wiki
+++ www/whyusefossil.wiki
@@ -232,18 +232,19 @@
232 </ul>
233 </ul>
234 <li><p><b>Why version control is important (reprise)</b>
235 <ol type="A">
236 <li><p>Every check-in and every individual file has a unique name - its
237 SHA1 hash. Team members can unambiguously identify any specific
 
238 version of the overall project or any specific version of an
239 individual file.
240 <li><p>Any historical version of the whole project or of any individual
241 file can be easily recreated at any time and by any team member.
242 <li><p>Accidental changes to files can be detected by recomputing their
243 SHA1 hash.
244 <li><p>Files of unknown origin can be identified using their SHA1 hash.
245 <li><p>Developers are able to work in parallel, review each others work,
246 and easily merge their changes together. External revisions to
247 the baseline can be easily incorporated into the latest changes.
248 <li><p>Developers can follow experimental lines of development, then
249 revert back to an earlier stable version if the experiment does
250
--- www/whyusefossil.wiki
+++ www/whyusefossil.wiki
@@ -232,18 +232,19 @@
232 </ul>
233 </ul>
234 <li><p><b>Why version control is important (reprise)</b>
235 <ol type="A">
236 <li><p>Every check-in and every individual file has a unique name - its
237 SHA1 or SHA3-256 hash. Team members can unambiguously identify
238 any specific
239 version of the overall project or any specific version of an
240 individual file.
241 <li><p>Any historical version of the whole project or of any individual
242 file can be easily recreated at any time and by any team member.
243 <li><p>Accidental changes to files can be detected by recomputing their
244 cryptographic hash.
245 <li><p>Files of unknown origin can be identified using their hash.
246 <li><p>Developers are able to work in parallel, review each others work,
247 and easily merge their changes together. External revisions to
248 the baseline can be easily incorporated into the latest changes.
249 <li><p>Developers can follow experimental lines of development, then
250 revert back to an earlier stable version if the experiment does
251

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button