Fossil

Check-in [e8c4f69c50]
Login

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

Overview
Comment:Change all mentions of "UUID" in the documentation and help screens into either "artifact ID" or "baseline ID" or "ticket ID" as appropriate. "UUID" has a widely recognized meaning that is different from its meaning in fossil. "UUID" is still used in code comments and in variable names.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e8c4f69c50ecbe4388aa28e489050e7ca6be2ed8
User & Date: drh 2008-10-24 13:27:53.000
Original Comment: Change all mentions of UUID in the documentation and help screens into either "artifact ID" or "baseline ID" or "ticket ID" as appropriate. UUID has a widely recognized meaning that is different from its meaning in fossil.
References
2008-10-24
13:49 Fixed ticket [368a5d6c5b]: specifying a tag in command should default to the latest UUID with that tag plus 5 other changes artifact: 922539e0ab user: drh
Context
2008-10-24
14:03
Remove control characters from rse-notes.txt. check-in: 9a482dd701 user: drh tags: trunk
13:27
Change all mentions of "UUID" in the documentation and help screens into either "artifact ID" or "baseline ID" or "ticket ID" as appropriate. "UUID" has a widely recognized meaning that is different from its meaning in fossil. "UUID" is still used in code comments and in variable names. check-in: e8c4f69c50 user: drh tags: trunk
11:14
Allow the "_FOSSIL_" file at the root of each check-out to be renamed ".fos". At some point we might make .fos the default, but for now _FOSSIL_ is the default. The file can be freely changed between these two names. check-in: 8bdea95c58 user: drh tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/descendants.c.
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  bag_clear(&seen);
  pqueue_clear(&queue);
}

/*
** COMMAND:  descendants
**
** Usage: %fossil descendants ?UUID?
**
** Find all leaf descendants of the current version or of the
** specified version.
*/
void descendants_cmd(void){
  Stmt q;
  int base;

  db_must_be_within_tree();
  if( g.argc==2 ){







|

|
|







128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  bag_clear(&seen);
  pqueue_clear(&queue);
}

/*
** COMMAND:  descendants
**
** Usage: %fossil descendants ?BASELINE-ID?
**
** Find all leaf descendants of the baseline specified or if the argument
** is omitted, of the baseline currently checked out.
*/
void descendants_cmd(void){
  Stmt q;
  int base;

  db_must_be_within_tree();
  if( g.argc==2 ){
Changes to src/info.c.
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  }
}


/*
** COMMAND: info
**
** Usage: %fossil info ?UUID|FILENAME?
**
** With no arguments, provide information about the current tree.
** If an argument is given, provide information about the record
** in the respository of the current tree that the argument refers
** to.  Or if the argument is the name of a repository, show
** information about that repository.
*/
void info_cmd(void){
  i64 fsize;
  if( g.argc!=2 && g.argc!=3 ){
    usage("?FILENAME|UUID?");
  }
  if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
    db_open_config();
    db_record_repository_filename(g.argv[2]);
    db_open_repository(g.argv[2]);
    printf("project-code: %s\n", db_get("project-code", "<none>"));
    printf("project-name: %s\n", db_get("project-name", "<unnamed>"));







|


|







|







70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  }
}


/*
** COMMAND: info
**
** Usage: %fossil info ?ARTIFACT-ID|FILENAME?
**
** With no arguments, provide information about the current tree.
** If an argument is specified, provide information about the object
** in the respository of the current tree that the argument refers
** to.  Or if the argument is the name of a repository, show
** information about that repository.
*/
void info_cmd(void){
  i64 fsize;
  if( g.argc!=2 && g.argc!=3 ){
    usage("?FILENAME|ARTIFACT-ID?");
  }
  if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
    db_open_config();
    db_record_repository_filename(g.argv[2]);
    db_open_repository(g.argv[2]);
    printf("project-code: %s\n", db_get("project-code", "<none>"));
    printf("project-name: %s\n", db_get("project-name", "<unnamed>"));
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
    @ </ul>
  }
}


/*
** WEBPAGE: vinfo
** URL:  /vinfo?name=RID|UUID
**
** Return information about a baseline
*/
void vinfo_page(void){
  Stmt q;
  int rid;
  int isLeaf;







|







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
    @ </ul>
  }
}


/*
** WEBPAGE: vinfo
** URL:  /vinfo?name=RID|ARTIFACTID
**
** Return information about a baseline
*/
void vinfo_page(void){
  Stmt q;
  int rid;
  int isLeaf;
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
  @ </pre></blockquote>
  blob_reset(&diff);
  style_footer();
}

/*
** WEBPAGE: artifact
** URL: /artifact?name=UUID
** 
** Show the complete content of a file identified by UUID
** as preformatted text.
*/
void artifact_page(void){
  int rid;
  Blob content;

  rid = name_to_rid(PD("name","0"));







|

|







793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
  @ </pre></blockquote>
  blob_reset(&diff);
  style_footer();
}

/*
** WEBPAGE: artifact
** URL: /artifact?name=ARTIFACTID
** 
** Show the complete content of a file identified by ARTIFACTID
** as preformatted text.
*/
void artifact_page(void){
  int rid;
  Blob content;

  rid = name_to_rid(PD("name","0"));
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
  @ </pre></blockquote>
  blob_reset(&content);
  style_footer();
}

/*
** WEBPAGE: tinfo
** URL: /tinfo?name=UUID
**
** Show the details of a ticket change control artifact.
*/
void tinfo_page(void){
  int rid;
  Blob content;
  char *zDate;







|







832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
  @ </pre></blockquote>
  blob_reset(&content);
  style_footer();
}

/*
** WEBPAGE: tinfo
** URL: /tinfo?name=ARTIFACTID
**
** Show the details of a ticket change control artifact.
*/
void tinfo_page(void){
  int rid;
  Blob content;
  char *zDate;
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
  manifest_clear(&m);
  style_footer();
}


/*
** WEBPAGE: info
** URL: info/UUID
**
** The argument is a UUID which might be a baseline or a file or
** a ticket changes or a wiki editor or something else. 
**
** Figure out what the UUID is and jump to it.
*/
void info_page(void){
  const char *zName;
  Blob uuid;
  int rid, nName;
  
  zName = P("name");







|

|


|







886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
  manifest_clear(&m);
  style_footer();
}


