Fossil SCM
Further work toward two-way configuration sync. Need to check in these changes before they are complete in order to deal with another issue.
Commit
71fc181feef52f367aa1b8a457e42698600cefe7
Parent
b44d4a89d0f0a3e…
2 files changed
+38
+46
+38
| --- src/blob.c | ||
| +++ src/blob.c | ||
| @@ -489,10 +489,48 @@ | ||
| 489 | 489 | int n = pFrom->nUsed; |
| 490 | 490 | int i = pFrom->iCursor; |
| 491 | 491 | while( i<n && fossil_isspace(aData[i]) ){ i++; } |
| 492 | 492 | pFrom->iCursor = i; |
| 493 | 493 | while( i<n && !fossil_isspace(aData[i]) ){ i++; } |
| 494 | + blob_extract(pFrom, i-pFrom->iCursor, pTo); | |
| 495 | + while( i<n && fossil_isspace(aData[i]) ){ i++; } | |
| 496 | + pFrom->iCursor = i; | |
| 497 | + return pTo->nUsed; | |
| 498 | +} | |
| 499 | + | |
| 500 | +/* | |
| 501 | +** Extract a single SQL token from pFrom and use it to initialize pTo. | |
| 502 | +** Return the number of bytes in the token. If no token is found, | |
| 503 | +** return 0. | |
| 504 | +** | |
| 505 | +** An SQL token consists of one or more non-space characters. If the | |
| 506 | +** first character is ' then the token is terminated by a matching ' | |
| 507 | +** (ignoring double '') or by the end of the string | |
| 508 | +** | |
| 509 | +** The cursor of pFrom is left pointing at the first character past | |
| 510 | +** the end of the token. | |
| 511 | +** | |
| 512 | +** pTo will be an ephermeral blob. If pFrom changes, it might alter | |
| 513 | +** pTo as well. | |
| 514 | +*/ | |
| 515 | +int blob_sqltoken(Blob *pFrom, Blob *pTo){ | |
| 516 | + char *aData = pFrom->aData; | |
| 517 | + int n = pFrom->nUsed; | |
| 518 | + int i = pFrom->iCursor; | |
| 519 | + while( i<n && fossil_isspace(aData[i]) ){ i++; } | |
| 520 | + pFrom->iCursor = i; | |
| 521 | + if( aData[i]=='\'' ){ | |
| 522 | + i++; | |
| 523 | + while( i<n ){ | |
| 524 | + if( aData[i]=='\'' ){ | |
| 525 | + if( aData[++i]!='\'' ) break; | |
| 526 | + } | |
| 527 | + i++; | |
| 528 | + } | |
| 529 | + }else{ | |
| 530 | + while( i<n && !fossil_isspace(aData[i]) ){ i++; } | |
| 531 | + } | |
| 494 | 532 | blob_extract(pFrom, i-pFrom->iCursor, pTo); |
| 495 | 533 | while( i<n && fossil_isspace(aData[i]) ){ i++; } |
| 496 | 534 | pFrom->iCursor = i; |
| 497 | 535 | return pTo->nUsed; |
| 498 | 536 | } |
| 499 | 537 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -489,10 +489,48 @@ | |
| 489 | int n = pFrom->nUsed; |
| 490 | int i = pFrom->iCursor; |
| 491 | while( i<n && fossil_isspace(aData[i]) ){ i++; } |
| 492 | pFrom->iCursor = i; |
| 493 | while( i<n && !fossil_isspace(aData[i]) ){ i++; } |
| 494 | blob_extract(pFrom, i-pFrom->iCursor, pTo); |
| 495 | while( i<n && fossil_isspace(aData[i]) ){ i++; } |
| 496 | pFrom->iCursor = i; |
| 497 | return pTo->nUsed; |
| 498 | } |
| 499 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -489,10 +489,48 @@ | |
| 489 | int n = pFrom->nUsed; |
| 490 | int i = pFrom->iCursor; |
| 491 | while( i<n && fossil_isspace(aData[i]) ){ i++; } |
| 492 | pFrom->iCursor = i; |
| 493 | while( i<n && !fossil_isspace(aData[i]) ){ i++; } |
| 494 | blob_extract(pFrom, i-pFrom->iCursor, pTo); |
| 495 | while( i<n && fossil_isspace(aData[i]) ){ i++; } |
| 496 | pFrom->iCursor = i; |
| 497 | return pTo->nUsed; |
| 498 | } |
| 499 | |
| 500 | /* |
| 501 | ** Extract a single SQL token from pFrom and use it to initialize pTo. |
| 502 | ** Return the number of bytes in the token. If no token is found, |
| 503 | ** return 0. |
| 504 | ** |
| 505 | ** An SQL token consists of one or more non-space characters. If the |
| 506 | ** first character is ' then the token is terminated by a matching ' |
| 507 | ** (ignoring double '') or by the end of the string |
| 508 | ** |
| 509 | ** The cursor of pFrom is left pointing at the first character past |
| 510 | ** the end of the token. |
| 511 | ** |
| 512 | ** pTo will be an ephermeral blob. If pFrom changes, it might alter |
| 513 | ** pTo as well. |
| 514 | */ |
| 515 | int blob_sqltoken(Blob *pFrom, Blob *pTo){ |
| 516 | char *aData = pFrom->aData; |
| 517 | int n = pFrom->nUsed; |
| 518 | int i = pFrom->iCursor; |
| 519 | while( i<n && fossil_isspace(aData[i]) ){ i++; } |
| 520 | pFrom->iCursor = i; |
| 521 | if( aData[i]=='\'' ){ |
| 522 | i++; |
| 523 | while( i<n ){ |
| 524 | if( aData[i]=='\'' ){ |
| 525 | if( aData[++i]!='\'' ) break; |
| 526 | } |
| 527 | i++; |
| 528 | } |
| 529 | }else{ |
| 530 | while( i<n && !fossil_isspace(aData[i]) ){ i++; } |
| 531 | } |
| 532 | blob_extract(pFrom, i-pFrom->iCursor, pTo); |
| 533 | while( i<n && fossil_isspace(aData[i]) ){ i++; } |
| 534 | pFrom->iCursor = i; |
| 535 | return pTo->nUsed; |
| 536 | } |
| 537 |
+46
| --- src/configure.c | ||
| +++ src/configure.c | ||
| @@ -14,10 +14,11 @@ | ||
| 14 | 14 | ** http://www.hwaci.com/drh/ |
| 15 | 15 | ** |
| 16 | 16 | ******************************************************************************* |
| 17 | 17 | ** |
| 18 | 18 | ** This file contains code used to manage repository configurations. |
| 19 | +** | |
| 19 | 20 | ** By "responsitory configure" we mean the local state of a repository |
| 20 | 21 | ** distinct from the versioned files. |
| 21 | 22 | */ |
| 22 | 23 | #include "config.h" |
| 23 | 24 | #include "configure.h" |
| @@ -118,10 +119,15 @@ | ||
| 118 | 119 | } |
| 119 | 120 | |
| 120 | 121 | /* |
| 121 | 122 | ** Return the mask for the named configuration parameter if it can be |
| 122 | 123 | ** safely exported. Return 0 if the parameter is not safe to export. |
| 124 | +** | |
| 125 | +** "Safe" in the previous paragraph means the permission is created to | |
| 126 | +** export the property. In other words, the requesting side has presented | |
| 127 | +** login credentials and has sufficient capabilities to access the requested | |
| 128 | +** information. | |
| 123 | 129 | */ |
| 124 | 130 | int configure_is_exportable(const char *zName){ |
| 125 | 131 | int i; |
| 126 | 132 | for(i=0; i<count(aConfig); i++){ |
| 127 | 133 | if( fossil_strcmp(zName, aConfig[i].zName)==0 ){ |
| @@ -297,10 +303,50 @@ | ||
| 297 | 303 | ** Process a single "config" card received from the other side of a |
| 298 | 304 | ** sync session. |
| 299 | 305 | ** |
| 300 | 306 | ** Mask consists of one or more CONFIGSET_* values ORed together, to |
| 301 | 307 | ** designate what types of configuration we are allowed to receive. |
| 308 | +** | |
| 309 | +** NEW FORMAT: | |
| 310 | +** | |
| 311 | +** zName is one of "/config", "/user", "/shun", "/reportfmt", or "/concealed". | |
| 312 | +** zName indicates the table that holds the configuration information being | |
| 313 | +** transferred. pContent is a string that consist of alternating Fossil | |
| 314 | +** and SQL tokens. The First token is a timestamp in seconds since 1970. | |
| 315 | +** The second token is a primary key for the table identified by zName. If | |
| 316 | +** The entry with the corresponding primary key exists and has a more recent | |
| 317 | +** mtime, then nothing happens. If the entry does not exist or if it has | |
| 318 | +** an older mtime, then the content described by subsequent token pairs is | |
| 319 | +** inserted. The first element of each token pair is a column name and | |
| 320 | +** the second is its value. | |
| 321 | +** | |
| 322 | +** In overview, we have: | |
| 323 | +** | |
| 324 | +** NAME CONTENT | |
| 325 | +** ------- ----------------------------------------------------------- | |
| 326 | +** /config $MTIME $NAME value $VALUE | |
| 327 | +** /user $MTIME $LOGIN pw $VALUE cap $VALUE info $VALUE photo $VALUE | |
| 328 | +** /shun $MTIME $UUID scom $VALUE | |
| 329 | +** /reportfmt $MTIME $TITLE owner $VALUE cols $VALUE sqlcode $VALUE | |
| 330 | +** /concealed $MTIME $HASH content $VALUE | |
| 331 | +** | |
| 332 | +** OLD FORMAT: | |
| 333 | +** | |
| 334 | +** The old format is retained for backwards compatiblity, but is deprecated. | |
| 335 | +** The cutover from old format to new was on 2011-04-25. After sufficient | |
| 336 | +** time has passed, support for the old format will be removed. | |
| 337 | +** | |
| 338 | +** zName is either the NAME of an element of the CONFIG table, or else | |
| 339 | +** one of the special names "@shun", "@reportfmt", "@user", or "@concealed". | |
| 340 | +** If zName is a CONFIG table name, then CONTENT replaces (overwrites) the | |
| 341 | +** element in the CONFIG table. For one of the @-labels, CONTENT is raw | |
| 342 | +** SQL that is evaluated. Note that the raw SQL in CONTENT might not | |
| 343 | +** insert directly into the target table but might instead use a proxy | |
| 344 | +** table like _fer_reportfmt or _xfer_user. Such tables must be created | |
| 345 | +** ahead of time using configure_prepare_to_receive(). Then after multiple | |
| 346 | +** calls to this routine, configure_finalize_receive() to transfer the | |
| 347 | +** information received into the true target table. | |
| 302 | 348 | */ |
| 303 | 349 | void configure_receive(const char *zName, Blob *pContent, int mask){ |
| 304 | 350 | if( (configure_is_exportable(zName) & mask)==0 ) return; |
| 305 | 351 | if( strcmp(zName, "logo-image")==0 ){ |
| 306 | 352 | Stmt ins; |
| 307 | 353 |
| --- src/configure.c | |
| +++ src/configure.c | |
| @@ -14,10 +14,11 @@ | |
| 14 | ** http://www.hwaci.com/drh/ |
| 15 | ** |
| 16 | ******************************************************************************* |
| 17 | ** |
| 18 | ** This file contains code used to manage repository configurations. |
| 19 | ** By "responsitory configure" we mean the local state of a repository |
| 20 | ** distinct from the versioned files. |
| 21 | */ |
| 22 | #include "config.h" |
| 23 | #include "configure.h" |
| @@ -118,10 +119,15 @@ | |
| 118 | } |
| 119 | |
| 120 | /* |
| 121 | ** Return the mask for the named configuration parameter if it can be |
| 122 | ** safely exported. Return 0 if the parameter is not safe to export. |
| 123 | */ |
| 124 | int configure_is_exportable(const char *zName){ |
| 125 | int i; |
| 126 | for(i=0; i<count(aConfig); i++){ |
| 127 | if( fossil_strcmp(zName, aConfig[i].zName)==0 ){ |
| @@ -297,10 +303,50 @@ | |
| 297 | ** Process a single "config" card received from the other side of a |
| 298 | ** sync session. |
| 299 | ** |
| 300 | ** Mask consists of one or more CONFIGSET_* values ORed together, to |
| 301 | ** designate what types of configuration we are allowed to receive. |
| 302 | */ |
| 303 | void configure_receive(const char *zName, Blob *pContent, int mask){ |
| 304 | if( (configure_is_exportable(zName) & mask)==0 ) return; |
| 305 | if( strcmp(zName, "logo-image")==0 ){ |
| 306 | Stmt ins; |
| 307 |
| --- src/configure.c | |
| +++ src/configure.c | |
| @@ -14,10 +14,11 @@ | |
| 14 | ** http://www.hwaci.com/drh/ |
| 15 | ** |
| 16 | ******************************************************************************* |
| 17 | ** |
| 18 | ** This file contains code used to manage repository configurations. |
| 19 | ** |
| 20 | ** By "responsitory configure" we mean the local state of a repository |
| 21 | ** distinct from the versioned files. |
| 22 | */ |
| 23 | #include "config.h" |
| 24 | #include "configure.h" |
| @@ -118,10 +119,15 @@ | |
| 119 | } |
| 120 | |
| 121 | /* |
| 122 | ** Return the mask for the named configuration parameter if it can be |
| 123 | ** safely exported. Return 0 if the parameter is not safe to export. |
| 124 | ** |
| 125 | ** "Safe" in the previous paragraph means the permission is created to |
| 126 | ** export the property. In other words, the requesting side has presented |
| 127 | ** login credentials and has sufficient capabilities to access the requested |
| 128 | ** information. |
| 129 | */ |
| 130 | int configure_is_exportable(const char *zName){ |
| 131 | int i; |
| 132 | for(i=0; i<count(aConfig); i++){ |
| 133 | if( fossil_strcmp(zName, aConfig[i].zName)==0 ){ |
| @@ -297,10 +303,50 @@ | |
| 303 | ** Process a single "config" card received from the other side of a |
| 304 | ** sync session. |
| 305 | ** |
| 306 | ** Mask consists of one or more CONFIGSET_* values ORed together, to |
| 307 | ** designate what types of configuration we are allowed to receive. |
| 308 | ** |
| 309 | ** NEW FORMAT: |
| 310 | ** |
| 311 | ** zName is one of "/config", "/user", "/shun", "/reportfmt", or "/concealed". |
| 312 | ** zName indicates the table that holds the configuration information being |
| 313 | ** transferred. pContent is a string that consist of alternating Fossil |
| 314 | ** and SQL tokens. The First token is a timestamp in seconds since 1970. |
| 315 | ** The second token is a primary key for the table identified by zName. If |
| 316 | ** The entry with the corresponding primary key exists and has a more recent |
| 317 | ** mtime, then nothing happens. If the entry does not exist or if it has |
| 318 | ** an older mtime, then the content described by subsequent token pairs is |
| 319 | ** inserted. The first element of each token pair is a column name and |
| 320 | ** the second is its value. |
| 321 | ** |
| 322 | ** In overview, we have: |
| 323 | ** |
| 324 | ** NAME CONTENT |
| 325 | ** ------- ----------------------------------------------------------- |
| 326 | ** /config $MTIME $NAME value $VALUE |
| 327 | ** /user $MTIME $LOGIN pw $VALUE cap $VALUE info $VALUE photo $VALUE |
| 328 | ** /shun $MTIME $UUID scom $VALUE |
| 329 | ** /reportfmt $MTIME $TITLE owner $VALUE cols $VALUE sqlcode $VALUE |
| 330 | ** /concealed $MTIME $HASH content $VALUE |
| 331 | ** |
| 332 | ** OLD FORMAT: |
| 333 | ** |
| 334 | ** The old format is retained for backwards compatiblity, but is deprecated. |
| 335 | ** The cutover from old format to new was on 2011-04-25. After sufficient |
| 336 | ** time has passed, support for the old format will be removed. |
| 337 | ** |
| 338 | ** zName is either the NAME of an element of the CONFIG table, or else |
| 339 | ** one of the special names "@shun", "@reportfmt", "@user", or "@concealed". |
| 340 | ** If zName is a CONFIG table name, then CONTENT replaces (overwrites) the |
| 341 | ** element in the CONFIG table. For one of the @-labels, CONTENT is raw |
| 342 | ** SQL that is evaluated. Note that the raw SQL in CONTENT might not |
| 343 | ** insert directly into the target table but might instead use a proxy |
| 344 | ** table like _fer_reportfmt or _xfer_user. Such tables must be created |
| 345 | ** ahead of time using configure_prepare_to_receive(). Then after multiple |
| 346 | ** calls to this routine, configure_finalize_receive() to transfer the |
| 347 | ** information received into the true target table. |
| 348 | */ |
| 349 | void configure_receive(const char *zName, Blob *pContent, int mask){ |
| 350 | if( (configure_is_exportable(zName) & mask)==0 ) return; |
| 351 | if( strcmp(zName, "logo-image")==0 ){ |
| 352 | Stmt ins; |
| 353 |