Fossil SCM

Improved error messages when a commit fails due to a lock conflict: Show the age of the lock in addition to the user. Suggest using the new --override-lock option instead of --allow-fork. Expire locks after any successful check-in from the same check-out.

drh 2019-07-12 13:58 trunk
Commit 3a5caa86dbaebba1fd4a956042ebdab2b031f3c26be0870bca7829b4ec2ccea3
3 files changed +15 -17 +1 -1 +37 -8
+15 -17
--- src/checkin.c
+++ src/checkin.c
@@ -2012,10 +2012,11 @@
20122012
** --no-prompt This option disables prompting the user for
20132013
** input and assumes an answer of 'No' for every
20142014
** question.
20152015
** --no-warnings omit all warnings about file contents
20162016
** --nosign do not attempt to sign this commit with gpg
2017
+** --override-lock allow a check-in even though parent is locked
20172018
** --private do not sync changes and their descendants
20182019
** --hash verify file status using hashing rather
20192020
** than relying on file mtimes
20202021
** --tag TAG-NAME assign given tag TAG-NAME to the check-in
20212022
** --date-override DATETIME DATE to use instead of 'now'
@@ -2088,10 +2089,11 @@
20882089
zComment = find_option("comment","m",1);
20892090
forceFlag = find_option("force", "f", 0)!=0;
20902091
allowConflict = find_option("allow-conflict",0,0)!=0;
20912092
allowEmpty = find_option("allow-empty",0,0)!=0;
20922093
allowFork = find_option("allow-fork",0,0)!=0;
2094
+ if( find_option("override-lock",0,0)!=0 ) allowFork = 1;
20932095
allowOlder = find_option("allow-older",0,0)!=0;
20942096
noPrompt = find_option("no-prompt", 0, 0)!=0;
20952097
noWarningFlag = find_option("no-warnings", 0, 0)!=0;
20962098
sCiInfo.zBranch = find_option("branch","b",1);
20972099
sCiInfo.zColor = find_option("bgcolor",0,1);
@@ -2272,28 +2274,24 @@
22722274
/*
22732275
** Do not allow a commit that will cause a fork unless the --allow-fork
22742276
** or --force flags is used, or unless this is a private check-in.
22752277
** The initial commit MUST have tags "trunk" and "sym-trunk".
22762278
*/
2277
- if( !vid ){
2278
- if( sCiInfo.zBranch==0 ){
2279
- if( allowFork==0 && forceFlag==0 && g.markPrivate==0
2280
- && db_exists("SELECT 1 from event where type='ci'") ){
2281
- fossil_fatal("Would fork. \"update\" first, use --branch, or --allow-fork.\n"
2282
- "See https://fossil-scm.org/fossil/doc/trunk/www/branching.wiki#branching");
2283
- }
2284
- sCiInfo.zBranch = db_get("main-branch", "trunk");
2285
- }
2286
- }else if( sCiInfo.zBranch==0 && allowFork==0 && forceFlag==0
2287
- && g.markPrivate==0 && (g.ckinLockFail || !is_a_leaf(vid))
2279
+ if( sCiInfo.zBranch==0
2280
+ && allowFork==0
2281
+ && forceFlag==0
2282
+ && g.markPrivate==0
2283
+ && (vid==0 || !is_a_leaf(vid) || g.ckinLockFail)
22882284
){
2289
- /* Can't avoid duplicating this string because some C compilers
2290
- ** refuse to see static const char zErr[] = "... as "constant"
2291
- ** enough for a printf() style format string. (e.g. Clang 10)
2292
- */
2293
- fossil_fatal("Would fork. \"update\" first, use --branch or, --allow-fork.\n"
2294
- "See https://fossil-scm.org/fossil/doc/trunk/www/branching.wiki#branching");
2285
+ if( g.ckinLockFail ){
2286
+ fossil_fatal("Might fork due to a check-in race with user \"%s\"\n"
2287
+ "Try \"update\" first, or --branch, or use --override-lock",
2288
+ g.ckinLockFail);
2289
+ }else{
2290
+ fossil_fatal("Would fork. \"update\" first or use --branch or "
2291
+ "--allow-fork.");
2292
+ }
22952293
}
22962294
22972295
/*
22982296
** Do not allow a commit against a closed leaf unless the commit
22992297
** ends up on a different branch.
23002298
--- src/checkin.c
+++ src/checkin.c
@@ -2012,10 +2012,11 @@
2012 ** --no-prompt This option disables prompting the user for
2013 ** input and assumes an answer of 'No' for every
2014 ** question.
2015 ** --no-warnings omit all warnings about file contents
2016 ** --nosign do not attempt to sign this commit with gpg
 
2017 ** --private do not sync changes and their descendants
2018 ** --hash verify file status using hashing rather
2019 ** than relying on file mtimes
2020 ** --tag TAG-NAME assign given tag TAG-NAME to the check-in
2021 ** --date-override DATETIME DATE to use instead of 'now'
@@ -2088,10 +2089,11 @@
2088 zComment = find_option("comment","m",1);
2089 forceFlag = find_option("force", "f", 0)!=0;
2090 allowConflict = find_option("allow-conflict",0,0)!=0;
2091 allowEmpty = find_option("allow-empty",0,0)!=0;
2092 allowFork = find_option("allow-fork",0,0)!=0;
 
2093 allowOlder = find_option("allow-older",0,0)!=0;
2094 noPrompt = find_option("no-prompt", 0, 0)!=0;
2095 noWarningFlag = find_option("no-warnings", 0, 0)!=0;
2096 sCiInfo.zBranch = find_option("branch","b",1);
2097 sCiInfo.zColor = find_option("bgcolor",0,1);
@@ -2272,28 +2274,24 @@
2272 /*
2273 ** Do not allow a commit that will cause a fork unless the --allow-fork
2274 ** or --force flags is used, or unless this is a private check-in.
2275 ** The initial commit MUST have tags "trunk" and "sym-trunk".
2276 */
2277 if( !vid ){
2278 if( sCiInfo.zBranch==0 ){
2279 if( allowFork==0 && forceFlag==0 && g.markPrivate==0
2280 && db_exists("SELECT 1 from event where type='ci'") ){
2281 fossil_fatal("Would fork. \"update\" first, use --branch, or --allow-fork.\n"
2282 "See https://fossil-scm.org/fossil/doc/trunk/www/branching.wiki#branching");
2283 }
2284 sCiInfo.zBranch = db_get("main-branch", "trunk");
2285 }
2286 }else if( sCiInfo.zBranch==0 && allowFork==0 && forceFlag==0
2287 && g.markPrivate==0 && (g.ckinLockFail || !is_a_leaf(vid))
2288 ){
2289 /* Can't avoid duplicating this string because some C compilers
2290 ** refuse to see static const char zErr[] = "... as "constant"
2291 ** enough for a printf() style format string. (e.g. Clang 10)
2292 */
2293 fossil_fatal("Would fork. \"update\" first, use --branch or, --allow-fork.\n"
2294 "See https://fossil-scm.org/fossil/doc/trunk/www/branching.wiki#branching");
 
 
2295 }
2296
2297 /*
2298 ** Do not allow a commit against a closed leaf unless the commit
2299 ** ends up on a different branch.
2300
--- src/checkin.c
+++ src/checkin.c
@@ -2012,10 +2012,11 @@
2012 ** --no-prompt This option disables prompting the user for
2013 ** input and assumes an answer of 'No' for every
2014 ** question.
2015 ** --no-warnings omit all warnings about file contents
2016 ** --nosign do not attempt to sign this commit with gpg
2017 ** --override-lock allow a check-in even though parent is locked
2018 ** --private do not sync changes and their descendants
2019 ** --hash verify file status using hashing rather
2020 ** than relying on file mtimes
2021 ** --tag TAG-NAME assign given tag TAG-NAME to the check-in
2022 ** --date-override DATETIME DATE to use instead of 'now'
@@ -2088,10 +2089,11 @@
2089 zComment = find_option("comment","m",1);
2090 forceFlag = find_option("force", "f", 0)!=0;
2091 allowConflict = find_option("allow-conflict",0,0)!=0;
2092 allowEmpty = find_option("allow-empty",0,0)!=0;
2093 allowFork = find_option("allow-fork",0,0)!=0;
2094 if( find_option("override-lock",0,0)!=0 ) allowFork = 1;
2095 allowOlder = find_option("allow-older",0,0)!=0;
2096 noPrompt = find_option("no-prompt", 0, 0)!=0;
2097 noWarningFlag = find_option("no-warnings", 0, 0)!=0;
2098 sCiInfo.zBranch = find_option("branch","b",1);
2099 sCiInfo.zColor = find_option("bgcolor",0,1);
@@ -2272,28 +2274,24 @@
2274 /*
2275 ** Do not allow a commit that will cause a fork unless the --allow-fork
2276 ** or --force flags is used, or unless this is a private check-in.
2277 ** The initial commit MUST have tags "trunk" and "sym-trunk".
2278 */
2279 if( sCiInfo.zBranch==0
2280 && allowFork==0
2281 && forceFlag==0
2282 && g.markPrivate==0
2283 && (vid==0 || !is_a_leaf(vid) || g.ckinLockFail)
 
 
 
 
 
 
2284 ){
2285 if( g.ckinLockFail ){
2286 fossil_fatal("Might fork due to a check-in race with user \"%s\"\n"
2287 "Try \"update\" first, or --branch, or use --override-lock",
2288 g.ckinLockFail);
2289 }else{
2290 fossil_fatal("Would fork. \"update\" first or use --branch or "
2291 "--allow-fork.");
2292 }
2293 }
2294
2295 /*
2296 ** Do not allow a commit against a closed leaf unless the commit
2297 ** ends up on a different branch.
2298
+1 -1
--- src/main.c
+++ src/main.c
@@ -190,11 +190,11 @@
190190
FILE *httpOut; /* Send HTTP output here */
191191
int xlinkClusterOnly; /* Set when cloning. Only process clusters */
192192
int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */
193193
int *aCommitFile; /* Array of files to be committed */
194194
int markPrivate; /* All new artifacts are private if true */
195
- int ckinLockFail; /* Check-in lock failure received from server */
195
+ char *ckinLockFail; /* Check-in lock failure received from server */
196196
int clockSkewSeen; /* True if clocks on client and server out of sync */
197197
int wikiFlags; /* Wiki conversion flags applied to %W */
198198
char isHTTP; /* True if server/CGI modes, else assume CLI. */
199199
char javascriptHyperlink; /* If true, set href= using script, not HTML */
200200
Blob httpHeader; /* Complete text of the HTTP request header */
201201
--- src/main.c
+++ src/main.c
@@ -190,11 +190,11 @@
190 FILE *httpOut; /* Send HTTP output here */
191 int xlinkClusterOnly; /* Set when cloning. Only process clusters */
192 int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */
193 int *aCommitFile; /* Array of files to be committed */
194 int markPrivate; /* All new artifacts are private if true */
195 int ckinLockFail; /* Check-in lock failure received from server */
196 int clockSkewSeen; /* True if clocks on client and server out of sync */
197 int wikiFlags; /* Wiki conversion flags applied to %W */
198 char isHTTP; /* True if server/CGI modes, else assume CLI. */
199 char javascriptHyperlink; /* If true, set href= using script, not HTML */
200 Blob httpHeader; /* Complete text of the HTTP request header */
201
--- src/main.c
+++ src/main.c
@@ -190,11 +190,11 @@
190 FILE *httpOut; /* Send HTTP output here */
191 int xlinkClusterOnly; /* Set when cloning. Only process clusters */
192 int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */
193 int *aCommitFile; /* Array of files to be committed */
194 int markPrivate; /* All new artifacts are private if true */
195 char *ckinLockFail; /* Check-in lock failure received from server */
196 int clockSkewSeen; /* True if clocks on client and server out of sync */
197 int wikiFlags; /* Wiki conversion flags applied to %W */
198 char isHTTP; /* True if server/CGI modes, else assume CLI. */
199 char javascriptHyperlink; /* If true, set href= using script, not HTML */
200 Blob httpHeader; /* Complete text of the HTTP request header */
201
+37 -8
--- src/xfer.c
+++ src/xfer.c
@@ -1559,10 +1559,11 @@
15591559
&& xfer.nToken==4
15601560
&& blob_is_hname(&xfer.aToken[2])
15611561
){
15621562
Stmt q;
15631563
sqlite3_int64 iNow = time(0);
1564
+ const sqlite3_int64 maxAge = 3600*24; /* Locks expire after 24 hours */
15641565
int seenFault = 0;
15651566
db_prepare(&q,
15661567
"SELECT json_extract(value,'$.login'),"
15671568
" mtime,"
15681569
" json_extract(value,'$.clientid'),"
@@ -1571,13 +1572,13 @@
15711572
" FROM config WHERE name GLOB 'ci-lock-*'"
15721573
);
15731574
while( db_step(&q)==SQLITE_ROW ){
15741575
int x = db_column_int(&q,3);
15751576
const char *zName = db_column_text(&q,4);
1576
- if( db_column_int64(&q,1)<iNow-3600*24 || !is_a_leaf(x) ){
1577
- /* check-in locks expire after 24 hours, or when the check-in
1578
- ** is no longer a leaf */
1577
+ if( db_column_int64(&q,1)<iNow-maxAge || !is_a_leaf(x) ){
1578
+ /* check-in locks expire after maxAge seconds, or when the
1579
+ ** check-in is no longer a leaf */
15791580
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
15801581
continue;
15811582
}
15821583
if( fossil_strcmp(zName+8, blob_str(&xfer.aToken[2]))==0 ){
15831584
const char *zClientId = db_column_text(&q, 2);
@@ -1597,10 +1598,29 @@
15971598
blob_str(&xfer.aToken[2]), g.zLogin,
15981599
blob_str(&xfer.aToken[3])
15991600
);
16001601
}
16011602
}
1603
+
1604
+ /* pragma ci-unlock CLIENT-ID
1605
+ **
1606
+ ** Remove any locks previously held by CLIENT-ID. Clients send this
1607
+ ** pragma with their own ID whenever they know that they no longer
1608
+ ** have any commits pending.
1609
+ */
1610
+ if( blob_eq(&xfer.aToken[1], "ci-unlock")
1611
+ && xfer.nToken==3
1612
+ && blob_is_hname(&xfer.aToken[2])
1613
+ ){
1614
+ db_multi_exec(
1615
+ "DELETE FROM config"
1616
+ " WHERE name GLOB 'ci-lock-*'"
1617
+ " AND json_extract(value,'$.clientid')=%Q",
1618
+ blob_str(&xfer.aToken[2])
1619
+ );
1620
+ }
1621
+
16021622
}else
16031623
16041624
/* Unknown message
16051625
*/
16061626
{
@@ -1762,10 +1782,11 @@
17621782
int nUvGimmeSent = 0; /* Number of uvgimme cards sent on this cycle */
17631783
int nUvFileRcvd = 0; /* Number of uvfile cards received on this cycle */
17641784
sqlite3_int64 mtime; /* Modification time on a UV file */
17651785
int autopushFailed = 0; /* Autopush following commit failed if true */
17661786
const char *zCkinLock; /* Name of check-in to lock. NULL for none */
1787
+ const char *zClientId; /* A unique identifier for this check-out */
17671788
17681789
if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
17691790
if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED))==0
17701791
&& configRcvMask==0 && configSendMask==0 ) return 0;
17711792
if( syncFlags & SYNC_FROMPARENT ){
@@ -1797,11 +1818,11 @@
17971818
blob_zero(&send);
17981819
blob_zero(&recv);
17991820
blob_zero(&xfer.err);
18001821
blob_zero(&xfer.line);
18011822
origConfigRcvMask = 0;
1802
-
1823
+ zClientId = db_lget("client-id", 0);
18031824
18041825
/* Send the send-private pragma if we are trying to sync private data */
18051826
if( syncFlags & SYNC_PRIVATE ){
18061827
blob_append(&send, "pragma send-private\n", -1);
18071828
}
@@ -1976,18 +1997,18 @@
19761997
}
19771998
}
19781999
19792000
/* Lock the current check-out */
19802001
if( zCkinLock ){
1981
- const char *zClientId;
1982
- zClientId = db_lget("client-id", 0);
19832002
if( zClientId==0 ){
19842003
zClientId = db_text(0, "SELECT lower(hex(randomblob(20)))");
19852004
db_lset("client-id", zClientId);
19862005
}
19872006
blob_appendf(&send, "pragma ci-lock %s %s\n", zCkinLock, zClientId);
19882007
zCkinLock = 0;
2008
+ }else if( zClientId ){
2009
+ blob_appendf(&send, "pragma ci-unlock %s\n", zClientId);
19892010
}
19902011
19912012
/* Append randomness to the end of the message. This makes all
19922013
** messages unique so that that the login-card nonce will always
19932014
** be unique.
@@ -2356,13 +2377,21 @@
23562377
** the lock, and LOCK-TIME is the timestamp (seconds since 1970)
23572378
** when the lock was taken.
23582379
*/
23592380
else if( blob_eq(&xfer.aToken[1], "ci-lock-fail") && xfer.nToken==4 ){
23602381
char *zUser = blob_terminate(&xfer.aToken[2]);
2382
+ sqlite3_int64 mtime, iNow;
23612383
defossilize(zUser);
2362
- fossil_print("\nParent check-in locked by %s\n", zUser);
2363
- g.ckinLockFail = 1;
2384
+ iNow = time(NULL);
2385
+ if( blob_is_int64(&xfer.aToken[3], &mtime) && iNow>mtime ){
2386
+ iNow = time(NULL);
2387
+ fossil_print("\nParent check-in lock by %s %s ago\n",
2388
+ zUser, human_readable_age((iNow+1-mtime)/86400.0));
2389
+ }else{
2390
+ fossil_print("\nParent check-in locked by %s\n", zUser);
2391
+ }
2392
+ g.ckinLockFail = fossil_strdup(zUser);
23642393
}
23652394
}else
23662395
23672396
/* error MESSAGE
23682397
**
23692398
--- src/xfer.c
+++ src/xfer.c
@@ -1559,10 +1559,11 @@
1559 && xfer.nToken==4
1560 && blob_is_hname(&xfer.aToken[2])
1561 ){
1562 Stmt q;
1563 sqlite3_int64 iNow = time(0);
 
1564 int seenFault = 0;
1565 db_prepare(&q,
1566 "SELECT json_extract(value,'$.login'),"
1567 " mtime,"
1568 " json_extract(value,'$.clientid'),"
@@ -1571,13 +1572,13 @@
1571 " FROM config WHERE name GLOB 'ci-lock-*'"
1572 );
1573 while( db_step(&q)==SQLITE_ROW ){
1574 int x = db_column_int(&q,3);
1575 const char *zName = db_column_text(&q,4);
1576 if( db_column_int64(&q,1)<iNow-3600*24 || !is_a_leaf(x) ){
1577 /* check-in locks expire after 24 hours, or when the check-in
1578 ** is no longer a leaf */
1579 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1580 continue;
1581 }
1582 if( fossil_strcmp(zName+8, blob_str(&xfer.aToken[2]))==0 ){
1583 const char *zClientId = db_column_text(&q, 2);
@@ -1597,10 +1598,29 @@
1597 blob_str(&xfer.aToken[2]), g.zLogin,
1598 blob_str(&xfer.aToken[3])
1599 );
1600 }
1601 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1602 }else
1603
1604 /* Unknown message
1605 */
1606 {
@@ -1762,10 +1782,11 @@
1762 int nUvGimmeSent = 0; /* Number of uvgimme cards sent on this cycle */
1763 int nUvFileRcvd = 0; /* Number of uvfile cards received on this cycle */
1764 sqlite3_int64 mtime; /* Modification time on a UV file */
1765 int autopushFailed = 0; /* Autopush following commit failed if true */
1766 const char *zCkinLock; /* Name of check-in to lock. NULL for none */
 
1767
1768 if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
1769 if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED))==0
1770 && configRcvMask==0 && configSendMask==0 ) return 0;
1771 if( syncFlags & SYNC_FROMPARENT ){
@@ -1797,11 +1818,11 @@
1797 blob_zero(&send);
1798 blob_zero(&recv);
1799 blob_zero(&xfer.err);
1800 blob_zero(&xfer.line);
1801 origConfigRcvMask = 0;
1802
1803
1804 /* Send the send-private pragma if we are trying to sync private data */
1805 if( syncFlags & SYNC_PRIVATE ){
1806 blob_append(&send, "pragma send-private\n", -1);
1807 }
@@ -1976,18 +1997,18 @@
1976 }
1977 }
1978
1979 /* Lock the current check-out */
1980 if( zCkinLock ){
1981 const char *zClientId;
1982 zClientId = db_lget("client-id", 0);
1983 if( zClientId==0 ){
1984 zClientId = db_text(0, "SELECT lower(hex(randomblob(20)))");
1985 db_lset("client-id", zClientId);
1986 }
1987 blob_appendf(&send, "pragma ci-lock %s %s\n", zCkinLock, zClientId);
1988 zCkinLock = 0;
 
 
1989 }
1990
1991 /* Append randomness to the end of the message. This makes all
1992 ** messages unique so that that the login-card nonce will always
1993 ** be unique.
@@ -2356,13 +2377,21 @@
2356 ** the lock, and LOCK-TIME is the timestamp (seconds since 1970)
2357 ** when the lock was taken.
2358 */
2359 else if( blob_eq(&xfer.aToken[1], "ci-lock-fail") && xfer.nToken==4 ){
2360 char *zUser = blob_terminate(&xfer.aToken[2]);
 
2361 defossilize(zUser);
2362 fossil_print("\nParent check-in locked by %s\n", zUser);
2363 g.ckinLockFail = 1;
 
 
 
 
 
 
 
2364 }
2365 }else
2366
2367 /* error MESSAGE
2368 **
2369
--- src/xfer.c
+++ src/xfer.c
@@ -1559,10 +1559,11 @@
1559 && xfer.nToken==4
1560 && blob_is_hname(&xfer.aToken[2])
1561 ){
1562 Stmt q;
1563 sqlite3_int64 iNow = time(0);
1564 const sqlite3_int64 maxAge = 3600*24; /* Locks expire after 24 hours */
1565 int seenFault = 0;
1566 db_prepare(&q,
1567 "SELECT json_extract(value,'$.login'),"
1568 " mtime,"
1569 " json_extract(value,'$.clientid'),"
@@ -1571,13 +1572,13 @@
1572 " FROM config WHERE name GLOB 'ci-lock-*'"
1573 );
1574 while( db_step(&q)==SQLITE_ROW ){
1575 int x = db_column_int(&q,3);
1576 const char *zName = db_column_text(&q,4);
1577 if( db_column_int64(&q,1)<iNow-maxAge || !is_a_leaf(x) ){
1578 /* check-in locks expire after maxAge seconds, or when the
1579 ** check-in is no longer a leaf */
1580 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1581 continue;
1582 }
1583 if( fossil_strcmp(zName+8, blob_str(&xfer.aToken[2]))==0 ){
1584 const char *zClientId = db_column_text(&q, 2);
@@ -1597,10 +1598,29 @@
1598 blob_str(&xfer.aToken[2]), g.zLogin,
1599 blob_str(&xfer.aToken[3])
1600 );
1601 }
1602 }
1603
1604 /* pragma ci-unlock CLIENT-ID
1605 **
1606 ** Remove any locks previously held by CLIENT-ID. Clients send this
1607 ** pragma with their own ID whenever they know that they no longer
1608 ** have any commits pending.
1609 */
1610 if( blob_eq(&xfer.aToken[1], "ci-unlock")
1611 && xfer.nToken==3
1612 && blob_is_hname(&xfer.aToken[2])
1613 ){
1614 db_multi_exec(
1615 "DELETE FROM config"
1616 " WHERE name GLOB 'ci-lock-*'"
1617 " AND json_extract(value,'$.clientid')=%Q",
1618 blob_str(&xfer.aToken[2])
1619 );
1620 }
1621
1622 }else
1623
1624 /* Unknown message
1625 */
1626 {
@@ -1762,10 +1782,11 @@
1782 int nUvGimmeSent = 0; /* Number of uvgimme cards sent on this cycle */
1783 int nUvFileRcvd = 0; /* Number of uvfile cards received on this cycle */
1784 sqlite3_int64 mtime; /* Modification time on a UV file */
1785 int autopushFailed = 0; /* Autopush following commit failed if true */
1786 const char *zCkinLock; /* Name of check-in to lock. NULL for none */
1787 const char *zClientId; /* A unique identifier for this check-out */
1788
1789 if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
1790 if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED))==0
1791 && configRcvMask==0 && configSendMask==0 ) return 0;
1792 if( syncFlags & SYNC_FROMPARENT ){
@@ -1797,11 +1818,11 @@
1818 blob_zero(&send);
1819 blob_zero(&recv);
1820 blob_zero(&xfer.err);
1821 blob_zero(&xfer.line);
1822 origConfigRcvMask = 0;
1823 zClientId = db_lget("client-id", 0);
1824
1825 /* Send the send-private pragma if we are trying to sync private data */
1826 if( syncFlags & SYNC_PRIVATE ){
1827 blob_append(&send, "pragma send-private\n", -1);
1828 }
@@ -1976,18 +1997,18 @@
1997 }
1998 }
1999
2000 /* Lock the current check-out */
2001 if( zCkinLock ){
 
 
2002 if( zClientId==0 ){
2003 zClientId = db_text(0, "SELECT lower(hex(randomblob(20)))");
2004 db_lset("client-id", zClientId);
2005 }
2006 blob_appendf(&send, "pragma ci-lock %s %s\n", zCkinLock, zClientId);
2007 zCkinLock = 0;
2008 }else if( zClientId ){
2009 blob_appendf(&send, "pragma ci-unlock %s\n", zClientId);
2010 }
2011
2012 /* Append randomness to the end of the message. This makes all
2013 ** messages unique so that that the login-card nonce will always
2014 ** be unique.
@@ -2356,13 +2377,21 @@
2377 ** the lock, and LOCK-TIME is the timestamp (seconds since 1970)
2378 ** when the lock was taken.
2379 */
2380 else if( blob_eq(&xfer.aToken[1], "ci-lock-fail") && xfer.nToken==4 ){
2381 char *zUser = blob_terminate(&xfer.aToken[2]);
2382 sqlite3_int64 mtime, iNow;
2383 defossilize(zUser);
2384 iNow = time(NULL);
2385 if( blob_is_int64(&xfer.aToken[3], &mtime) && iNow>mtime ){
2386 iNow = time(NULL);
2387 fossil_print("\nParent check-in lock by %s %s ago\n",
2388 zUser, human_readable_age((iNow+1-mtime)/86400.0));
2389 }else{
2390 fossil_print("\nParent check-in locked by %s\n", zUser);
2391 }
2392 g.ckinLockFail = fossil_strdup(zUser);
2393 }
2394 }else
2395
2396 /* error MESSAGE
2397 **
2398

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button