| | @@ -1644,18 +1644,19 @@ |
| 1644 | 1644 | |
| 1645 | 1645 | #if INTERFACE |
| 1646 | 1646 | /* |
| 1647 | 1647 | ** Flag options for controlling client_sync() |
| 1648 | 1648 | */ |
| 1649 | | -#define SYNC_PUSH 0x0001 |
| 1650 | | -#define SYNC_PULL 0x0002 |
| 1651 | | -#define SYNC_CLONE 0x0004 |
| 1652 | | -#define SYNC_PRIVATE 0x0008 |
| 1653 | | -#define SYNC_VERBOSE 0x0010 |
| 1654 | | -#define SYNC_RESYNC 0x0020 |
| 1655 | | -#define SYNC_UNVERSIONED 0x0040 |
| 1656 | | -#define SYNC_FROMPARENT 0x0080 |
| 1649 | +#define SYNC_PUSH 0x0001 /* push content client to server */ |
| 1650 | +#define SYNC_PULL 0x0002 /* pull content server to client */ |
| 1651 | +#define SYNC_CLONE 0x0004 /* clone the repository */ |
| 1652 | +#define SYNC_PRIVATE 0x0008 /* Also transfer private content */ |
| 1653 | +#define SYNC_VERBOSE 0x0010 /* Extra diagnostics */ |
| 1654 | +#define SYNC_RESYNC 0x0020 /* --verily */ |
| 1655 | +#define SYNC_UNVERSIONED 0x0040 /* Sync unversioned content */ |
| 1656 | +#define SYNC_UV_REVERT 0x0080 /* Copy server unversioned to client */ |
| 1657 | +#define SYNC_FROMPARENT 0x0100 /* Pull from the parent project */ |
| 1657 | 1658 | #endif |
| 1658 | 1659 | |
| 1659 | 1660 | /* |
| 1660 | 1661 | ** Floating-point absolute value |
| 1661 | 1662 | */ |
| | @@ -1749,11 +1750,11 @@ |
| 1749 | 1750 | } |
| 1750 | 1751 | |
| 1751 | 1752 | /* When syncing unversioned files, create a TEMP table in which to store |
| 1752 | 1753 | ** the names of files that do not need to be sent from client to server. |
| 1753 | 1754 | */ |
| 1754 | | - if( syncFlags & SYNC_UNVERSIONED ){ |
| 1755 | + if( (syncFlags & SYNC_UNVERSIONED)!=0 ){ |
| 1755 | 1756 | db_multi_exec( |
| 1756 | 1757 | "CREATE TEMP TABLE uv_tosend(" |
| 1757 | 1758 | " name TEXT PRIMARY KEY," |
| 1758 | 1759 | " mtimeOnly BOOLEAN" |
| 1759 | 1760 | ") WITHOUT ROWID;" |
| | @@ -1877,27 +1878,42 @@ |
| 1877 | 1878 | configSendMask = 0; |
| 1878 | 1879 | } |
| 1879 | 1880 | |
| 1880 | 1881 | /* Send unversioned files present here on the client but missing or |
| 1881 | 1882 | ** obsolete on the server. |
| 1883 | + ** |
| 1884 | + ** Or, if the SYNC_UV_REVERT flag is set, delete the local unversioned |
| 1885 | + ** files that do not exist on the server. |
| 1882 | 1886 | */ |
| 1883 | 1887 | if( uvDoPush ){ |
| 1884 | | - Stmt uvq; |
| 1885 | | - int rc = SQLITE_OK; |
| 1886 | 1888 | assert( (syncFlags & SYNC_UNVERSIONED)!=0 ); |
| 1887 | 1889 | assert( uvStatus==2 ); |
| 1888 | | - db_prepare(&uvq, "SELECT name, mtimeOnly FROM uv_tosend"); |
| 1889 | | - while( (rc = db_step(&uvq))==SQLITE_ROW ){ |
| 1890 | | - const char *zName = db_column_text(&uvq, 0); |
| 1891 | | - send_unversioned_file(&xfer, zName, db_column_int(&uvq,1)); |
| 1892 | | - nCardSent++; |
| 1893 | | - nArtifactSent++; |
| 1894 | | - db_multi_exec("DELETE FROM uv_tosend WHERE name=%Q", zName); |
| 1895 | | - if( blob_size(xfer.pOut)>xfer.mxSend ) break; |
| 1896 | | - } |
| 1897 | | - db_finalize(&uvq); |
| 1898 | | - if( rc==SQLITE_DONE ) uvDoPush = 0; |
| 1890 | + if( syncFlags & SYNC_UV_REVERT ){ |
| 1891 | + db_multi_exec( |
| 1892 | + "DELETE FROM unversioned" |
| 1893 | + " WHERE name IN (SELECT name FROM uv_tosend);" |
| 1894 | + "DELETE FROM uv_tosend;" |
| 1895 | + ); |
| 1896 | + uvDoPush = 0; |
| 1897 | + }else{ |
| 1898 | + Stmt uvq; |
| 1899 | + int rc = SQLITE_OK; |
| 1900 | + db_prepare(&uvq, "SELECT name, mtimeOnly FROM uv_tosend"); |
| 1901 | + while( (rc = db_step(&uvq))==SQLITE_ROW ){ |
| 1902 | + const char *zName = db_column_text(&uvq, 0); |
| 1903 | + send_unversioned_file(&xfer, zName, db_column_int(&uvq,1)); |
| 1904 | + nCardSent++; |
| 1905 | + nArtifactSent++; |
| 1906 | + db_multi_exec("DELETE FROM uv_tosend WHERE name=%Q", zName); |
| 1907 | + if( syncFlags & SYNC_VERBOSE ){ |
| 1908 | + fossil_print("\rUnversioned-file sent: %s\n", zName); |
| 1909 | + } |
| 1910 | + if( blob_size(xfer.pOut)>xfer.mxSend ) break; |
| 1911 | + } |
| 1912 | + db_finalize(&uvq); |
| 1913 | + if( rc==SQLITE_DONE ) uvDoPush = 0; |
| 1914 | + } |
| 1899 | 1915 | } |
| 1900 | 1916 | |
| 1901 | 1917 | /* Append randomness to the end of the message. This makes all |
| 1902 | 1918 | ** messages unique so that that the login-card nonce will always |
| 1903 | 1919 | ** be unique. |
| | @@ -2016,10 +2032,14 @@ |
| 2016 | 2032 | */ |
| 2017 | 2033 | if( blob_eq(&xfer.aToken[0], "uvfile") ){ |
| 2018 | 2034 | xfer_accept_unversioned_file(&xfer, 1); |
| 2019 | 2035 | nArtifactRcvd++; |
| 2020 | 2036 | nUvFileRcvd++; |
| 2037 | + if( syncFlags & SYNC_VERBOSE ){ |
| 2038 | + fossil_print("\rUnversioned-file received: %s\n", |
| 2039 | + blob_str(&xfer.aToken[1])); |
| 2040 | + } |
| 2021 | 2041 | }else |
| 2022 | 2042 | |
| 2023 | 2043 | /* gimme UUID |
| 2024 | 2044 | ** |
| 2025 | 2045 | ** Server is requesting a file. If the file is a manifest, assume |
| | @@ -2089,10 +2109,11 @@ |
| 2089 | 2109 | const char *zName = blob_str(&xfer.aToken[1]); |
| 2090 | 2110 | const char *zHash = blob_str(&xfer.aToken[3]); |
| 2091 | 2111 | int iStatus; |
| 2092 | 2112 | if( uvStatus==0 ) uvStatus = 2; |
| 2093 | 2113 | iStatus = unversioned_status(zName, mtime, zHash); |
| 2114 | + if( (syncFlags & SYNC_UV_REVERT)!=0 && iStatus==4 ) iStatus = 2; |
| 2094 | 2115 | if( iStatus<=1 ){ |
| 2095 | 2116 | if( zHash[0]!='-' ){ |
| 2096 | 2117 | blob_appendf(xfer.pOut, "uvgimme %s\n", zName); |
| 2097 | 2118 | nCardSent++; |
| 2098 | 2119 | nUvGimmeSent++; |
| | @@ -2229,10 +2250,11 @@ |
| 2229 | 2250 | ** bandwidth trying to upload unversioned content. If the server |
| 2230 | 2251 | ** does accept new unversioned content, it sends "uv-push-ok". |
| 2231 | 2252 | */ |
| 2232 | 2253 | if( blob_eq(&xfer.aToken[1], "uv-pull-only") ){ |
| 2233 | 2254 | uvStatus = 1; |
| 2255 | + if( syncFlags & SYNC_UV_REVERT ) uvDoPush = 1; |
| 2234 | 2256 | }else if( blob_eq(&xfer.aToken[1], "uv-push-ok") ){ |
| 2235 | 2257 | uvStatus = 2; |
| 2236 | 2258 | uvDoPush = 1; |
| 2237 | 2259 | } |
| 2238 | 2260 | }else |
| 2239 | 2261 | |