Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Add the ability to parse and use manifests with the B-card. Add documentation for the B-card. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | experimental |
| Files: | files | file ages | folders |
| SHA1: |
ec56d8ff58c5cccebf1fb8d2a427d220 |
| User & Date: | drh 2010-10-17 17:25:12.000 |
Context
|
2010-10-18
| ||
| 22:34 | Rework manifest parsing in order to process delta-manifests correctly. check-in: aa61a65c18 user: drh tags: experimental | |
|
2010-10-17
| ||
| 17:25 | Add the ability to parse and use manifests with the B-card. Add documentation for the B-card. check-in: ec56d8ff58 user: drh tags: experimental | |
|
2010-10-16
| ||
| 16:32 | Bring over the latest bug fixes from trunk. check-in: b2175857cc user: drh tags: experimental | |
Changes
Changes to src/branch.c.
| ︙ | ︙ | |||
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
user_select();
db_begin_transaction();
rootid = name_to_rid(g.argv[4]);
if( rootid==0 ){
fossil_fatal("unable to locate check-in off of which to branch");
}
/* Create a manifest for the new branch */
blob_zero(&branch);
zComment = mprintf("Create new branch named \"%h\"", zBranch);
blob_appendf(&branch, "C %F\n", zComment);
zDate = date_in_standard_format(zDateOvrd ? zDateOvrd : "now");
zDate[10] = 'T';
blob_appendf(&branch, "D %s\n", zDate);
/* Copy all of the content from the parent into the branch */
| > > > > > > > > < < < < < | | | | < | < < | > > | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
user_select();
db_begin_transaction();
rootid = name_to_rid(g.argv[4]);
if( rootid==0 ){
fossil_fatal("unable to locate check-in off of which to branch");
}
pParent = manifest_get(rootid, CFTYPE_MANIFEST);
if( pParent==0 ){
fossil_fatal("%s is not a valid check-in", g.argv[4]);
}
/* Create a manifest for the new branch */
blob_zero(&branch);
if( pParent->zBaseline ){
blob_appendf(&branch, "B %s\n", pParent->zBaseline);
}
zComment = mprintf("Create new branch named \"%h\"", zBranch);
blob_appendf(&branch, "C %F\n", zComment);
zDate = date_in_standard_format(zDateOvrd ? zDateOvrd : "now");
zDate[10] = 'T';
blob_appendf(&branch, "D %s\n", zDate);
/* Copy all of the content from the parent into the branch */
for(i=0; i<pParent->nFile; ++i){
blob_appendf(&branch, "F %F", pParent->aFile[i].zName);
if( pParent->aFile[i].zUuid[0] ){
blob_appendf(&branch, " %s", pParent->aFile[i].zUuid);
if( pParent->aFile[i].zPerm[0] ){
blob_appendf(&branch, " %s", pParent->aFile[i].zPerm);
}
}
blob_append(&branch, "\n", 1);
}
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rootid);
blob_appendf(&branch, "P %s\n", zUuid);
blob_appendf(&branch, "R %s\n", pParent->zRepoCksum);
manifest_destroy(pParent);
/* Add the symbolic branch name and the "branch" tag to identify
|
| ︙ | ︙ |
Changes to src/browse.c.
| ︙ | ︙ | |||
105 106 107 108 109 110 111 |
int nCol, nRow;
int cnt, i;
char *zPrefix;
Stmt q;
const char *zCI = P("ci");
int rid = 0;
char *zUuid = 0;
| < < < | < < > | 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 |
int nCol, nRow;
int cnt, i;
char *zPrefix;
Stmt q;
const char *zCI = P("ci");
int rid = 0;
char *zUuid = 0;
Blob dirname;
Manifest *pM = 0;
const char *zSubdirLink;
login_check_credentials();
if( !g.okHistory ){ login_needed(); return; }
style_header("File List");
sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
pathelementFunc, 0, 0);
/* If the name= parameter is an empty string, make it a NULL pointer */
if( zD && strlen(zD)==0 ){ zD = 0; }
/* If a specific check-in is requested, fetch and parse it. If the
** specific check-in does not exist, clear zCI. zCI==0 will cause all
** files from all check-ins to be displayed.
*/
if( zCI ){
pM = manifest_get_by_name(zCI, &rid);
if( pM ){
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
}
}
/* Compute the title of the page */
blob_zero(&dirname);
|
| ︙ | ︙ |
Changes to src/diffcmd.c.
| ︙ | ︙ | |||
358 359 360 361 362 363 364 |
int diffFlags
){
Manifest *pFrom, *pTo;
ManifestFile *pFromFile, *pToFile;
int ignoreEolWs = (diffFlags & DIFF_NOEOLWS)!=0 ? 1 : 0;
int asNewFlag = (diffFlags & DIFF_NEWFILE)!=0 ? 1 : 0;
| | | | 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
int diffFlags
){
Manifest *pFrom, *pTo;
ManifestFile *pFromFile, *pToFile;
int ignoreEolWs = (diffFlags & DIFF_NOEOLWS)!=0 ? 1 : 0;
int asNewFlag = (diffFlags & DIFF_NEWFILE)!=0 ? 1 : 0;
pFrom = manifest_get_by_name(zFrom, 0);
manifest_file_rewind(pFrom);
pFromFile = manifest_file_next(pFrom,0);
pTo = manifest_get_by_name(zTo, 0);
manifest_file_rewind(pTo);
pToFile = manifest_file_next(pTo,0);
while( pFromFile || pToFile ){
int cmp;
if( pFromFile==0 ){
cmp = +1;
|
| ︙ | ︙ |
Changes to src/manifest.c.
| ︙ | ︙ | |||
51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
/*
** A parsed manifest or cluster.
*/
struct Manifest {
Blob content; /* The original content blob */
int type; /* Type of artifact. One of CFTYPE_xxxxx */
char *zComment; /* Decoded comment. The C card. */
double rDate; /* Date and time from D card. 0.0 if no D card. */
char *zUser; /* Name of the user from the U card. */
char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */
char *zWiki; /* Text of the wiki page. W card. */
char *zWikiTitle; /* Name of the wiki page. L card. */
double rEventDate; /* Date of an event. E card. */
| > > | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
/*
** A parsed manifest or cluster.
*/
struct Manifest {
Blob content; /* The original content blob */
int type; /* Type of artifact. One of CFTYPE_xxxxx */
char *zBaseline; /* Baseline manifest. The B card. */
Manifest *pBaseline; /* The actual baseline manifest */
char *zComment; /* Decoded comment. The C card. */
double rDate; /* Date and time from D card. 0.0 if no D card. */
char *zUser; /* Name of the user from the U card. */
char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */
char *zWiki; /* Text of the wiki page. W card. */
char *zWikiTitle; /* Name of the wiki page. L card. */
double rEventDate; /* Date of an event. E card. */
|
| ︙ | ︙ | |||
112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
static void manifest_clear(Manifest *p){
blob_reset(&p->content);
free(p->aFile);
free(p->azParent);
free(p->azCChild);
free(p->aTag);
free(p->aField);
memset(p, 0, sizeof(*p));
}
/*
** Add an element to the manifest cache using LRU replacement.
*/
void manifest_cache_insert(int rid, Manifest *p){
| > | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
static void manifest_clear(Manifest *p){
blob_reset(&p->content);
free(p->aFile);
free(p->azParent);
free(p->azCChild);
free(p->aTag);
free(p->aField);
if( p->pBaseline ) manifest_clear(p->pBaseline);
memset(p, 0, sizeof(*p));
}
/*
** Add an element to the manifest cache using LRU replacement.
*/
void manifest_cache_insert(int rid, Manifest *p){
|
| ︙ | ︙ | |||
283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
goto manifest_syntax_error;
}
p->zAttachName = (char*)file_tail(zName);
p->zAttachSrc = zSrc;
p->zAttachTarget = zTarget;
break;
}
/*
** C <comment>
**
** Comment text is fossil-encoded. There may be no more than
** one C line. C lines are required for manifests and are
** disallowed on all other control files.
| > > > > > > > > > > > > > > > > > > | 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 |
goto manifest_syntax_error;
}
p->zAttachName = (char*)file_tail(zName);
p->zAttachSrc = zSrc;
p->zAttachTarget = zTarget;
break;
}
/*
** B <uuid>
**
** A B-line gives the UUID for the baselinen of a delta-manifest.
*/
case 'B': {
char *zBaseline;
if( p->zBaseline ) goto manifest_syntax_error;
md5sum_step_text(blob_buffer(&line), blob_size(&line));
if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
zBaseline = blob_terminate(&a1);
if( blob_size(&a1)!=UUID_SIZE ) goto manifest_syntax_error;
if( !validate16(zBaseline, UUID_SIZE) ) goto manifest_syntax_error;
p->zBaseline = zBaseline;
break;
}
/*
** C <comment>
**
** Comment text is fossil-encoded. There may be no more than
** one C line. C lines are required for manifests and are
** disallowed on all other control files.
|
| ︙ | ︙ | |||
345 346 347 348 349 350 351 |
if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error;
p->zEventId = blob_terminate(&a2);
if( !validate16(p->zEventId, UUID_SIZE) ) goto manifest_syntax_error;
break;
}
/*
| | < < | | > | | > > > | 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 |
if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error;
p->zEventId = blob_terminate(&a2);
if( !validate16(p->zEventId, UUID_SIZE) ) goto manifest_syntax_error;
break;
}
/*
** F <filename> ?<uuid>? ?<permissions>? ?<old-name>?
**
** Identifies a file in a manifest. Multiple F lines are
** allowed in a manifest. F lines are not allowed in any
** other control file. The filename and old-name are fossil-encoded.
*/
case 'F': {
char *zName, *zUuid, *zPerm, *zPriorName;
md5sum_step_text(blob_buffer(&line), blob_size(&line));
if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
zName = blob_terminate(&a1);
blob_token(&line, &a2);
zUuid = blob_terminate(&a2);
if( p->zBaseline==0 || zUuid[0]!=0 ){
if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error;
if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
}
blob_token(&line, &a3);
zPerm = blob_terminate(&a3);
defossilize(zName);
if( !file_is_simple_pathname(zName) ){
goto manifest_syntax_error;
}
blob_token(&line, &a4);
zPriorName = blob_terminate(&a4);
if( zPriorName[0] ){
|
| ︙ | ︙ | |||
675 676 677 678 679 680 681 |
default: {
goto manifest_syntax_error;
}
}
}
if( !seenHeader ) goto manifest_syntax_error;
| | | 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 |
default: {
goto manifest_syntax_error;
}
}
}
if( !seenHeader ) goto manifest_syntax_error;
if( p->nFile>0 || p->zRepoCksum!=0 || p->zBaseline ){
if( p->nCChild>0 ) goto manifest_syntax_error;
if( p->rDate<=0.0 ) goto manifest_syntax_error;
if( p->nField>0 ) goto manifest_syntax_error;
if( p->zTicketUuid ) goto manifest_syntax_error;
if( p->zWiki ) goto manifest_syntax_error;
if( p->zWikiTitle ) goto manifest_syntax_error;
if( p->zEventId ) goto manifest_syntax_error;
|
| ︙ | ︙ | |||
778 779 780 781 782 783 784 | ** parse of pContent. Return a pointer ot the new object. ** ** If pContent is not a well-formed control artifact, return 0. ** ** pContent is reset, regardless of whether or not a Manifest object ** is returned. */ | | | 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 |
** parse of pContent. Return a pointer ot the new object.
**
** If pContent is not a well-formed control artifact, return 0.
**
** pContent is reset, regardless of whether or not a Manifest object
** is returned.
*/
static Manifest *manifest_new(Blob *pContent){
Manifest *p = fossil_malloc( sizeof(*p) );
if( manifest_parse(p, pContent)==0 ){
fossil_free(p);
p = 0;
}
return p;
}
|
| ︙ | ︙ | |||
802 803 804 805 806 807 808 809 810 811 812 813 814 815 |
p = manifest_new(&content);
if( p && cfType!=CFTYPE_ANY && cfType!=p->type ){
manifest_destroy(p);
p = 0;
}
return p;
}
/*
** Destroy a Manifest object previously obtained from manifest_new().
*/
void manifest_destroy(Manifest *p){
if( p ){
manifest_clear(p);
| > > > > > > > > > > > > > > > > > > > | 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 |
p = manifest_new(&content);
if( p && cfType!=CFTYPE_ANY && cfType!=p->type ){
manifest_destroy(p);
p = 0;
}
return p;
}
/*
** Given a checkin name, load and parse the manifest for that checkin.
** Throw a fatal error if anything goes wrong.
*/
Manifest *manifest_get_by_name(const char *zName, int *pRid){
int rid;
Manifest *p;
rid = name_to_rid(zName);
if( !is_a_version(rid) ){
fossil_fatal("no such checkin: %s", zName);
}
p = manifest_get(rid, CFTYPE_MANIFEST);
if( p==0 ){
fossil_fatal("cannot parse manifest for checkin: %s", zName);
}
return p;
}
/*
** Destroy a Manifest object previously obtained from manifest_new().
*/
void manifest_destroy(Manifest *p){
if( p ){
manifest_clear(p);
|
| ︙ | ︙ | |||
843 844 845 846 847 848 849 |
}
}
/*
** Rewind a manifest-file iterator back to the beginning of the manifest.
*/
void manifest_file_rewind(Manifest *p){
| | > > > > > > > > > > | > | | < < < | < | | | > > > > > | > > > > > > > > > > > > > > > | > > > > > > > | > > | > > > | > > > | 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 |
}
}
/*
** Rewind a manifest-file iterator back to the beginning of the manifest.
*/
void manifest_file_rewind(Manifest *p){
p->iFile = 0;
if( p->zBaseline!=0 && p->pBaseline==0 ){
p->pBaseline = manifest_get_by_name(p->zBaseline, 0);
if( p->pBaseline==0 ){
fossil_fatal("cannot access baseline manifest %S", p->zBaseline);
}
}
if( p->pBaseline ){
p->pBaseline->iFile = 0;
}
}
/*
** Advance to the next manifest-file.
**
** Return NULL for end-of-records or if there is an error. If an error
** occurs and pErr!=0 then store 1 in *pErr.
*/
ManifestFile *manifest_file_next(
Manifest *p,
int *pErr
){
ManifestFile *pOut = 0;
if( pErr ) *pErr = 0;
if( p->pBaseline==0 ){
/* Manifest p is a baseline-manifest. Just scan down the list
** of files. */
if( p->iFile<p->nFile ) pOut = &p->aFile[p->iFile++];
}else{
/* Manifest p is a delta-manifest. Scan the baseline but amend the
** file list in the baseline with changes described by p.
*/
Manifest *pB = p->pBaseline;
int cmp;
while(1){
if( pB->iFile>=pB->nFile ){
/* We have used all entries out of the baseline. Return the next
** entry from the delta. */
if( p->iFile<p->nFile ) pOut = &p->aFile[p->iFile++];
break;
}else if( p->iFile>=p->nFile ){
/* We have used all entries from the delta. Return the next
** entry from the baseline. */
if( pB->iFile<pB->nFile ) pOut = &pB->aFile[pB->iFile++];
break;
}else if( (cmp = strcmp(pB->aFile[pB->iFile].zName,
p->aFile[p->iFile].zName)) < 0 ){
/* The next baseline entry comes before the next delta entry.
** So return the baseline entry. */
pOut = &pB->aFile[pB->iFile++];
break;
}else if( cmp>0 ){
/* The next delta entry comes before the next baseline
** entry so return the delta entry */
pOut = &p->aFile[p->iFile++];
break;
}else if( p->aFile[p->iFile].zUuid[0] ){
/* The next delta entry is a replacement for the next baseline
** entry. Skip the baseline entry and return the delta entry */
pB->iFile++;
pOut = &p->aFile[p->iFile++];
break;
}else{
/* The next delta entry is a delete of the next baseline
** entry. Skip them both. Repeat the loop to find the next
** non-delete entry. */
pB->iFile++;
p->iFile++;
continue;
}
}
}
return pOut;
}
/*
** Translate a filename into a filename-id (fnid). Create a new fnid
** if no previously exists.
*/
static int filename_to_fnid(const char *zFilename){
|
| ︙ | ︙ | |||
1450 1451 1452 1453 1454 1455 1456 |
if( m.type==CFTYPE_MANIFEST ){
manifest_cache_insert(rid, &m);
}else{
manifest_clear(&m);
}
return 1;
}
| < < < < < < < < < < < < < < < < < < < | 1534 1535 1536 1537 1538 1539 1540 |
if( m.type==CFTYPE_MANIFEST ){
manifest_cache_insert(rid, &m);
}else{
manifest_clear(&m);
}
return 1;
}
|
Changes to src/zip.c.
| ︙ | ︙ | |||
311 312 313 314 315 316 317 |
** added to as part of the zip file. It may be 0 or an empty string,
** in which case it is ignored. The intention is to create a zip which
** politely expands into a subdir instead of filling your current dir
** with source files. For example, pass a UUID or "ProjectName".
**
*/
void zip_of_baseline(int rid, Blob *pZip, const char *zDir){
| | < < | | | | | | 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 |
** added to as part of the zip file. It may be 0 or an empty string,
** in which case it is ignored. The intention is to create a zip which
** politely expands into a subdir instead of filling your current dir
** with source files. For example, pass a UUID or "ProjectName".
**
*/
void zip_of_baseline(int rid, Blob *pZip, const char *zDir){
Blob mfile, hash, file;
Manifest *pManifest;
ManifestFile *pFile;
Blob filename;
int nPrefix;
content_get(rid, &mfile);
if( blob_size(&mfile)==0 ){
blob_zero(pZip);
return;
}
blob_zero(&hash);
blob_zero(&filename);
zip_open();
if( zDir && zDir[0] ){
blob_appendf(&filename, "%s/", zDir);
}
nPrefix = blob_size(&filename);
pManifest = manifest_get(rid, CFTYPE_MANIFEST);
if( pManifest ){
char *zName;
zip_set_timedate(pManifest->rDate);
blob_append(&filename, "manifest", -1);
zName = blob_str(&filename);
zip_add_folders(zName);
zip_add_file(zName, &mfile);
sha1sum_blob(&mfile, &hash);
blob_reset(&mfile);
blob_append(&hash, "\n", 1);
blob_resize(&filename, nPrefix);
blob_append(&filename, "manifest.uuid", -1);
zName = blob_str(&filename);
zip_add_file(zName, &hash);
blob_reset(&hash);
manifest_file_rewind(pManifest);
while( (pFile = manifest_file_next(pManifest,0))!=0 ){
int fid = uuid_to_rid(pFile->zUuid, 0);
if( fid ){
content_get(fid, &file);
blob_resize(&filename, nPrefix);
blob_append(&filename, pFile->zName, -1);
zName = blob_str(&filename);
zip_add_folders(zName);
zip_add_file(zName, &file);
blob_reset(&file);
}
}
}else{
blob_reset(&mfile);
}
manifest_destroy(pManifest);
blob_reset(&filename);
zip_close(pZip);
}
/*
|
| ︙ | ︙ |
Changes to www/fileformat.wiki.
| ︙ | ︙ | |||
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | No card may be duplicated. The entire manifest may be PGP clear-signed, but otherwise it may contain no additional text or data beyond what is described here. Allowed cards in the manifest are as follows: <blockquote> <b>C</b> <i>checkin-comment</i><br> <b>D</b> <i>time-and-date-stamp</i><br> <b>F</b> <i>filename</i> <i>SHA1-hash</i> <i>permissions</i> <i>old-name</i><br> <b>P</b> <i>SHA1-hash</i>+<br> <b>R</b> <i>repository-checksum</i><br> <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name <b>*</b> ?value?</i><br> <b>U</b> <i>user-login</i><br> <b>Z</b> <i>manifest-checksum</i> </blockquote> A manifest must have exactly one C-card. The sole argument to the C-card is a check-in comment that describes the check-in that the manifest defines. The check-in comment is text. The following escape sequences are applied to the text: A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A newline (ASCII 0x0a) is "\n" (ASCII 0x6C, x6E). A backslash | > > > > > > > > > | 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 | No card may be duplicated. The entire manifest may be PGP clear-signed, but otherwise it may contain no additional text or data beyond what is described here. Allowed cards in the manifest are as follows: <blockquote> <b>B</b> <i>baseline-manifest</i><br> <b>C</b> <i>checkin-comment</i><br> <b>D</b> <i>time-and-date-stamp</i><br> <b>F</b> <i>filename</i> <i>SHA1-hash</i> <i>permissions</i> <i>old-name</i><br> <b>P</b> <i>SHA1-hash</i>+<br> <b>R</b> <i>repository-checksum</i><br> <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name <b>*</b> ?value?</i><br> <b>U</b> <i>user-login</i><br> <b>Z</b> <i>manifest-checksum</i> </blockquote> A manifest may optionally have a single B-card. The B-card specifies another manifest that serves as the "baseline" for this manifest. A manifest that has a B-card is called a delta-manifest and a manifest that omits the B-card is a baseline-manifest. The other manifest identified by the argument of the B-card must be a baseline-manifest. A baseline-manifest records the complete contents of a checkin. A delta-manifest records all changes from its baseline. A manifest must have exactly one C-card. The sole argument to the C-card is a check-in comment that describes the check-in that the manifest defines. The check-in comment is text. The following escape sequences are applied to the text: A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A newline (ASCII 0x0a) is "\n" (ASCII 0x6C, x6E). A backslash |
| ︙ | ︙ | |||
123 124 125 126 127 128 129 | date and time should be in coordinated universal time (UTC). The format is: <blockquote> <i>YYYY</i><b>-</b><i>MM</i><b>-</b><i>DD</i><b>T</b><i>HH</i><b>:</b><i>MM</i><b>:</b><i>SS</i> </blockquote> | | < | > > > | | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | date and time should be in coordinated universal time (UTC). The format is: <blockquote> <i>YYYY</i><b>-</b><i>MM</i><b>-</b><i>DD</i><b>T</b><i>HH</i><b>:</b><i>MM</i><b>:</b><i>SS</i> </blockquote> A manifest has zero or more F-cards. Each F-card identifies a file that is part of the check-in. There are one, two, three, or four arguments. The first argument is the pathname of the file in the check-in relative to the root of the project file hierarchy. No ".." or "." directories are allowed within the filename. Space characters are escaped as in C-card comment text. Backslash characters and newlines are not allowed within filenames. The directory separator character is a forward slash (ASCII 0x2F). The second argument to the F-card is the full 40-character lower-case hexadecimal SHA1 hash of the content artifact. The second argument is required for baselin manifests but is optional for delta manifests. When the second argument to the F-card is omitted, it means that the file has been deleted relative to the baseline. The optional 3rd argument defines any special access permissions associated with the file. The only special code currently defined is "x" which means that the file is executable. All files are always readable and writable. This can be expressed by "w" permission if desired but is optional. The optional 4th argument is the name of the same file as it existed in the parent check-in. If the name of the file is unchanged from its parent, then the 4th argument is omitted. |
| ︙ | ︙ |