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: |
e8c4f69c50ecbe4388aa28e489050e7c |
| 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
Changes to src/descendants.c.
| ︙ | ︙ | |||
128 129 130 131 132 133 134 | bag_clear(&seen); pqueue_clear(&queue); } /* ** COMMAND: descendants ** | | | | | 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 | } } /* ** COMMAND: info ** | | | | | 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 |
@ </ul>
}
}
/*
** WEBPAGE: vinfo
| | | 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 | @ </pre></blockquote> blob_reset(&diff); style_footer(); } /* ** WEBPAGE: artifact | | | | 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 | @ </pre></blockquote> blob_reset(&content); style_footer(); } /* ** WEBPAGE: tinfo | | | 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 | manifest_clear(&m); style_footer(); } /* ** WEBPAGE: info | | | | | 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 |
** 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-");
}
/*
| | | | | 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 |
tag_propagate(rid, tagid, tagtype, zValue, mtime);
}
}
/*
** COMMAND: test-tag
| | | | 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 | zValue = g.argc==5 ? g.argv[4] : 0; db_begin_transaction(); tag_insert(zTag, tagtype, zValue, -1, 0.0, rid); db_end_transaction(0); } /* | | | 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 |
if( name_to_uuid(&uuid, 9) ){
return;
}
rid = name_to_rid(blob_str(&uuid));
blob_zero(&ctrl);
if( validate16(zTagname, strlen(zTagname)) ){
| > | > | > | 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 | /* ** COMMAND: tag ** Usage: %fossil tag SUBCOMMAND ... ** ** Run various subcommands to control tags and properties ** | | | | | | | | | | | | | | | | | | 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 |
}
blob_set(&tagname, prefix);
if( strncmp(g.argv[2],"add",n)==0 ){
char *zValue;
if( g.argc!=5 && g.argc!=6 ){
| | | | | 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 |
if( raw || strncmp(zName, prefix, preflen)==0 ){
printf("%s\n", zName+preflen);
}
}
}
db_finalize(&q);
}else{
| | | 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 | ; return zBaseSql; } /* ** COMMAND: timeline ** | | | | 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 |
}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{
| | | 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 |
/*
** WEBPAGE: wiki
** URL: /wiki?name=PAGENAME
*/
void wiki_page(void){
char *zTag;
| | | 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 |
@ <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
| | | 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:
@ <a>
@ <address>
|
| ︙ | ︙ | |||
705 706 707 708 709 710 711 | ** %fossil wiki list ** ** Lists all wiki entries, one per line, ordered ** case-insentively by name. ** ** TODOs: ** | | | | | | 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 | 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, | | | | | | | 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 | 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 | | | 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 | <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 | | | | | | | | | | | | | | | 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 |
<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>
| | | | 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 | For example, the <i><baseurl></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><baseurl></i> is usually <b>http://localhost:8080/</b>. | | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | For example, the <i><baseurl></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><baseurl></i> is usually <b>http://localhost:8080/</b>. The <i><version></i> is any unique prefix of the baseline ID for the baseline containing the documentation you want to access. Or <i><version></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 | </p> <p> Allowed cards in the cluster are as follows: </p> <blockquote> | | | | 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 | <p> Allowed cards in a control artifact are as follows: </p> <blockquote> <b>D</b> <i>time-and-date-stamp</i><br /> | | | | 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 | 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 /> | | | 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 | <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 /> | | | | 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 |
</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>
| | | > | | | | 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 | <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 | | > | 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 | <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> | | > | | | | | | | | | | | | | 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 | 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 | | | | | | | | | 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 | <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> | | | | | | | | | | | | | | | | | | | | | | | 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 | <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. | | | | | | | | | 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 |
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>
| | | | | | | | | | | 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>
|