@@ -1545,10 +1545,62 @@
1545 1545 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
send_unversioned_catalog(&xfer);
1546 1546 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1547 1547 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1548 1548 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
uvCatalogSent = 1;
1549 1549 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1550 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1551 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* pragma ci-lock CHECKIN-HASH CLIENT-ID
1552 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
1553 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** The client wants to make non-branch commit against the check-in
1554 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** identified by CHECKIN-HASH. The server will remember this and
1555 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** subsequent ci-lock request from different clients will generate
1556 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** a ci-lock-fail pragma in the reply.
1557 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
1558 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( blob_eq(&xfer.aToken[1], "ci-lock")
1559 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ && xfer.nToken==4
1560 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ && blob_is_hname(&xfer.aToken[2])
1561 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ){
1562 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Stmt q;
1563 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sqlite3_int64 iNow = time(0);
1564 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int seenFault = 0;
1565 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_prepare(&q,
1566 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT json_extract(value,'$.login'),"
1567 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " mtime,"
1568 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " json_extract(value,'$.clientid'),"
1569 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " (SELECT rid FROM blob WHERE uuid=substr(name,9)),"
1570 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " name"
1571 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " FROM config WHERE name GLOB 'ci-lock-*'"
1572 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
1573 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ while( db_step(&q)==SQLITE_ROW ){
1574 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int x = db_column_int(&q,3);
1575 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zName = db_column_text(&q,4);
1576 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( db_column_int64(&q,1)<iNow-3600*24 || !is_a_leaf(x) ){
1577 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* check-in locks expire after 24 hours, or when the check-in
1578 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** is no longer a leaf */
1579 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1580 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ continue;
1581 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1582 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( fossil_strcmp(zName+8, blob_str(&xfer.aToken[2]))==0 ){
1583 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zClientId = db_column_text(&q, 2);
1584 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zLogin = db_column_text(&q,0);
1585 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sqlite3_int64 mtime = db_column_int64(&q, 1);
1586 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( fossil_strcmp(zClientId, blob_str(&xfer.aToken[3]))!=0 ){
1587 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ pragma ci-lock-fail %F(zLogin) %lld(mtime)
1588 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1589 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ seenFault = 1;
1590 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1591 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1592 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_finalize(&q);
1593 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( !seenFault ){
1594 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_multi_exec(
1595 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "REPLACE INTO config(name,value,mtime)"
1596 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "VALUES('ci-lock-%q',json_object('login',%Q,'clientid',%Q),now())",
1597 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_str(&xfer.aToken[2]), g.zLogin,
1598 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_str(&xfer.aToken[3])
1599 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
1600 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1601 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1550 1602 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else
1551 1603 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
1552 1604 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/* Unknown message
1553 1605 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
1554 1606 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
{
@@ -1655,10 +1707,11 @@
1655 1707 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#define SYNC_UV_REVERT 0x0080 /* Copy server unversioned to client */
1656 1708 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#define SYNC_FROMPARENT 0x0100 /* Pull from the parent project */
1657 1709 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#define SYNC_UV_TRACE 0x0200 /* Describe UV activities */
1658 1710 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#define SYNC_UV_DRYRUN 0x0400 /* Do not actually exchange files */
1659 1711 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#define SYNC_IFABLE 0x0800 /* Inability to sync is not fatal */
1712 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ #define SYNC_CKIN_LOCK 0x1000 /* Lock the current check-in */
1660 1713 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#endif
1661 1714 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
1662 1715 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
1663 1716 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** Floating-point absolute value
1664 1717 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
@@ -1708,10 +1761,11 @@
1708 1761 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int uvDoPush = 0; /* Generate uvfile messages to send to server */
1709 1762 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int nUvGimmeSent = 0; /* Number of uvgimme cards sent on this cycle */
1710 1763 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int nUvFileRcvd = 0; /* Number of uvfile cards received on this cycle */
1711 1764 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
sqlite3_int64 mtime; /* Modification time on a UV file */
1712 1765 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int autopushFailed = 0; /* Autopush following commit failed if true */
1766 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zCkinLock; /* Name of check-in to lock. NULL for none */
1713 1767 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
1714 1768 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
1715 1769 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED))==0
1716 1770 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
&& configRcvMask==0 && configSendMask==0 ) return 0;
1717 1771 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( syncFlags & SYNC_FROMPARENT ){
@@ -1749,10 +1803,18 @@
1749 1803 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
1750 1804 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/* Send the send-private pragma if we are trying to sync private data */
1751 1805 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( syncFlags & SYNC_PRIVATE ){
1752 1806 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_append(&send, "pragma send-private\n", -1);
1753 1807 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1808 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1809 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* Figure out which check-in to lock */
1810 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( syncFlags & SYNC_CKIN_LOCK ){
1811 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int vid = db_lget_int("checkout",0);
1812 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zCkinLock = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
1813 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
1814 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zCkinLock = 0;
1815 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1754 1816 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
1755 1817 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/* When syncing unversioned files, create a TEMP table in which to store
1756 1818 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** the names of files that need to be sent from client to server.
1757 1819 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
**
1758 1820 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** The initial assumption is that all unversioned files need to be sent
@@ -1911,10 +1973,22 @@
1911 1973 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1912 1974 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_finalize(&uvq);
1913 1975 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( rc==SQLITE_DONE ) uvDoPush = 0;
1914 1976 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1915 1977 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1978 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1979 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* Lock the current check-out */
1980 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zCkinLock ){
1981 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zClientId;
1982 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zClientId = db_lget("client-id", 0);
1983 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zClientId==0 ){
1984 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zClientId = db_text(0, "SELECT lower(hex(randomblob(20)))");
1985 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_lset("client-id", zClientId);
1986 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1987 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_appendf(&send, "pragma ci-lock %s %s\n", zCkinLock, zClientId);
1988 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zCkinLock = 0;
1989 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1916 1990 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
1917 1991 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/* Append randomness to the end of the message. This makes all
1918 1992 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** messages unique so that that the login-card nonce will always
1919 1993 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** be unique.
1920 1994 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
@@ -2271,10 +2345,25 @@
2271 2345 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( blob_eq(&xfer.aToken[1], "uv-pull-only") ){
2272 2346 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( syncFlags & SYNC_UV_REVERT ) uvDoPush = 1;
2273 2347 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else if( blob_eq(&xfer.aToken[1], "uv-push-ok") ){
2274 2348 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
uvDoPush = 1;
2275 2349 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
2350 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2351 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* pragma ci-lock-fail USER-HOLDING-LOCK LOCK-TIME
2352 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
2353 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** The server generates this message when a "pragma ci-lock"
2354 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** is attempted on a check-in for which there is an existing
2355 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** lock. USER-HOLDING-LOCK is the name of the user who originated
2356 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** the lock, and LOCK-TIME is the timestamp (seconds since 1970)
2357 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** when the lock was taken.
2358 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
2359 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ else if( blob_eq(&xfer.aToken[1], "ci-lock-fail") && xfer.nToken==4 ){
2360 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char *zUser = blob_terminate(&xfer.aToken[2]);
2361 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ defossilize(zUser);
2362 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_print("Parent check-in locked by %s\n", zUser);
2363 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ g.ckinLockFail = 1;
2364 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2276 2365 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else
2277 2366 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
2278 2367 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/* error MESSAGE
2279 2368 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
**
2280 2369 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** Report an error and abandon the sync session.
2281 2370 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!