Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Use better fork detection mechanism and disable checking during push since it may not have a complete sync and issue warning prematurely. |
|---|---|
| Timelines: | family | ancestors | descendants | both | sync-forkwarn |
| Files: | files | file ages | folders |
| SHA1: |
d0e2f1bd3e71ebf64b8b36b06ff87188 |
| User & Date: | andybradford 2015-04-13 03:38:55.659 |
Context
|
2015-04-16
| ||
| 23:46 | Allow fossil_find_nearest_fork to be used on repository that is not open. check-in: 97f976785d user: andybradford tags: trunk | |
|
2015-04-13
| ||
| 08:30 | Merge trunk check-in: 731042d5ea user: jan.nijtmans tags: sync-forkwarn | |
| 03:38 | Use better fork detection mechanism and disable checking during push since it may not have a complete sync and issue warning prematurely. check-in: d0e2f1bd3e user: andybradford tags: sync-forkwarn | |
| 03:31 | Bring in needed changes from related branch. check-in: ebce686332 user: andybradford tags: sync-forkwarn | |
Changes
Changes to src/info.c.
| ︙ | ︙ | |||
119 120 121 122 123 124 125 |
if( is_a_leaf(rid) ){
if( db_int(0, "SELECT 1 FROM tagxref AS tx"
" WHERE tx.rid=%d"
" AND tx.tagid=%d"
" AND tx.tagtype>0",
rid, TAG_CLOSED)){
fossil_print("%s\n", "closed");
| | | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
if( is_a_leaf(rid) ){
if( db_int(0, "SELECT 1 FROM tagxref AS tx"
" WHERE tx.rid=%d"
" AND tx.tagid=%d"
" AND tx.tagtype>0",
rid, TAG_CLOSED)){
fossil_print("%s\n", "closed");
}else if( fossil_find_nearest_fork(rid, 1) ){
fossil_print("%s\n", "fork");
isFork = 1;
}else{
fossil_print("%s\n", "open");
}
}else{
fossil_print("no\n");
|
| ︙ | ︙ |
Changes to src/leaf.c.
| ︙ | ︙ | |||
149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
}else{
db_static_prepare(&addLeaf, "INSERT OR IGNORE INTO leaf VALUES(:rid)");
db_bind_int(&addLeaf, ":rid", rid);
db_step(&addLeaf);
db_reset(&addLeaf);
}
}
/*
** Return an SQL expression (stored in memory obtained from fossil_malloc())
** that is true if the SQL variable named "zVar" contains the rid with
** a CLOSED tag. In other words, return true if the leaf is closed.
**
** The result can be prefaced with a NOT operator to get all leaves that
| > > > > > > > > > | 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
}else{
db_static_prepare(&addLeaf, "INSERT OR IGNORE INTO leaf VALUES(:rid)");
db_bind_int(&addLeaf, ":rid", rid);
db_step(&addLeaf);
db_reset(&addLeaf);
}
}
/*
** Check for a fork against rid and set g.fForkSeen
*/
void fork_check(int rid){
if( is_a_leaf(rid) && fossil_find_nearest_fork(rid, 0) ){
g.forkSeen = 1;
}
}
/*
** Return an SQL expression (stored in memory obtained from fossil_malloc())
** that is true if the SQL variable named "zVar" contains the rid with
** a CLOSED tag. In other words, return true if the leaf is closed.
**
** The result can be prefaced with a NOT operator to get all leaves that
|
| ︙ | ︙ | |||
186 187 188 189 190 191 192 |
while( db_step(&parentsOf)==SQLITE_ROW ){
bag_insert(&needToCheck, db_column_int(&parentsOf, 0));
}
db_reset(&parentsOf);
}
/*
| | > > > | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
while( db_step(&parentsOf)==SQLITE_ROW ){
bag_insert(&needToCheck, db_column_int(&parentsOf, 0));
}
db_reset(&parentsOf);
}
/*
** Do all pending leaf and fork checks.
*/
void leaf_do_pending_checks(void){
int rid;
for(rid=bag_first(&needToCheck); rid; rid=bag_next(&needToCheck,rid)){
leaf_check(rid);
}
for(rid=bag_first(&needToCheck); rid; rid=bag_next(&needToCheck,rid)){
fork_check(rid);
}
bag_clear(&needToCheck);
}
|
Changes to src/main.c.
| ︙ | ︙ | |||
172 173 174 175 176 177 178 179 180 181 182 183 184 185 | FILE *httpIn; /* Accept HTTP input from here */ FILE *httpOut; /* Send HTTP output here */ int xlinkClusterOnly; /* Set when cloning. Only process clusters */ int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ int *aCommitFile; /* Array of files to be committed */ int markPrivate; /* All new artifacts are private if true */ int clockSkewSeen; /* True if clocks on client and server out of sync */ int wikiFlags; /* Wiki conversion flags applied to %W */ char isHTTP; /* True if server/CGI modes, else assume CLI. */ char javascriptHyperlink; /* If true, set href= using script, not HTML */ Blob httpHeader; /* Complete text of the HTTP request header */ UrlData url; /* Information about current URL */ const char *zLogin; /* Login name. NULL or "" if not logged in. */ const char *zSSLIdentity; /* Value of --ssl-identity option, filename of | > | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | FILE *httpIn; /* Accept HTTP input from here */ FILE *httpOut; /* Send HTTP output here */ int xlinkClusterOnly; /* Set when cloning. Only process clusters */ int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ int *aCommitFile; /* Array of files to be committed */ int markPrivate; /* All new artifacts are private if true */ int clockSkewSeen; /* True if clocks on client and server out of sync */ int forkSeen; /* True if an unhandled fork was seen during sync */ int wikiFlags; /* Wiki conversion flags applied to %W */ char isHTTP; /* True if server/CGI modes, else assume CLI. */ char javascriptHyperlink; /* If true, set href= using script, not HTML */ Blob httpHeader; /* Complete text of the HTTP request header */ UrlData url; /* Information about current URL */ const char *zLogin; /* Login name. NULL or "" if not logged in. */ const char *zSSLIdentity; /* Value of --ssl-identity option, filename of |
| ︙ | ︙ |
Changes to src/merge.c.
| ︙ | ︙ | |||
55 56 57 58 59 60 61 62 | db_finalize(&q); } /* Pick the most recent leaf that is (1) not equal to vid and (2) ** has not already been merged into vid and (3) the leaf is not ** closed and (4) the leaf is in the same branch as vid. */ | > > | > > > | > > | > > > > | > > > | > > > > > > > | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
db_finalize(&q);
}
/* Pick the most recent leaf that is (1) not equal to vid and (2)
** has not already been merged into vid and (3) the leaf is not
** closed and (4) the leaf is in the same branch as vid.
**
** Set vmergeFlag to control whether the vmerge table is checked.
*/
int fossil_find_nearest_fork(int vid, int vmergeFlag){
Blob sql;
Stmt q;
int rid = 0;
blob_zero(&sql);
blob_append_sql(&sql,
"SELECT leaf.rid"
" FROM leaf, event"
" WHERE leaf.rid=event.objid"
" AND leaf.rid!=%d", /* Constraint (1) */
vid
);
if( vmergeFlag ){
blob_append_sql(&sql,
" AND leaf.rid NOT IN (SELECT merge FROM vmerge)" /* Constraint (2) */
);
}
blob_append_sql(&sql,
" AND NOT EXISTS(SELECT 1 FROM tagxref" /* Constraint (3) */
" WHERE rid=leaf.rid"
" AND tagid=%d"
" AND tagtype>0)"
" AND (SELECT value FROM tagxref" /* Constraint (4) */
" WHERE tagid=%d AND rid=%d AND tagtype>0) ="
" (SELECT value FROM tagxref"
" WHERE tagid=%d AND rid=leaf.rid AND tagtype>0)"
" ORDER BY event.mtime DESC LIMIT 1",
TAG_CLOSED, TAG_BRANCH, vid, TAG_BRANCH
);
db_prepare(&q, "%s", blob_sql_text(&sql));
blob_reset(&sql);
if( db_step(&q)==SQLITE_ROW ){
rid = db_column_int(&q, 0);
}
db_finalize(&q);
return rid;
}
/*
** COMMAND: merge
**
** Usage: %fossil merge ?OPTIONS? ?VERSION?
**
|
| ︙ | ︙ | |||
194 195 196 197 198 199 200 |
** the leaf is not closed and (4) the leaf is in the same branch
** as the current checkout.
*/
Stmt q;
if( pickFlag || backoutFlag || integrateFlag){
fossil_fatal("cannot use --backout, --cherrypick or --integrate with a fork merge");
}
| | | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
** the leaf is not closed and (4) the leaf is in the same branch
** as the current checkout.
*/
Stmt q;
if( pickFlag || backoutFlag || integrateFlag){
fossil_fatal("cannot use --backout, --cherrypick or --integrate with a fork merge");
}
mid = fossil_find_nearest_fork(vid, 1);
if( mid==0 ){
fossil_fatal("no unmerged forks of branch \"%s\"",
db_text(0, "SELECT value FROM tagxref"
" WHERE tagid=%d AND rid=%d AND tagtype>0",
TAG_BRANCH, vid)
);
}
|
| ︙ | ︙ |
Changes to src/xfer.c.
| ︙ | ︙ | |||
45 46 47 48 49 50 51 | int nFileSent; /* Number of files sent */ int nDeltaSent; /* Number of deltas sent */ int nFileRcvd; /* Number of files received */ int nDeltaRcvd; /* Number of deltas received */ int nDanglingFile; /* Number of dangling deltas received */ int mxSend; /* Stop sending "file" when pOut reaches this size */ int resync; /* Send igot cards for all holdings */ | < | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | int nFileSent; /* Number of files sent */ int nDeltaSent; /* Number of deltas sent */ int nFileRcvd; /* Number of files received */ int nDeltaRcvd; /* Number of deltas received */ int nDanglingFile; /* Number of dangling deltas received */ int mxSend; /* Stop sending "file" when pOut reaches this size */ int resync; /* Send igot cards for all holdings */ u8 syncPrivate; /* True to enable syncing private content */ u8 nextIsPrivate; /* If true, next "file" received is a private */ time_t maxTime; /* Time when this transfer should be finished */ }; /* |
| ︙ | ︙ | |||
201 202 203 204 205 206 207 |
blob_reset(&hash);
if( rid==0 ){
blob_appendf(&pXfer->err, "%s", g.zErrMsg);
blob_reset(&content);
}else{
if( !isPriv ) content_make_public(rid);
manifest_crosslink(rid, &content, MC_NO_ERRORS);
| < < < < | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
blob_reset(&hash);
if( rid==0 ){
blob_appendf(&pXfer->err, "%s", g.zErrMsg);
blob_reset(&content);
}else{
if( !isPriv ) content_make_public(rid);
manifest_crosslink(rid, &content, MC_NO_ERRORS);
}
assert( blob_is_reset(&content) );
remote_has(rid);
}
/*
** The aToken[0..nToken-1] blob array is a parse of a "cfile" line
|
| ︙ | ︙ | |||
281 282 283 284 285 286 287 |
srcid = 0;
pXfer->nFileRcvd++;
}
rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid,
szC, isPriv);
Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]),
blob_size(&pXfer->aToken[1]));
| < < < < | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
srcid = 0;
pXfer->nFileRcvd++;
}
rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid,
szC, isPriv);
Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]),
blob_size(&pXfer->aToken[1]));
remote_has(rid);
blob_reset(&content);
}
/*
** Try to send a file as a delta against its parent.
** If successful, return the number of bytes in the delta.
|
| ︙ | ︙ | |||
931 932 933 934 935 936 937 |
** message has been uncompressed and placed in the g.cgiIn blob.
** Process this message and form an appropriate reply.
*/
void page_xfer(void){
int isPull = 0;
int isPush = 0;
int nErr = 0;
| < | 922 923 924 925 926 927 928 929 930 931 932 933 934 935 |
** message has been uncompressed and placed in the g.cgiIn blob.
** Process this message and form an appropriate reply.
*/
void page_xfer(void){
int isPull = 0;
int isPush = 0;
int nErr = 0;
Xfer xfer;
int deltaFlag = 0;
int isClone = 0;
int nGimme = 0;
int size;
int recvConfig = 0;
char *zNow;
|
| ︙ | ︙ | |||
986 987 988 989 990 991 992 |
}
zScript = xfer_push_code();
if( zScript ){ /* NOTE: Are TH1 transfer hooks enabled? */
pzUuidList = &zUuidList;
pnUuidList = &nUuidList;
}
while( blob_line(xfer.pIn, &xfer.line) ){
| < < < < | 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 |
}
zScript = xfer_push_code();
if( zScript ){ /* NOTE: Are TH1 transfer hooks enabled? */
pzUuidList = &zUuidList;
pnUuidList = &nUuidList;
}
while( blob_line(xfer.pIn, &xfer.line) ){
if( blob_buffer(&xfer.line)[0]=='#' ) continue;
if( blob_size(&xfer.line)==0 ) continue;
xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));
/* file UUID SIZE \n CONTENT
** file UUID DELTASRC SIZE \n CONTENT
**
** Accept a file from the client.
*/
if( blob_eq(&xfer.aToken[0], "file") ){
if( !isPush ){
cgi_reset_content();
@ error not\sauthorized\sto\swrite
nErr++;
break;
}
xfer_accept_file(&xfer, 0, pzUuidList, pnUuidList);
if( blob_size(&xfer.err) ){
cgi_reset_content();
@ error %T(blob_str(&xfer.err))
nErr++;
break;
}
}else
|
| ︙ | ︙ | |||
1028 1029 1030 1031 1032 1033 1034 |
if( !isPush ){
cgi_reset_content();
@ error not\sauthorized\sto\swrite
nErr++;
break;
}
xfer_accept_compressed_file(&xfer, 0, pzUuidList, pnUuidList);
| < < < | 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 |
if( !isPush ){
cgi_reset_content();
@ error not\sauthorized\sto\swrite
nErr++;
break;
}
xfer_accept_compressed_file(&xfer, 0, pzUuidList, pnUuidList);
if( blob_size(&xfer.err) ){
cgi_reset_content();
@ error %T(blob_str(&xfer.err))
nErr++;
break;
}
}else
|
| ︙ | ︙ | |||
1313 1314 1315 1316 1317 1318 1319 |
{
cgi_reset_content();
@ error bad\scommand:\s%F(blob_str(&xfer.line))
}
blobarray_reset(xfer.aToken, xfer.nToken);
blob_reset(&xfer.line);
}
| < < < | 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 |
{
cgi_reset_content();
@ error bad\scommand:\s%F(blob_str(&xfer.line))
}
blobarray_reset(xfer.aToken, xfer.nToken);
blob_reset(&xfer.line);
}
if( isPush ){
if( rc==TH_OK ){
rc = xfer_run_script(zScript, zUuidList, 1);
if( rc==TH_ERROR ){
cgi_reset_content();
@ error push\sscript\sfailed:\s%F(g.zErrMsg)
nErr++;
|
| ︙ | ︙ | |||
1454 1455 1456 1457 1458 1459 1460 |
Xfer xfer; /* Transfer data */
int pctDone; /* Percentage done with a message */
int lastPctDone = -1; /* Last displayed pctDone */
double rArrivalTime; /* Time at which a message arrived */
const char *zSCode = db_get("server-code", "x");
const char *zPCode = db_get("project-code", 0);
int nErr = 0; /* Number of errors */
| < > | 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 |
Xfer xfer; /* Transfer data */
int pctDone; /* Percentage done with a message */
int lastPctDone = -1; /* Last displayed pctDone */
double rArrivalTime; /* Time at which a message arrived */
const char *zSCode = db_get("server-code", "x");
const char *zPCode = db_get("project-code", 0);
int nErr = 0; /* Number of errors */
int nRoundtrip= 0; /* Number of HTTP requests */
int nArtifactSent = 0; /* Total artifacts sent */
int nArtifactRcvd = 0; /* Total artifacts received */
const char *zOpType = 0;/* Push, Pull, Sync, Clone */
double rSkew = 0.0; /* Maximum time skew */
if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0
&& configRcvMask==0 && configSendMask==0 ) return 0;
transport_stats(0, 0, 1);
socket_global_init();
memset(&xfer, 0, sizeof(xfer));
xfer.pIn = &recv;
xfer.pOut = &send;
xfer.mxSend = db_get_int("max-upload", 250000);
xfer.maxTime = -1;
g.forkSeen = 0;
if( syncFlags & SYNC_PRIVATE ){
g.perm.Private = 1;
xfer.syncPrivate = 1;
}
blobarray_zero(xfer.aToken, count(xfer.aToken));
blob_zero(&send);
|
| ︙ | ︙ | |||
1670 1671 1672 1673 1674 1675 1676 |
if( rDiff*24.0*3600.0 >= -(blob_size(&recv)/5000.0 + 20) ) rDiff = 0.0;
if( fossil_fabs(rDiff)>fossil_fabs(rSkew) ) rSkew = rDiff;
}
nCardRcvd++;
continue;
}
xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));
| < < < < < < < | 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 |
if( rDiff*24.0*3600.0 >= -(blob_size(&recv)/5000.0 + 20) ) rDiff = 0.0;
if( fossil_fabs(rDiff)>fossil_fabs(rSkew) ) rSkew = rDiff;
}
nCardRcvd++;
continue;
}
xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));
nCardRcvd++;
if( (syncFlags & SYNC_VERBOSE)!=0 && recv.nUsed>0 ){
pctDone = (recv.iCursor*100)/recv.nUsed;
if( pctDone!=lastPctDone ){
fossil_print("\rprocessed: %d%% ", pctDone);
lastPctDone = pctDone;
fflush(stdout);
}
}
/* file UUID SIZE \n CONTENT
** file UUID DELTASRC SIZE \n CONTENT
**
** Receive a file transmitted from the server.
*/
if( blob_eq(&xfer.aToken[0],"file") ){
xfer_accept_file(&xfer, (syncFlags & SYNC_CLONE)!=0, 0, 0);
nArtifactRcvd++;
}else
/* cfile UUID USIZE CSIZE \n CONTENT
** cfile UUID DELTASRC USIZE CSIZE \n CONTENT
**
** Receive a compressed file transmitted from the server.
*/
if( blob_eq(&xfer.aToken[0],"cfile") ){
xfer_accept_compressed_file(&xfer, (syncFlags & SYNC_CLONE)!=0, 0, 0);
nArtifactRcvd++;
}else
/* gimme UUID
**
** Server is requesting a file. If the file is a manifest, assume
** that the server will also want to know all of the content files
|
| ︙ | ︙ | |||
1976 1977 1978 1979 1980 1981 1982 |
manifest_crosslink_end(MC_PERMIT_HOOKS);
}else{
manifest_crosslink_end(MC_PERMIT_HOOKS);
content_enable_dephantomize(1);
}
db_end_transaction(0);
};
| < < < | 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 |
manifest_crosslink_end(MC_PERMIT_HOOKS);
}else{
manifest_crosslink_end(MC_PERMIT_HOOKS);
content_enable_dephantomize(1);
}
db_end_transaction(0);
};
transport_stats(&nSent, &nRcvd, 1);
if( (rSkew*24.0*3600.0) > 10.0 ){
fossil_warning("*** time skew *** server is fast by %s",
db_timespan_name(rSkew));
g.clockSkewSeen = 1;
}else if( rSkew*24.0*3600.0 < -10.0 ){
fossil_warning("*** time skew *** server is slow by %s",
|
| ︙ | ︙ | |||
2002 2003 2004 2005 2006 2007 2008 2009 2010 |
transport_global_shutdown(&g.url);
if( nErr && go==2 ){
db_multi_exec("DROP TABLE onremote");
manifest_crosslink_end(MC_PERMIT_HOOKS);
content_enable_dephantomize(1);
db_end_transaction(0);
}
return nErr;
}
| > > > | 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 |
transport_global_shutdown(&g.url);
if( nErr && go==2 ){
db_multi_exec("DROP TABLE onremote");
manifest_crosslink_end(MC_PERMIT_HOOKS);
content_enable_dephantomize(1);
db_end_transaction(0);
}
if( (syncFlags & SYNC_CLONE)==0 && g.forkSeen ){
fossil_warning("***** WARNING: a fork has occurred *****");
}
return nErr;
}
|