/*
** WEBPAGE: info
** URL: info/ARTIFACTID
**
** The argument is a artifact ID which might be a baseline or a file or
** a ticket changes or a wiki editor or something else. 
**
** Figure out what the artifact ID is and jump to it.
*/
void info_page(void){
  const char *zName;
  Blob uuid;
  int rid, nName;
  
  zName = P("name");
Changes to src/name.c.
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
** attempts to produce a UUID. See tag_to_uuid.
*/
int sym_tag_to_uuid(const char *pName, Blob *pUuid){
    return tag_to_uuid(pName,pUuid,"sym-");
}

/*
** COMMAND:  test-name-to-uuid
**
** Convert a name to a full UUID.
*/
void test_name_to_uuid(void){
  int i;
  Blob name;
  db_must_be_within_tree();
  for(i=2; i<g.argc; i++){
    blob_init(&name, g.argv[i], -1);
    printf("%s -> ", g.argv[i]);
    if( name_to_uuid(&name, 1) ){







|

|

|







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
** attempts to produce a UUID. See tag_to_uuid.
*/
int sym_tag_to_uuid(const char *pName, Blob *pUuid){
    return tag_to_uuid(pName,pUuid,"sym-");
}

/*
** COMMAND:  test-name-to-id
**
** Convert a name to a full artifact ID.
*/
void test_name_to_id(void){
  int i;
  Blob name;
  db_must_be_within_tree();
  for(i=2; i<g.argc; i++){
    blob_init(&name, g.argv[i], -1);
    printf("%s -> ", g.argv[i]);
    if( name_to_uuid(&name, 1) ){
Changes to src/tag.c.
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
    tag_propagate(rid, tagid, tagtype, zValue, mtime);
  }
}


/*
** COMMAND: test-tag
** %fossil test-tag (+|*|-)TAGNAME UUID ?VALUE?
**
** Add a tag or anti-tag to the rebuildable tables of the local repository.
** No tag artifact is created so the new tag is erased the next
** time the repository is rebuilt.  This routine is for testing
** use only.
*/
void testtag_cmd(void){
  const char *zTag;
  const char *zValue;
  int rid;
  int tagtype;
  db_must_be_within_tree();
  if( g.argc!=4 && g.argc!=5 ){
    usage("TAGNAME UUID ?VALUE?");
  }
  zTag = g.argv[2];
  switch( zTag[0] ){
    case '+':  tagtype = 1;  break;
    case '*':  tagtype = 2;  break;
    case '-':  tagtype = 0;  break;
    default:   







|













|







209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
    tag_propagate(rid, tagid, tagtype, zValue, mtime);
  }
}


/*
** COMMAND: test-tag
** %fossil test-tag (+|*|-)TAGNAME ARTIFACT-ID ?VALUE?
**
** Add a tag or anti-tag to the rebuildable tables of the local repository.
** No tag artifact is created so the new tag is erased the next
** time the repository is rebuilt.  This routine is for testing
** use only.
*/
void testtag_cmd(void){
  const char *zTag;
  const char *zValue;
  int rid;
  int tagtype;
  db_must_be_within_tree();
  if( g.argc!=4 && g.argc!=5 ){
    usage("TAGNAME ARTIFACT-ID ?VALUE?");
  }
  zTag = g.argv[2];
  switch( zTag[0] ){
    case '+':  tagtype = 1;  break;
    case '*':  tagtype = 2;  break;
    case '-':  tagtype = 0;  break;
    default:   
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  zValue = g.argc==5 ? g.argv[4] : 0;
  db_begin_transaction();
  tag_insert(zTag, tagtype, zValue, -1, 0.0, rid);
  db_end_transaction(0); 
}

/*
** Prepare an artifact that describes a fork from a certain UUID.
** Furthermore a propagating symbolic tag will be inserted and
** all other propagating symbolic tags will be cancelled.
**
** The changes are appended at the Blob pCtrl. However the manifest
** is not complete at that stage.
*/
static void tag_prepare_fork(







|







245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  zValue = g.argc==5 ? g.argv[4] : 0;
  db_begin_transaction();
  tag_insert(zTag, tagtype, zValue, -1, 0.0, rid);
  db_end_transaction(0); 
}

/*
** Prepare an artifact that describes a fork from a certain baseline.
** Furthermore a propagating symbolic tag will be inserted and
** all other propagating symbolic tags will be cancelled.
**
** The changes are appended at the Blob pCtrl. However the manifest
** is not complete at that stage.
*/
static void tag_prepare_fork(
330
331
332
333
334
335
336

337

338

339
340
341
342
343
344
345
  if( name_to_uuid(&uuid, 9) ){
    return;
  }
  rid = name_to_rid(blob_str(&uuid));
  blob_zero(&ctrl);

  if( validate16(zTagname, strlen(zTagname)) ){

    fossil_fatal("invalid tag name \"%s\" - might be confused with a UUID",

                 zTagname);

  }
  if( fork ){
    tag_prepare_fork(&ctrl, zTagname, rid, preflen);
  }else{
    zDate = db_text(0, "SELECT datetime('now')");
    zDate[10] = 'T';
    blob_appendf(&ctrl, "D %s\n", zDate);







>
|
>
|
>







330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
  if( name_to_uuid(&uuid, 9) ){
    return;
  }
  rid = name_to_rid(blob_str(&uuid));
  blob_zero(&ctrl);

  if( validate16(zTagname, strlen(zTagname)) ){
    fossil_fatal(
       "invalid tag name \"%s\" - might be confused with"
       " a hexadecimal artifact ID",
       zTagname
    );
  }
  if( fork ){
    tag_prepare_fork(&ctrl, zTagname, rid, preflen);
  }else{
    zDate = db_text(0, "SELECT datetime('now')");
    zDate[10] = 'T';
    blob_appendf(&ctrl, "D %s\n", zDate);
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

/*
** COMMAND: tag
** Usage: %fossil tag SUBCOMMAND ...
**
** Run various subcommands to control tags and properties
**
**     %fossil tag add ?--raw? TAGNAME UUID ?VALUE?
**
**         Add a new tag or property to UUID. The tag will
**         be usable instead of a UUID in commands such as
**         update and merge.
**
**     %fossil tag branch ?--raw? ?--nofork? TAGNAME UUID ?VALUE?
**
**         A fork will be created so that the new checkin
**         is a sibling of UUID and identical to it except
**         for a generated comment. Then the new tag will
**         be added to the new checkin and propagated to
**         all direct children.  Additionally all symbolic
**         tags of that checkin inherited from UUID will
**         be cancelled.
**
**         However, if the option --nofork is given, no
**         fork will be created and the tag/property will be
**         added to UUID directly. No tags will be canceled.
**
**     %fossil tag cancel ?--raw? TAGNAME UUID
**
**         Remove the tag TAGNAME from UUID, and also remove
**         the propagation of the tag to any descendants.
**
**     %fossil tag find ?--raw? TAGNAME
**
**         List all baselines that use TAGNAME
**
**     %fossil tag list ?--raw? ?UUID?
**
**         List all tags, or if UUID is supplied, list
**         all tags and their values for UUID.
**
** The option --raw allows the manipulation of all types of
** tags used for various internal purposes in fossil. You
** should not use this option to make changes unless you are
** sure what you are doing.
**
** If you need to use a tagname that might be confused with
** a UUID, you can explicitly disambiguate it by prefixing
** it with "tag:". For instance:
**
**   fossil update decaf
**
** will be taken as a UUID and fossil will probably complain
** that no such revision was found. However
**
**   fossil update tag:decaf
**
** will assume that "decaf" is a tag/branch name.
**
*/
void tag_cmd(void){







|

|
|


|


|



|




|

|

|






|

|
|







|
|



|
|







367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427

/*
** COMMAND: tag
** Usage: %fossil tag SUBCOMMAND ...
**
** Run various subcommands to control tags and properties
**
**     %fossil tag add ?--raw? TAGNAME BASELINE ?VALUE?
**
**         Add a new tag or property to BASELINE. The tag will
**         be usable instead of a BASELINE in commands such as
**         update and merge.
**
**     %fossil tag branch ?--raw? ?--nofork? TAGNAME BASELINE ?VALUE?
**
**         A fork will be created so that the new checkin
**         is a sibling of BASELINE and identical to it except
**         for a generated comment. Then the new tag will
**         be added to the new checkin and propagated to
**         all direct children.  Additionally all symbolic
**         tags of that checkin inherited from BASELINE will
**         be cancelled.
**
**         However, if the option --nofork is given, no
**         fork will be created and the tag/property will be
**         added to BASELINE directly. No tags will be canceled.
**
**     %fossil tag cancel ?--raw? TAGNAME BASELINE
**
**         Remove the tag TAGNAME from BASELINE, and also remove
**         the propagation of the tag to any descendants.
**
**     %fossil tag find ?--raw? TAGNAME
**
**         List all baselines that use TAGNAME
**
**     %fossil tag list ?--raw? ?BASELINE?
**
**         List all tags, or if BASELINE is supplied, list
**         all tags and their values for BASELINE.
**
** The option --raw allows the manipulation of all types of
** tags used for various internal purposes in fossil. You
** should not use this option to make changes unless you are
** sure what you are doing.
**
** If you need to use a tagname that might be confused with
** a hexadecimal baseline or artifact ID, you can explicitly
** disambiguate it by prefixing it with "tag:". For instance:
**
**   fossil update decaf
**
** will be taken as an artifact or baseline ID and fossil will
** probably complain that no such revision was found. However
**
**   fossil update tag:decaf
**
** will assume that "decaf" is a tag/branch name.
**
*/
void tag_cmd(void){
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
  }

  blob_set(&tagname, prefix);

  if( strncmp(g.argv[2],"add",n)==0 ){
    char *zValue;
    if( g.argc!=5 && g.argc!=6 ){
      usage("add ?--raw? TAGNAME UUID ?VALUE?");
    }
    blob_append(&tagname, g.argv[3], strlen(g.argv[3]));
    zValue = g.argc==6 ? g.argv[5] : 0;
    tag_add_artifact(blob_str(&tagname), g.argv[4], zValue, 1, 0, 0);
  }else

  if( strncmp(g.argv[2],"branch",n)==0 ){
    char *zValue;
    if( g.argc!=5 && g.argc!=6 ){
      usage("branch ?--raw? ?--nofork? TAGNAME UUID ?VALUE?");
    }
    blob_append(&tagname, g.argv[3], strlen(g.argv[3]));
    zValue = g.argc==6 ? g.argv[5] : 0;
    tag_add_artifact(blob_str(&tagname), g.argv[4], zValue, 2, fork!=0,
                                                      preflen);
    if( fork ){
      const char *zUuid = db_text(0, "SELECT uuid, MAX(rowid) FROM blob");
      printf("New_Fork \"%s\": %s\n", g.argv[3], zUuid);
    }
  }else

  if( strncmp(g.argv[2],"cancel",n)==0 ){
    if( g.argc!=5 ){
      usage("cancel ?--raw? TAGNAME UUID");
    }
    blob_append(&tagname, g.argv[3], strlen(g.argv[3]));
    tag_add_artifact(blob_str(&tagname), g.argv[4], 0, 0, 0, 0);
  }else

  if( strncmp(g.argv[2],"find",n)==0 ){
    Stmt q;







|









|













|







442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
  }

  blob_set(&tagname, prefix);

  if( strncmp(g.argv[2],"add",n)==0 ){
    char *zValue;
    if( g.argc!=5 && g.argc!=6 ){
      usage("add ?--raw? TAGNAME BASELINE ?VALUE?");
    }
    blob_append(&tagname, g.argv[3], strlen(g.argv[3]));
    zValue = g.argc==6 ? g.argv[5] : 0;
    tag_add_artifact(blob_str(&tagname), g.argv[4], zValue, 1, 0, 0);
  }else

  if( strncmp(g.argv[2],"branch",n)==0 ){
    char *zValue;
    if( g.argc!=5 && g.argc!=6 ){
      usage("branch ?--raw? ?--nofork? TAGNAME BASELINE ?VALUE?");
    }
    blob_append(&tagname, g.argv[3], strlen(g.argv[3]));
    zValue = g.argc==6 ? g.argv[5] : 0;
    tag_add_artifact(blob_str(&tagname), g.argv[4], zValue, 2, fork!=0,
                                                      preflen);
    if( fork ){
      const char *zUuid = db_text(0, "SELECT uuid, MAX(rowid) FROM blob");
      printf("New_Fork \"%s\": %s\n", g.argv[3], zUuid);
    }
  }else

  if( strncmp(g.argv[2],"cancel",n)==0 ){
    if( g.argc!=5 ){
      usage("cancel ?--raw? TAGNAME BASELINE");
    }
    blob_append(&tagname, g.argv[3], strlen(g.argv[3]));
    tag_add_artifact(blob_str(&tagname), g.argv[4], 0, 0, 0, 0);
  }else

  if( strncmp(g.argv[2],"find",n)==0 ){
    Stmt q;
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
          if( raw || strncmp(zName, prefix, preflen)==0 ){
            printf("%s\n", zName+preflen);
          }
        }
      }
      db_finalize(&q);
    }else{
      usage("tag list ?UUID?");
    }
  }else
  {
    goto tag_cmd_usage;
  }

  /* Cleanup */
  blob_reset(&tagname);
  return;

tag_cmd_usage:
  usage("add|branch|cancel|find|list ...");
}







|













530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
          if( raw || strncmp(zName, prefix, preflen)==0 ){
            printf("%s\n", zName+preflen);
          }
        }
      }
      db_finalize(&q);
    }else{
      usage("tag list ?BASELINE?");
    }
  }else
  {
    goto tag_cmd_usage;
  }

  /* Cleanup */
  blob_reset(&tagname);
  return;

tag_cmd_usage:
  usage("add|branch|cancel|find|list ...");
}
Changes to src/timeline.c.
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
  ;
  return zBaseSql;
}

