Fossil SCM
Fix the server-side sync operation so that it will not generate a delta loop when a file changes from its original state through two or more intermediate states and back to its original state and all versions of the file attempt to sync in a single transaction.
Commit
e5b8eb12352f11fb0082c46818e25eaa7a674f13
Parent
8ea929ca557c99d…
1 file changed
+9
-9
+9
-9
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -273,19 +273,15 @@ | ||
| 273 | 273 | Blob *pUuid /* The UUID of the file to send */ |
| 274 | 274 | ){ |
| 275 | 275 | static const char *const azQuery[] = { |
| 276 | 276 | "SELECT pid FROM plink x" |
| 277 | 277 | " WHERE cid=%d" |
| 278 | - " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" | |
| 279 | - " AND NOT EXISTS(SELECT 1 FROM plink y" | |
| 280 | - " WHERE y.pid=x.cid AND y.cid=x.pid)", | |
| 281 | - | |
| 282 | - "SELECT pid FROM mlink x" | |
| 278 | + " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)", | |
| 279 | + | |
| 280 | + "SELECT pid, min(mtime) FROM mlink, event ON mlink.mid=event.objid" | |
| 283 | 281 | " WHERE fid=%d" |
| 284 | 282 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 285 | - " AND NOT EXISTS(SELECT 1 FROM mlink y" | |
| 286 | - " WHERE y.pid=x.fid AND y.fid=x.pid)" | |
| 287 | 283 | }; |
| 288 | 284 | int i; |
| 289 | 285 | Blob src, delta; |
| 290 | 286 | int size = 0; |
| 291 | 287 | int srcId = 0; |
| @@ -303,11 +299,11 @@ | ||
| 303 | 299 | if( size>=blob_size(pContent)-50 ){ |
| 304 | 300 | size = 0; |
| 305 | 301 | }else if( uuid_is_shunned(zUuid) ){ |
| 306 | 302 | size = 0; |
| 307 | 303 | }else{ |
| 308 | - if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); | |
| 304 | + if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); | |
| 309 | 305 | blob_appendf(pXfer->pOut, "file %b %s %d\n", pUuid, zUuid, size); |
| 310 | 306 | blob_append(pXfer->pOut, blob_buffer(&delta), size); |
| 311 | 307 | } |
| 312 | 308 | blob_reset(&delta); |
| 313 | 309 | free(zUuid); |
| @@ -1659,11 +1655,15 @@ | ||
| 1659 | 1655 | ** to the next cycle. |
| 1660 | 1656 | */ |
| 1661 | 1657 | if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){ |
| 1662 | 1658 | char *zMsg = blob_terminate(&xfer.aToken[1]); |
| 1663 | 1659 | defossilize(zMsg); |
| 1664 | - if( zMsg ) fossil_print("\rServer says: %s\n", zMsg); | |
| 1660 | + if( pushFlag && zMsg && strglob("pull only *", zMsg) ){ | |
| 1661 | + pushFlag = 0; | |
| 1662 | + zMsg = 0; | |
| 1663 | + } | |
| 1664 | + fossil_print("\rServer says: %s\n", zMsg); | |
| 1665 | 1665 | }else |
| 1666 | 1666 | |
| 1667 | 1667 | /* pragma NAME VALUE... |
| 1668 | 1668 | ** |
| 1669 | 1669 | ** The server can send pragmas to try to convey meta-information to |
| 1670 | 1670 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -273,19 +273,15 @@ | |
| 273 | Blob *pUuid /* The UUID of the file to send */ |
| 274 | ){ |
| 275 | static const char *const azQuery[] = { |
| 276 | "SELECT pid FROM plink x" |
| 277 | " WHERE cid=%d" |
| 278 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 279 | " AND NOT EXISTS(SELECT 1 FROM plink y" |
| 280 | " WHERE y.pid=x.cid AND y.cid=x.pid)", |
| 281 | |
| 282 | "SELECT pid FROM mlink x" |
| 283 | " WHERE fid=%d" |
| 284 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 285 | " AND NOT EXISTS(SELECT 1 FROM mlink y" |
| 286 | " WHERE y.pid=x.fid AND y.fid=x.pid)" |
| 287 | }; |
| 288 | int i; |
| 289 | Blob src, delta; |
| 290 | int size = 0; |
| 291 | int srcId = 0; |
| @@ -303,11 +299,11 @@ | |
| 303 | if( size>=blob_size(pContent)-50 ){ |
| 304 | size = 0; |
| 305 | }else if( uuid_is_shunned(zUuid) ){ |
| 306 | size = 0; |
| 307 | }else{ |
| 308 | if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); |
| 309 | blob_appendf(pXfer->pOut, "file %b %s %d\n", pUuid, zUuid, size); |
| 310 | blob_append(pXfer->pOut, blob_buffer(&delta), size); |
| 311 | } |
| 312 | blob_reset(&delta); |
| 313 | free(zUuid); |
| @@ -1659,11 +1655,15 @@ | |
| 1659 | ** to the next cycle. |
| 1660 | */ |
| 1661 | if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){ |
| 1662 | char *zMsg = blob_terminate(&xfer.aToken[1]); |
| 1663 | defossilize(zMsg); |
| 1664 | if( zMsg ) fossil_print("\rServer says: %s\n", zMsg); |
| 1665 | }else |
| 1666 | |
| 1667 | /* pragma NAME VALUE... |
| 1668 | ** |
| 1669 | ** The server can send pragmas to try to convey meta-information to |
| 1670 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -273,19 +273,15 @@ | |
| 273 | Blob *pUuid /* The UUID of the file to send */ |
| 274 | ){ |
| 275 | static const char *const azQuery[] = { |
| 276 | "SELECT pid FROM plink x" |
| 277 | " WHERE cid=%d" |
| 278 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)", |
| 279 | |
| 280 | "SELECT pid, min(mtime) FROM mlink, event ON mlink.mid=event.objid" |
| 281 | " WHERE fid=%d" |
| 282 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 283 | }; |
| 284 | int i; |
| 285 | Blob src, delta; |
| 286 | int size = 0; |
| 287 | int srcId = 0; |
| @@ -303,11 +299,11 @@ | |
| 299 | if( size>=blob_size(pContent)-50 ){ |
| 300 | size = 0; |
| 301 | }else if( uuid_is_shunned(zUuid) ){ |
| 302 | size = 0; |
| 303 | }else{ |
| 304 | if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); |
| 305 | blob_appendf(pXfer->pOut, "file %b %s %d\n", pUuid, zUuid, size); |
| 306 | blob_append(pXfer->pOut, blob_buffer(&delta), size); |
| 307 | } |
| 308 | blob_reset(&delta); |
| 309 | free(zUuid); |
| @@ -1659,11 +1655,15 @@ | |
| 1655 | ** to the next cycle. |
| 1656 | */ |
| 1657 | if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){ |
| 1658 | char *zMsg = blob_terminate(&xfer.aToken[1]); |
| 1659 | defossilize(zMsg); |
| 1660 | if( pushFlag && zMsg && strglob("pull only *", zMsg) ){ |
| 1661 | pushFlag = 0; |
| 1662 | zMsg = 0; |
| 1663 | } |
| 1664 | fossil_print("\rServer says: %s\n", zMsg); |
| 1665 | }else |
| 1666 | |
| 1667 | /* pragma NAME VALUE... |
| 1668 | ** |
| 1669 | ** The server can send pragmas to try to convey meta-information to |
| 1670 |