/*
** COMMAND: timeline
**
** Usage: %fossil timeline ?WHEN? ?UUID|DATETIME? ?-n|--count N?
**
** Print a summary of activity going backwards in date and time
** specified or from the current date and time if no arguments
** are given.  Show as many as N (default 20) check-ins.  The
** WHEN argument can be any unique abbreviation of one of these
** keywords:
**
**     before
**     after
**     descendants | children
**     ancestors | parents
**
** The UUID can be any unique prefix of 4 characters or more.
** The DATETIME should be in the ISO8601 format.  For
** examples: "2007-08-18 07:21:21".  You can also say "current"
** for the current version or "now" for the current time.
*/
void timeline_cmd(void){
  Stmt q;
  int n, k;







|












|







552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
  ;
  return zBaseSql;
}

/*
** COMMAND: timeline
**
** Usage: %fossil timeline ?WHEN? ?BASELINE|DATETIME? ?-n|--count N?
**
** Print a summary of activity going backwards in date and time
** specified or from the current date and time if no arguments
** are given.  Show as many as N (default 20) check-ins.  The
** WHEN argument can be any unique abbreviation of one of these
** keywords:
**
**     before
**     after
**     descendants | children
**     ancestors | parents
**
** The BASELINE can be any unique prefix of 4 characters or more.
** The DATETIME should be in the ISO8601 format.  For
** examples: "2007-08-18 07:21:21".  You can also say "current"
** for the current version or "now" for the current time.
*/
void timeline_cmd(void){
  Stmt q;
  int n, k;
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
    }else if( strncmp(g.argv[2],"children",k)==0 ){
      mode = 3;
    }else if( strncmp(g.argv[2],"ancestors",k)==0 && k>1 ){
      mode = 4;
    }else if( strncmp(g.argv[2],"parents",k)==0 ){
      mode = 4;
    }else{
      usage("?WHEN? ?UUID|DATETIME?");
    }
    zOrigin = g.argv[3];
  }else if( g.argc==3 ){
    zOrigin = g.argv[2];
  }else{
    zOrigin = "now";
  }







|







602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
    }else if( strncmp(g.argv[2],"children",k)==0 ){
      mode = 3;
    }else if( strncmp(g.argv[2],"ancestors",k)==0 && k>1 ){
      mode = 4;
    }else if( strncmp(g.argv[2],"parents",k)==0 ){
      mode = 4;
    }else{
      usage("?WHEN? ?BASELINE|DATETIME?");
    }
    zOrigin = g.argv[3];
  }else if( g.argc==3 ){
    zOrigin = g.argv[2];
  }else{
    zOrigin = "now";
  }
Changes to src/wiki.c.
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

/*
** WEBPAGE: wiki
** URL: /wiki?name=PAGENAME
*/
void wiki_page(void){
  char *zTag;
  int rid;
  int isSandbox;
  Blob wiki;
  Manifest m;
  const char *zPageName;
  char *zHtmlPageName;
  char *zBody = mprintf("%s","<i>Empty Page</i>");








|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

/*
** WEBPAGE: wiki
** URL: /wiki?name=PAGENAME
*/
void wiki_page(void){
  char *zTag;
  int rid = 0;
  int isSandbox;
  Blob wiki;
  Manifest m;
  const char *zPageName;
  char *zHtmlPageName;
  char *zBody = mprintf("%s","<i>Empty Page</i>");

549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
  @ <li> <p><b>Indented Paragraphs</b>.
  @ Any paragraph that begins with two or more spaces or a tab and
  @ which is not a bullet or enumeration list item is rendered 
  @ indented.  Only a single level of indentation is supported by wiki; use
  @ HTML for deeper indentation.</p>
  @ <li> <p><b>Hyperlinks</b>.
  @ Text within square brackets ("[...]") becomes a hyperlink.  The
  @ target can be a wiki page name, the UUID of a check-in or ticket,
  @ the name of an image, or a URL.  By default, the target is displayed
  @ as the text of the hyperlink.  But you can specify alternative text
  @ after the target name separated by a "|" character.</p>
  @ <li> <p><b>HTML</b>.
  @ The following standard HTML elements may be used:
  @ &lt;a&gt;
  @ &lt;address&gt;







|







549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
  @ <li> <p><b>Indented Paragraphs</b>.
  @ Any paragraph that begins with two or more spaces or a tab and
  @ which is not a bullet or enumeration list item is rendered 
  @ indented.  Only a single level of indentation is supported by wiki; use
  @ HTML for deeper indentation.</p>
  @ <li> <p><b>Hyperlinks</b>.
  @ Text within square brackets ("[...]") becomes a hyperlink.  The
  @ target can be a wiki page name, the artifact ID of a check-in or ticket,
  @ the name of an image, or a URL.  By default, the target is displayed
  @ as the text of the hyperlink.  But you can specify alternative text
  @ after the target name separated by a "|" character.</p>
  @ <li> <p><b>HTML</b>.
  @ The following standard HTML elements may be used:
  @ &lt;a&gt;
  @ &lt;address&gt;
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
**     %fossil wiki list
**
**        Lists all wiki entries, one per line, ordered
**        case-insentively by name.
**
** TODOs:
**
**     %fossil wiki export ?-u UUID? WikiName ?FILE?
**
**        Outputs the selected version of WikiName.
**
**     %fossil wiki delete ?-m MESSAGE? WikiName
**
**        The same as deleting a file entry, but i don't know if fossil
**        supports a commit message for Wiki entries.
**
**     %fossil wiki ?-u? ?-d? ?-s=[|]? list
**
**        Lists the UUID and/or Date of last change along with each entry
**        name, delimited by the -s char.
**
**     %fossil wiki diff ?UUID? ?-f infile[=stdin]? EntryName
**
**        Diffs the local copy of a page with a given version (defaulting
**        to the head version).
*/
void wiki_cmd(void){
  int n;
  db_find_and_open_repository(1);







|










|
|

|







705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
**     %fossil wiki list
**
**        Lists all wiki entries, one per line, ordered
**        case-insentively by name.
**
** TODOs:
**
**     %fossil wiki export ?-u ARTIFACT? WikiName ?FILE?
**
**        Outputs the selected version of WikiName.
**
**     %fossil wiki delete ?-m MESSAGE? WikiName
**
**        The same as deleting a file entry, but i don't know if fossil
**        supports a commit message for Wiki entries.
**
**     %fossil wiki ?-u? ?-d? ?-s=[|]? list
**
**        Lists the artifact ID and/or Date of last change along with
**        each entry name, delimited by the -s char.
**
**     %fossil wiki diff ?ARTIFACT? ?-f infile[=stdin]? EntryName
**
**        Diffs the local copy of a page with a given version (defaulting
**        to the head version).
*/
void wiki_cmd(void){
  int n;
  db_find_and_open_repository(1);
Changes to www/bugtheory.wiki.
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
make sense of the meaning of the various artifacts for themselves.

<h2>Interpretation Of Ticket Change Artifacts</h2>

Every ticket change artifact contains (among other things)

  *  a timestamp,
  *  a ticket UUID, and
  *  one or more name/value pairs.

The current state of a ticket is found by replaying all ticket
change artifacts with the same ticket UUID in timestamp order.
For a given ticket, all values are initially NULL.  As each
ticket change artifact is encountered, values are either replaced
or appended, according to a flag on the name/value pair.  The current
values for the fields of a ticket are the values that remain at the
end of the replay process.

To create a new ticket, one inserts a ticket change
artifact with a new UUID.  The ticket UUID
is a random 40-character lower-case hexadecimal number.  The "tktnew"
page in the fossil web interface creates new ticket UUIDs
using a good source of randomness to insure uniqueness.
The name/value pairs on the initial ticket change
artifact are the initial values for the fields in the ticket.

Amending a ticket means simply creating a new artifact with the
same ticket UUID and with name/value pairs for those fields which
are changing.  Fields of the ticket which are not being modified
should not appear as name/value pairs in the new artifact.

This approach to storing ticket state means that independently entered
changes are automatically merged together when artifacts are shared
between repositories.  Tickets do not branch.  This approach also makes
it trivial to track the historic progression of changes to a ticket.







|



|







|

|





|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
make sense of the meaning of the various artifacts for themselves.

<h2>Interpretation Of Ticket Change Artifacts</h2>

Every ticket change artifact contains (among other things)

  *  a timestamp,
  *  a ticket ID, and
  *  one or more name/value pairs.

The current state of a ticket is found by replaying all ticket
change artifacts with the same ticket ID in timestamp order.
For a given ticket, all values are initially NULL.  As each
ticket change artifact is encountered, values are either replaced
or appended, according to a flag on the name/value pair.  The current
values for the fields of a ticket are the values that remain at the
end of the replay process.

To create a new ticket, one inserts a ticket change
artifact with a new ID.  The ticket ID
is a random 40-character lower-case hexadecimal number.  The "tktnew"
page in the fossil web interface creates new ticket IDs
using a good source of randomness to insure uniqueness.
The name/value pairs on the initial ticket change
artifact are the initial values for the fields in the ticket.

Amending a ticket means simply creating a new artifact with the
same ticket ID and with name/value pairs for those fields which
are changing.  Fields of the ticket which are not being modified
should not appear as name/value pairs in the new artifact.

This approach to storing ticket state means that independently entered
changes are automatically merged together when artifacts are shared
between repositories.  Tickets do not branch.  This approach also makes
it trivial to track the historic progression of changes to a ticket.
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
a sync.  Each repository also has local state which is not (normally)
shared.  The name/value pairs for a ticket are part of global state,
but the interpretation and display of that information is local state.
Hence, each repository is free to set up its own ticket display and
input formats and reporting rules according to its own particular needs.

Each repository defines its own TICKET table in its database.  There is
one row in the TICKET table for each unique ticket UUID.  The
names of columns in the TICKET table correspond to the names in
the name/value pairs of ticket change artifacts.  When running the replay
algorithm, if a name/value pair is seen which has no corresponding column
in the TICKET table, then that name/value pair is ignored.  Columns can
be added or removed from the TICKET table at any time.  Whenever the
TICKET table is modified, the replay algorithm automatically reruns
to repopulate the table using the new column names.  Note that the TICKET







|







92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
a sync.  Each repository also has local state which is not (normally)
shared.  The name/value pairs for a ticket are part of global state,
but the interpretation and display of that information is local state.
Hence, each repository is free to set up its own ticket display and
input formats and reporting rules according to its own particular needs.

Each repository defines its own TICKET table in its database.  There is
one row in the TICKET table for each unique ticket ID.  The
names of columns in the TICKET table correspond to the names in
the name/value pairs of ticket change artifacts.  When running the replay
algorithm, if a name/value pair is seen which has no corresponding column
in the TICKET table, then that name/value pair is ignored.  Columns can
be added or removed from the TICKET table at any time.  Whenever the
TICKET table is modified, the replay algorithm automatically reruns
to repopulate the table using the new column names.  Note that the TICKET
Changes to www/concepts.wiki.
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

<h3>2.1 Identification Of Artifacts</h3>

<p>A particular version of a particular file is called an "artifact".
Each artifact has a universally unique name which is the
<a href="http://en.wikipedia.org/wiki/SHA">SHA1</a> hash of the content
of that file expressed as 40 characters of lower-case hexadecimal.  Such
a hash is referred to as the Universally Unique Identifier or UUID
for the artifact.  The SHA1 algorithm is created with the purpose of
providing a highly forgery-resistent identifier for a file.  Given any
file it is simple to find the UUID for that file.  But given a
UUID it is computationally intractable to generate a file that will
have that UUID.</p>


<p>UUIDs look something like this:</p>

<blockquote><b>
6089f0b563a9db0a6d90682fe47fd7161ff867c8<br>
59712614a1b3ccfd84078a37fa5b606e28434326<br>
19dbf73078be9779edd6a0156195e610f81c94f9<br>
b4104959a67175f02d6b415480be22a239f1f077<br>
997c9d6ae03ad114b2b57f04e9eeef17dcb82788
</b></blockquote>

<p>When referring to an artifact using fossil, you can use a unique
prefix of the UUID that is four characters or longer.  This saves
a lot of typing.  When displaying UUIDs, fossil will usually only
show the first 10 digits since that is normally enough to uniquely
identify a file.</p>

<p>Changing (or adding or removing) a single byte in a file results
in a completely different UUID.  And since the UUID is the name of
the artifact, making any change to a file results in a new artifact.
In this way, artifacts are immutable.</p>

<p>A repository is really just an unordered collection of
artifacts.  New artifacts can be added to the repository, but
existing artifacts can never be removed.  Fossil is designed in
such a way that it can be handed a set of artifacts in any
order and it can figure out the relationship between those
artifacts and reconstruct the complete development history of
a software project.</p>

<h3>2.2 Manifests</h3>

<p>At the root of a source tree is a special file called the
"manifest".  The manifest is a listing of all other files in
that source tree.  The manifest contains the (complete) UUID 
of the file and the name of the file as it appears on disk,
and thus serves as a mapping from UUID to disk name.  The UUID
of the manifest is the UUID that identifies a baseline.  When
you look at a "timeline" of changes in fossil, the UUID associated
with each check-in or commit is really just the UUID of the
manifest for that baseline.</p>

<p>Fossil automatically generates a manifest whenever you "commit" 
a new baseline.  So this is not something that you, the developer,
need to worry with.  The format of a manifest is intentionally
designed to be simple to parse, so that if
you want to read and interpret a manifest, either by hand or







|


|
|
|


|










|
|




|















|

|
|
|
|







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

<h3>2.1 Identification Of Artifacts</h3>

<p>A particular version of a particular file is called an "artifact".
Each artifact has a universally unique name which is the
<a href="http://en.wikipedia.org/wiki/SHA">SHA1</a> hash of the content
of that file expressed as 40 characters of lower-case hexadecimal.  Such
a hash is referred to as the Artifact Identifier or Artifact ID
for the artifact.  The SHA1 algorithm is created with the purpose of
providing a highly forgery-resistent identifier for a file.  Given any
file it is simple to find the artifact ID for that file.  But given a
artifact ID it is computationally intractable to generate a file that will
have that Artifact ID.</p>


<p>Artifact IDs look something like this:</p>

<blockquote><b>
6089f0b563a9db0a6d90682fe47fd7161ff867c8<br>
59712614a1b3ccfd84078a37fa5b606e28434326<br>
19dbf73078be9779edd6a0156195e610f81c94f9<br>
b4104959a67175f02d6b415480be22a239f1f077<br>
997c9d6ae03ad114b2b57f04e9eeef17dcb82788
</b></blockquote>

<p>When referring to an artifact using fossil, you can use a unique
prefix of the artifact ID that is four characters or longer.  This saves
a lot of typing.  When displaying artifact IDs, fossil will usually only
show the first 10 digits since that is normally enough to uniquely
identify a file.</p>

<p>Changing (or adding or removing) a single byte in a file results
in a completely different artifact ID.  And since the artifact ID is the name of
the artifact, making any change to a file results in a new artifact.
In this way, artifacts are immutable.</p>

<p>A repository is really just an unordered collection of
artifacts.  New artifacts can be added to the repository, but
existing artifacts can never be removed.  Fossil is designed in
such a way that it can be handed a set of artifacts in any
order and it can figure out the relationship between those
artifacts and reconstruct the complete development history of
a software project.</p>

<h3>2.2 Manifests</h3>

<p>At the root of a source tree is a special file called the
"manifest".  The manifest is a listing of all other files in
that source tree.  The manifest contains the (complete) artifact ID 
of the file and the name of the file as it appears on disk,
and thus serves as a mapping from artifact ID to disk name.  The artifact ID
of the manifest is the identifier for the entire baseline.  When
you look at a "timeline" of changes in fossil, the ID associated
with each check-in or commit is really just the artifact ID of the
manifest for that baseline.</p>

<p>Fossil automatically generates a manifest whenever you "commit" 
a new baseline.  So this is not something that you, the developer,
need to worry with.  The format of a manifest is intentionally
designed to be simple to parse, so that if
you want to read and interpret a manifest, either by hand or
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
<ul>
<li>A <b>baseline</b> is a set of files arranged
    in a hierarchy.</li>
<li>A <b>repository</b> keeps a record of historical baselines.</li>
<li>Repositories share their changes using <b>push</b>, <b>pull</b>,
    <b>sync</b>, and <b>clone</b>.</li>
<li>A particular version of a particular file is an <b>artifact</b>
    that is identified by a <b>UUID</b>.</li>
<li>Artifacts tracked by fossil are inherently immutable.</li>
<li>Fossil automatically generates a <b>manifest</b> file that identifies
    every artifact in a baseline.</li>
<li>The UUID of the manifest is the UUID of the baseline.</li>
</ul>

<h2>3.0 Fossil - The Program</h2>

<p>Fossil is software.  The implementation of fossil is in the form
of a single executable named "fossil".  To install fossil on your system,
all you have to do is obtain a copy of this one executable file (either







|



|







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
<ul>
<li>A <b>baseline</b> is a set of files arranged
    in a hierarchy.</li>
<li>A <b>repository</b> keeps a record of historical baselines.</li>
<li>Repositories share their changes using <b>push</b>, <b>pull</b>,
    <b>sync</b>, and <b>clone</b>.</li>
<li>A particular version of a particular file is an <b>artifact</b>
    that is identified by an <b>artifact ID</b>.</li>
<li>Artifacts tracked by fossil are inherently immutable.</li>
<li>Fossil automatically generates a <b>manifest</b> file that identifies
    every artifact in a baseline.</li>
<li>The artifact ID of the manifest is the identifier of the baseline.</li>
</ul>

<h2>3.0 Fossil - The Program</h2>

<p>Fossil is software.  The implementation of fossil is in the form
of a single executable named "fossil".  To install fossil on your system,
all you have to do is obtain a copy of this one executable file (either
Changes to www/embeddeddoc.wiki.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
For example, the <i>&lt;baseurl&gt;</i> for the fossil project itself is
either <b>http://www.fossil-scm.org/fossil</b> or
<b>http://www.hwaci.com/cgi-bin/fossil</b>.
If you launch the web server using the "<b>fossil server</b>" command line,
then the <i>&lt;baseurl&gt;</i> is usually
<b>http://localhost:8080/</b>.

The <i>&lt;version&gt;</i> is any unique UUID prefix of the baseline 
for the documentation you want to access.
Or <i>&lt;version&gt;</i> can be one of the keywords "<b>tip</b>" or
"<b>ckout</b>".  The "<b>tip</b>" keyword means to use the most recently
checked-in baseline.  This is useful if you want to see the very latest
version of the documentation.  The "<b>ckout</b>" keywords means to
pull the documentation file from the local source tree on disk, not
from the any versioned baseline.  The "<b>ckout</b>" keyword normally
only works when you start your server using the "<b>fossil server</b>"







|
|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
For example, the <i>&lt;baseurl&gt;</i> for the fossil project itself is
either <b>http://www.fossil-scm.org/fossil</b> or
<b>http://www.hwaci.com/cgi-bin/fossil</b>.
If you launch the web server using the "<b>fossil server</b>" command line,
then the <i>&lt;baseurl&gt;</i> is usually
<b>http://localhost:8080/</b>.

The <i>&lt;version&gt;</i> is any unique prefix of the baseline ID for 
the baseline containing the documentation you want to access.
Or <i>&lt;version&gt;</i> can be one of the keywords "<b>tip</b>" or
"<b>ckout</b>".  The "<b>tip</b>" keyword means to use the most recently
checked-in baseline.  This is useful if you want to see the very latest
version of the documentation.  The "<b>ckout</b>" keywords means to
pull the documentation file from the local source tree on disk, not
from the any versioned baseline.  The "<b>ckout</b>" keyword normally
only works when you start your server using the "<b>fossil server</b>"
Changes to www/fileformat.wiki.
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
</p>

<p>
Allowed cards in the cluster are as follows:
</p>

<blockquote>
<b>M</b> <i>uuid</i><br />
<b>Z</b> <i>checksum</i>
</blockquote>

<p>
A cluster contains one or more "M" cards followed by a single "Z"
line.  Each M card has a single argument which is the UUID of 
another artifact in the repository.  The Z card work exactly like
the Z card of a manifest.  The argument to the Z card is the
lower-case hexadecimal representation of the MD5 checksum of all
prior cards in the cluster.  Note that the Z card is required
on a cluster.
</p>








|





|







223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
</p>

<p>
Allowed cards in the cluster are as follows:
</p>

<blockquote>
<b>M</b> <i>artifact-id</i><br />
<b>Z</b> <i>checksum</i>
</blockquote>

<p>
A cluster contains one or more "M" cards followed by a single "Z"
line.  Each M card has a single argument which is the artifact ID of 
another artifact in the repository.  The Z card work exactly like
the Z card of a manifest.  The argument to the Z card is the
lower-case hexadecimal representation of the MD5 checksum of all
prior cards in the cluster.  Note that the Z card is required
on a cluster.
</p>

256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285

<p>
Allowed cards in a control artifact are as follows:
</p>

<blockquote>
<b>D</b> <i>time-and-date-stamp</i><br />
<b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name  uuid  ?value?</i><br />
<b>Z</b> <i>checksum</i><br />
</blockquote>

<p>
A control artifact must have one D card and one Z card and
one or more or more T cards.  No other cards or other text is
allowed in a control artifact.  Control artifacts might be PGP
clearsigned.</p>

<p>The D card and the Z card of a control artifact are the same
as in a manifest.</p>

<p>The T card represents a "tag" or property that is applied to
some other artifact.  The T card has two or three values.  The
second argument is the 40 character lowercase UUID of the artifact
to which the tag is to be applied. The
first value is the tag name.  The first character of the tag
is either "+", "-", or "*".  A "+" means the tag should be added
to the artifact.  The "-" means the tag should be removed.
The "*" character means the tag should be added to the artifact
and all direct decendants (but not branches) of the artifact down
to but not including the first decendant that contains a 







|














|







256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285

<p>
Allowed cards in a control artifact are as follows:
</p>

<blockquote>
<b>D</b> <i>time-and-date-stamp</i><br />
<b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name  artifact-id  ?value?</i><br />
<b>Z</b> <i>checksum</i><br />
</blockquote>

<p>
A control artifact must have one D card and one Z card and
one or more or more T cards.  No other cards or other text is
allowed in a control artifact.  Control artifacts might be PGP
clearsigned.</p>

<p>The D card and the Z card of a control artifact are the same
as in a manifest.</p>

<p>The T card represents a "tag" or property that is applied to
some other artifact.  The T card has two or three values.  The
second argument is the 40 character lowercase artifact ID of the artifact
to which the tag is to be applied. The
first value is the tag name.  The first character of the tag
is either "+", "-", or "*".  A "+" means the tag should be added
to the artifact.  The "-" means the tag should be removed.
The "*" character means the tag should be added to the artifact
and all direct decendants (but not branches) of the artifact down
to but not including the first decendant that contains a 
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
cards by newline characters.  The format of each card is as in
manifests, clusters, and control artifacts.  Wiki artifacts accept
the following card types:</p>

<blockquote>
<b>D</b> <i>time-and-date-stamp</i><br />
<b>L</b> <i>wiki-title</i><br />
<b>P</b> <i>parent-uuid</i>+<br />
<b>U</b> <i>user-name</i><br />
<b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br />
<b>Z</b> <i>checksum</i>
</blockquote>

<p>The D card is the date and time when the wiki page was edited.
The P card specifies the parent wiki pages, if any.  The L card







|







303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
cards by newline characters.  The format of each card is as in
manifests, clusters, and control artifacts.  Wiki artifacts accept
the following card types:</p>

<blockquote>
<b>D</b> <i>time-and-date-stamp</i><br />
<b>L</b> <i>wiki-title</i><br />
<b>P</b> <i>parent-artifact-id</i>+<br />
<b>U</b> <i>user-name</i><br />
<b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br />
<b>Z</b> <i>checksum</i>
</blockquote>

<p>The D card is the date and time when the wiki page was edited.
The P card specifies the parent wiki pages, if any.  The L card
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356

<p>A ticket-change artifact represents a change to a trouble ticket.
The following cards are allowed on a ticket change artifact:</p>

<blockquote>
<b>D</b> <i>time-and-date-stamp</i><br />
<b>J</b> ?<b>+</b>?<i>name value</i><br />
<b>K</b> <i>ticket-uuid</i><br />
<b>U</b> <i>user-name</i><br />
<b>Z</b> <i>checksum</i>
</blockquote>

<p>
The D card is the usual date and time stamp and represents the point
in time when the change was entered.  The U card is the login of the
programmer who entered this change.  The Z card is the checksum over
the entire artifact.</p>

<p>
Every ticket has a UUID.  The ticket to which this change is applied
is specified by the K card.  A ticket exists if it contains one or
more changes.  The first "change" to a ticket is what brings the
ticket into existance.</p>

<p>
J cards specify changes to "fields" of the ticket.  Each fossil
server has a ticket configuration which specifies the fields its







|











|







330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356

<p>A ticket-change artifact represents a change to a trouble ticket.
The following cards are allowed on a ticket change artifact:</p>

<blockquote>
<b>D</b> <i>time-and-date-stamp</i><br />
<b>J</b> ?<b>+</b>?<i>name value</i><br />
<b>K</b> <i>ticket-id</i><br />
<b>U</b> <i>user-name</i><br />
<b>Z</b> <i>checksum</i>
</blockquote>

<p>
The D card is the usual date and time stamp and represents the point
in time when the change was entered.  The U card is the login of the
programmer who entered this change.  The Z card is the checksum over
the entire artifact.</p>

<p>
Every ticket has a unique ID.  The ticket to which this change is applied
is specified by the K card.  A ticket exists if it contains one or
more changes.  The first "change" to a ticket is what brings the
ticket into existance.</p>

<p>
J cards specify changes to "fields" of the ticket.  Each fossil
server has a ticket configuration which specifies the fields its
Changes to www/quickstart.wiki.
157
158
159
160
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
    </blockquote>

    <p>When you pull in changes from others, they go into your repository,
    not into your checked-out local tree.  To get the changes into your
    local tree, use <b>update</b>:</p>

    <blockquote>
    <b>fossil update</b> <i>UUID</i>
    </blockquote>

    <p>The <i>UUID</i> is some unique abbreviation to the 40-character

    version ID.  If you omit the <i>UUID</i> fossil moves you to the
    leaf version of the branch your are currently on.  If your branch
    has multiple leaves, you get an error - you'll have to specify the
    leaf you want using a <i>UUID</i> argument.</p>

</blockquote><h2>Branching And Merging</h2><blockquote>

    <p>You can create branches by doing multiple commits off of the
    same base version.  To merge to branches back together, first
    <b>update</b> to the leaf of one branch.  Then do a <b>merge</b>
    of the leaf of the other branch:</p>

    <blockquote>
    <b>fossil merge</b> <i>UUID</i>
    </blockquote>

    <p>Test to make sure your merge didn't mess up the code, then
    <b>commit</b> and possibly also <b>push</b> your changes.   Remember
    that nobody else can see your changes until you <b>commit</b> and
    if other are using a different repository you will also need to
    <b>push</b>.</p>







|


|
>
|


|









|







157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
    </blockquote>

    <p>When you pull in changes from others, they go into your repository,
    not into your checked-out local tree.  To get the changes into your
    local tree, use <b>update</b>:</p>

    <blockquote>
    <b>fossil update</b> <i>AID</i>
    </blockquote>

    <p>The <i>AID</i> is some unique abbreviation to the 40-character
    artifact identifier (AID) for a particular baseline.  If you omit
    the <i>AID</i> fossil moves you to the
    leaf version of the branch your are currently on.  If your branch
    has multiple leaves, you get an error - you'll have to specify the
    leaf you want using a <i>AID</i> argument.</p>

</blockquote><h2>Branching And Merging</h2><blockquote>

    <p>You can create branches by doing multiple commits off of the
    same base version.  To merge to branches back together, first
    <b>update</b> to the leaf of one branch.  Then do a <b>merge</b>
    of the leaf of the other branch:</p>

    <blockquote>
    <b>fossil merge</b> <i>AID</i>
    </blockquote>

    <p>Test to make sure your merge didn't mess up the code, then
    <b>commit</b> and possibly also <b>push</b> your changes.   Remember
    that nobody else can see your changes until you <b>commit</b> and
    if other are using a different repository you will also need to
    <b>push</b>.</p>
Changes to www/sync.wiki.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
<h1 align="center">The Fossil Sync Protocol</h1>

<p>Fossil supports commands <b>push</b>, <b>pull</b>, and <b>sync</b>
for transferring information from one repository to another.  The
command is run on the client repository.  A URL for the server repository
is specified as part of the command.  This document describes what happens
behind the scenes in order to synchronize the information on the two
repositories.</p>

<h2>1.0 Overview</h2>

<p>The global state of a fossil repository consists of an unordered
collection of artifacts.  Each artifact is identified by its SHA1 hash.

Synchronization is simply the process of sharing artifacts between
servers so that all servers have copies of all artifacts.  Because
artifacts are unordered, the order in which artifacts are received
at a server is inconsequential.  It is assumed that the SHA1 hashes
of artifacts are unique - that every artifact has a different SHA1 hash.
To first approximation, synchronization proceeds by sharing lists 
SHA1 hashes of available artifacts, then sharing those artifacts that












|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<h1 align="center">The Fossil Sync Protocol</h1>

<p>Fossil supports commands <b>push</b>, <b>pull</b>, and <b>sync</b>
for transferring information from one repository to another.  The
command is run on the client repository.  A URL for the server repository
is specified as part of the command.  This document describes what happens
behind the scenes in order to synchronize the information on the two
repositories.</p>

<h2>1.0 Overview</h2>

<p>The global state of a fossil repository consists of an unordered
collection of artifacts.  Each artifact is identified by its SHA1 hash
expressed as a 40-character lower-case hexadecimal string.
Synchronization is simply the process of sharing artifacts between
servers so that all servers have copies of all artifacts.  Because
artifacts are unordered, the order in which artifacts are received
at a server is inconsequential.  It is assumed that the SHA1 hashes
of artifacts are unique - that every artifact has a different SHA1 hash.
To first approximation, synchronization proceeds by sharing lists 
SHA1 hashes of available artifacts, then sharing those artifacts that
148
149
150
151
152
153
154
155

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187

<p>Privileges are cumulative.  There can be multiple successful
login cards.  The session privileges are the bit-wise OR of the
privileges of each individual login.</p>

<h3>3.3 File Cards</h3>

<p>Repository content records or files are transferred using

a "file" card.  File cards come in two different formats depending
on whether the file is sent directly or as a delta from some
other file.</p>

<blockquote>
<b>file</b> <i>uuid size</i> <b>\n</b> <i>content</i><br>
<b>file</b> <i>uuid delta-uuid size</i> <b>\n</b> <i>content</i>
</blockquote>

<p>File cards are different from all other cards in that they
followed by in-line "payload" data.  The content of the file
or the file delta consists of the first <i>size</i> bytes of the
x-fossil content that immediately follow the newline that
terminates the file card.  No other cards have this characteristic.
</p>

<p>The first argument of a file card is the UUID of the file that
is being transferred.  The UUID is the lower-case hexadecimal
representation of the SHA1 hash of the entire file content.
The last argument of the file card is the number of bytes of
payload that immediately follow the file card.  If the file
card has only two arguments, that means the payload is the
complete content of the file.  If the file card has three
arguments, then the payload is a delta and second argument is
the UUID of another file that is the source of the delta.</p>

<p>File cards are sent in both directions: client to server and
server to client.  A delta might be sent before the source of
the delta, so both client and server should remember deltas
and be able to apply them when their source arrives.</p>

<h3>3.4 Push and Pull Cards</h3>







|
>
|
|
|


|
|



|
|




|
|
|



|

|







149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

<p>Privileges are cumulative.  There can be multiple successful
login cards.  The session privileges are the bit-wise OR of the
privileges of each individual login.</p>

<h3>3.3 File Cards</h3>

<p>Artifacts are transferred using "file" cards.  (The name "file"
card comes from the fact that most artifacts correspond to files.)
File cards come in two different formats depending
on whether the artifact is sent directly or as a delta from some
other artifact.</p>

<blockquote>
<b>file</b> <i>artifact-id size</i> <b>\n</b> <i>content</i><br>
<b>file</b> <i>artifact-id delta-artifact-id size</i> <b>\n</b> <i>content</i>
</blockquote>

<p>File cards are different from all other cards in that they
followed by in-line "payload" data.  The content of the artifact
or the artifact delta consists of the first <i>size</i> bytes of the
x-fossil content that immediately follow the newline that
terminates the file card.  No other cards have this characteristic.
</p>

<p>The first argument of a file card is the ID of the artifact that
is being transferred.  The artifact ID is the lower-case hexadecimal
representation of the SHA1 hash of the artifact.
The last argument of the file card is the number of bytes of
payload that immediately follow the file card.  If the file
card has only two arguments, that means the payload is the
complete content of the artifact.  If the file card has three
arguments, then the payload is a delta and second argument is
the ID of another artifact that is the source of the delta.</p>

<p>File cards are sent in both directions: client to server and
server to client.  A delta might be sent before the source of
the delta, so both client and server should remember deltas
and be able to apply them when their source arrives.</p>

<h3>3.4 Push and Pull Cards</h3>
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
a push message so that the client can discover the projectcode for
this project.</p>

<h3>3.6 Igot Cards</h3>

<p>An igot card can be sent from either client to server or from
server to client in order to indicate that the sender holds a copy
of a particular file.  The format is:</p>

<blockquote>
<b>igot</b> <i>uuid</i>
</blockquote>

<p>The argument of the igot card is the UUID of the file that
the sender possesses.
The receiver of an igot card will typically check to see if
it also holds the same file and if not it will request the file
using a gimme card in either the reply or in the next message.</p>

<h3>3.7 Gimme Cards</h3>

<p>A gimme card is sent from either client to server or from server
to client.  The gimme card asks the receiver to send a particular
file back to the sender.  The format of a gimme card is this:</p>

<blockquote>
<b>gimme</b> <i>uuid</i>
</blockquote>

<p>The argument to the gimme card is the UUID of the file that
the sender wants.  The receiver will typically respond to a
gimme card by sending a file card in its reply or in the next
message.</p>

<h3>3.8 Cookie Cards</h3>

<p>A cookie card can be used by a server to record a small amount







|


|


|


|






|


|


|







226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
a push message so that the client can discover the projectcode for
this project.</p>

<h3>3.6 Igot Cards</h3>

<p>An igot card can be sent from either client to server or from
server to client in order to indicate that the sender holds a copy
of a particular artifact.  The format is:</p>

<blockquote>
<b>igot</b> <i>artifact-id</i>
</blockquote>

<p>The argument of the igot card is the ID of the artifact that
the sender possesses.
The receiver of an igot card will typically check to see if
it also holds the same artifact and if not it will request the artifact
using a gimme card in either the reply or in the next message.</p>

<h3>3.7 Gimme Cards</h3>

<p>A gimme card is sent from either client to server or from server
to client.  The gimme card asks the receiver to send a particular
artifact back to the sender.  The format of a gimme card is this:</p>

<blockquote>
<b>gimme</b> <i>artifact-id</i>
</blockquote>

<p>The argument to the gimme card is the ID of the artifact that
the sender wants.  The receiver will typically respond to a
gimme card by sending a file card in its reply or in the next
message.</p>

<h3>3.8 Cookie Cards</h3>

<p>A cookie card can be used by a server to record a small amount
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
<h3>3.10 Unknown Cards</h3>

<p>If either the client or the server sees a card that is not
described above, then it generates an error and aborts.</p>

<h2>4.0 Phantoms And Clusters</h2>

<p>When a repository knows that a file exists and knows the UUID of
that file, but it does not know the file content, then it stores that
file as a "phantom".  A repository will typically create a phantom when
it receives an igot card for a file that it does not hold or when it
receives a file card that references a delta source that it does not
hold.  When a server is generating its reply or when a client is
generating a new request, it will usually send gimme cards for every
phantom that it holds.</p>

<p>A cluster is a special file that tells of the existence of other
files.  Any file in the repository that follows the syntactic rules
of a cluster is considered a cluster.</p>

<p>A cluster is a line oriented file.  Each line of a cluster
is a card.  The cards are separated by the newline ("\n") character.
Each card consists of a single character card type, a space, and a
single argument.  No extra whitespace and no trailing or leading
whitespace is allowed.  All cards in the cluster must occur in
strict lexicographical order.</p>

<p>A cluster consists of one or more "M" cards followed by a single
"Z" card.  Each M card holds an argument which is a UUID for a file
in the repository.  The Z card has a single argument which is the
lower-case hexadecimal representation of the MD5 checksum of all
preceding M cards up to and included the newline character that
occurred just before the Z that starts the Z card.</p>

<p>Any file that does not match the specifications of a cluster
exactly is not a cluster.  There must be no extra whitespace in
the file.  There must be one or more M cards.  There must be a
single Z card with a correct MD5 checksum.  And all cards must
be in strict lexicographical order.</p>

<h3>4.1 The Unclustered Table</h3>

<p>Every repository maintains a table named "<b>unclustered</b>"
which records the identity of every file and phantom it holds that is not
mentioned in a cluster.  The entries in the unclustered table can
be thought of as leaves on a tree of files.  Some of the unclustered
files will be clusters.  Those clusters may contain other clusters,
which might contain still more clusters, and so forth.  Beginning
with the files in the unclustered table, one can follow the chain
of clusters to find every file in the repository.</p>

<h2>5.0 Synchronization Strategies</h2>

<h3>5.1 Pull</h3>

<p>A typical pull operation proceeds as shown below.  Details
of the actual implementation may very slightly but the gist of
a pull is captured in the following steps:</p>

<ol>
<li>The client sends login and pull cards.
<li>The client sends a cookie card if it has previously received a cookie.
<li>The client sends gimme cards for every phantom that it holds.
<hr>
<li>The server checks the login password and rejects the session if
the user does not have permission to pull.
<li>If the number entries in the unclustered table on the server is
greater than 100, then the server constructs a new cluster file to
cover all those unclustered entries.
<li>The server sends file cards for every gimme card it received
from the client.
<li>The server sends ihave cards for every file in its unclustered
table that is not a phantom.
<hr>
<li>The client adds the content of file cards to its repository.
<li>The client creates a phantom for every ihave card in the server reply
that mentions a file that the client does not possess.
<li>The client creates a phantom for the delta source of file cards when
the delta source is a file that the client does not possess.
</ol>

<p>These ten steps represent a single HTTP round-trip request.
The first three steps are the processing that occurs on the client
to generate the request.  The middle four steps are processing
that occurs on the server to interpret the request and generate a
reply.  And the last three steps are the processing that the
client does to interpret the reply.</p>

<p>During a pull, the client will keep sending HTTP requests
until it holds all files that exist on the server.</p>

<p>Note that the server tries
to limit the size of its reply message to something reasonable
(usually about 1MB) so that it might stop sending file cards as
described in step (6) if the reply becomes too large.</p>

<p>Step (5) is the only way in which new clusters can be created.







|
|
|
|





|
|


|







|
|




|

|






|

|
|

|
|

















|



|




|

|










|







300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
<h3>3.10 Unknown Cards</h3>

<p>If either the client or the server sees a card that is not
described above, then it generates an error and aborts.</p>

<h2>4.0 Phantoms And Clusters</h2>

<p>When a repository knows that a artifact exists and knows the ID of
that artifact, but it does not know the artifact content, then it stores that
artifact as a "phantom".  A repository will typically create a phantom when
it receives an igot card for a artifact that it does not hold or when it
receives a file card that references a delta source that it does not
hold.  When a server is generating its reply or when a client is
generating a new request, it will usually send gimme cards for every
phantom that it holds.</p>

<p>A cluster is a special artifact that tells of the existence of other
artifacts.  Any artifact in the repository that follows the syntactic rules
of a cluster is considered a cluster.</p>

<p>A cluster is line oriented.  Each line of a cluster
is a card.  The cards are separated by the newline ("\n") character.
Each card consists of a single character card type, a space, and a
single argument.  No extra whitespace and no trailing or leading
whitespace is allowed.  All cards in the cluster must occur in
strict lexicographical order.</p>

<p>A cluster consists of one or more "M" cards followed by a single
"Z" card.  Each M card holds an argument which is a artifact ID for an
artifact in the repository.  The Z card has a single argument which is the
lower-case hexadecimal representation of the MD5 checksum of all
preceding M cards up to and included the newline character that
occurred just before the Z that starts the Z card.</p>

<p>Any artifact that does not match the specifications of a cluster
exactly is not a cluster.  There must be no extra whitespace in
the artifact.  There must be one or more M cards.  There must be a
single Z card with a correct MD5 checksum.  And all cards must
be in strict lexicographical order.</p>

<h3>4.1 The Unclustered Table</h3>

<p>Every repository maintains a table named "<b>unclustered</b>"
which records the identity of every artifact and phantom it holds that is not
mentioned in a cluster.  The entries in the unclustered table can
be thought of as leaves on a tree of artifacts.  Some of the unclustered
artifacts will be other clusters.  Those clusters may contain other clusters,
which might contain still more clusters, and so forth.  Beginning
with the artifacts in the unclustered table, one can follow the chain
of clusters to find every artifact in the repository.</p>

<h2>5.0 Synchronization Strategies</h2>

<h3>5.1 Pull</h3>

<p>A typical pull operation proceeds as shown below.  Details
of the actual implementation may very slightly but the gist of
a pull is captured in the following steps:</p>

<ol>
<li>The client sends login and pull cards.
<li>The client sends a cookie card if it has previously received a cookie.
<li>The client sends gimme cards for every phantom that it holds.
<hr>
<li>The server checks the login password and rejects the session if
the user does not have permission to pull.
<li>If the number entries in the unclustered table on the server is
greater than 100, then the server constructs a new cluster artifact to
cover all those unclustered entries.
<li>The server sends file cards for every gimme card it received
from the client.
<li>The server sends ihave cards for every artifact in its unclustered
table that is not a phantom.
<hr>
<li>The client adds the content of file cards to its repository.
<li>The client creates a phantom for every ihave card in the server reply
that mentions an artifact that the client does not possess.
<li>The client creates a phantom for the delta source of file cards when
the delta source is an artifact that the client does not possess.
</ol>

<p>These ten steps represent a single HTTP round-trip request.
The first three steps are the processing that occurs on the client
to generate the request.  The middle four steps are processing
that occurs on the server to interpret the request and generate a
reply.  And the last three steps are the processing that the
client does to interpret the reply.</p>

<p>During a pull, the client will keep sending HTTP requests
until it holds all artifacts that exist on the server.</p>

<p>Note that the server tries
to limit the size of its reply message to something reasonable
(usually about 1MB) so that it might stop sending file cards as
described in step (6) if the reply becomes too large.</p>

<p>Step (5) is the only way in which new clusters can be created.
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
<h3>5.2 Push</h3>

<p>A typical push operation proceeds roughly as shown below.  As
with a pull, the actual implementation may vary slightly.</p>

<ol>
<li>The client sends login and push cards.
<li>The client sends file cards for any files that it holds that have
never before been pushed - files that come from local check-ins.
<li>If this is the second or later cycle in a push, then the
client sends file cards for any gimme cards that the server sent
in the previous cycle.
<li>The client sends igot cards for every file in its unclustered table
that is not a phantom.
<hr>
<li>The server checks the login and push cards and issues an error if
anything is amiss.
<li>The server accepts file cards from the client and adds those files
to its repository.
<li>The server creates phantoms for igot cards that mention files it
does not possess or for file cards that mention delta source files that
it does not possess.
<li>The server issues gimme cards for all phantoms.
<hr>
<li>The client remembers the gimme cards from the server so that it
can generate file cards in reply on the next cycle.
</ol>

<p>As with a pull, the steps of a push operation repeat until the
server knows all files that exist on the client.  Also, as with
pull, the client attempts to keep the size of the request from
growing too large by suppressing file cards once the
size of the request reaches 1MB.</p>

<h3>5.3 Sync</h3>

<p>A sync is just a pull and a push that happen at the same time.







|
|



|




|

|
|








|







405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
<h3>5.2 Push</h3>

<p>A typical push operation proceeds roughly as shown below.  As
with a pull, the actual implementation may vary slightly.</p>

<ol>
<li>The client sends login and push cards.
<li>The client sends file cards for any artifacts that it holds that have
never before been pushed - artifacts that come from local check-ins.
<li>If this is the second or later cycle in a push, then the
client sends file cards for any gimme cards that the server sent
in the previous cycle.
<li>The client sends igot cards for every artifact in its unclustered table
that is not a phantom.
<hr>
<li>The server checks the login and push cards and issues an error if
anything is amiss.
<li>The server accepts file cards from the client and adds those artifacts
to its repository.
<li>The server creates phantoms for igot cards that mention artifacts it
does not possess or for file cards that mention delta source artifacts that
it does not possess.
<li>The server issues gimme cards for all phantoms.
<hr>
<li>The client remembers the gimme cards from the server so that it
can generate file cards in reply on the next cycle.
</ol>

<p>As with a pull, the steps of a push operation repeat until the
server knows all artifacts that exist on the client.  Also, as with
pull, the client attempts to keep the size of the request from
growing too large by suppressing file cards once the
size of the request reaches 1MB.</p>

<h3>5.3 Sync</h3>

<p>A sync is just a pull and a push that happen at the same time.
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
    card per line.  
<li>Card formats are:
    <ul>
    <li> <b>login</b> <i>userid nonce signature</i>
    <li> <b>push</b> <i>servercode projectcode</i>
    <li> <b>pull</b> <i>servercode projectcode</i>
    <li> <b>clone</b>
    <li> <b>file</b> <i>uuid size</i> <b>\n</b> <i>content</i>
    <li> <b>file</b> <i>uuid delta-uuid size</i> <b>\n</b> <i>content</i>
    <li> <b>igot</b> <i>uuid</i>
    <li> <b>gimme</b> <i>uuid</i>
    <li> <b>cookie</b>  <i>cookie-text</i>
    <li> <b>error</b> <i>error-message</i>
    </ul>
<li>Phantoms are files that a repository knows exist but does not possess.
<li>Clusters are files that contain the UUIDs of other files.
<li>Clusters are created automatically on the server during a pull.
<li>Repositories keep track of all files that are not named in any
cluster and send igot messages for those files.
<li>Repositories keep track of all the phantoms they hold and send
gimme messages for those files.
</ol>







|
|
|
|



|
|

|
|

|

456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
    card per line.  
<li>Card formats are:
    <ul>
    <li> <b>login</b> <i>userid nonce signature</i>
    <li> <b>push</b> <i>servercode projectcode</i>
    <li> <b>pull</b> <i>servercode projectcode</i>
    <li> <b>clone</b>
    <li> <b>file</b> <i>artifact-id size</i> <b>\n</b> <i>content</i>
    <li> <b>file</b> <i>artifact-id delta-artifact-id size</i> <b>\n</b> <i>content</i>
    <li> <b>igot</b> <i>artifact-id</i>
    <li> <b>gimme</b> <i>artifact-id</i>
    <li> <b>cookie</b>  <i>cookie-text</i>
    <li> <b>error</b> <i>error-message</i>
    </ul>
<li>Phantoms are artifacts that a repository knows exist but does not possess.
<li>Clusters are artifacts that contain IDs of other artifacts.
<li>Clusters are created automatically on the server during a pull.
<li>Repositories keep track of all artifacts that are not named in any
cluster and send igot messages for those artifacts.
<li>Repositories keep track of all the phantoms they hold and send
gimme messages for those artifacts.
</ol>