Fossil SCM
Warn the client that pushes content which generates a fork on the server.
Commit
6b410f914ef5be53f7a2afec6af893083e213eaa
Parent
5a12e8c3b68fc90…
2 files changed
+17
+14
+17
| --- src/leaf.c | ||
| +++ src/leaf.c | ||
| @@ -73,10 +73,27 @@ | ||
| 73 | 73 | } |
| 74 | 74 | db_reset(&q); |
| 75 | 75 | return nNonBranch; |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | +/* | |
| 79 | +** Return the primary parent pid given a child rid | |
| 80 | +*/ | |
| 81 | +int primary_parent_pid_from_rid(int rid){ | |
| 82 | + static Stmt q; | |
| 83 | + int pid = -1; | |
| 84 | + | |
| 85 | + db_static_prepare(&q, | |
| 86 | + "SELECT pid FROM plink WHERE cid=:rid AND pid>0 AND isprim" | |
| 87 | + ); | |
| 88 | + db_bind_int(&q, ":rid", rid); | |
| 89 | + if( db_step(&q)==SQLITE_ROW ){ | |
| 90 | + pid = db_column_int(&q, 0); | |
| 91 | + } | |
| 92 | + db_reset(&q); | |
| 93 | + return pid; | |
| 94 | +} | |
| 78 | 95 | |
| 79 | 96 | /* |
| 80 | 97 | ** Recompute the entire LEAF table. |
| 81 | 98 | ** |
| 82 | 99 | ** This can be expensive (5 seconds or so) for a really large repository. |
| 83 | 100 |
| --- src/leaf.c | |
| +++ src/leaf.c | |
| @@ -73,10 +73,27 @@ | |
| 73 | } |
| 74 | db_reset(&q); |
| 75 | return nNonBranch; |
| 76 | } |
| 77 | |
| 78 | |
| 79 | /* |
| 80 | ** Recompute the entire LEAF table. |
| 81 | ** |
| 82 | ** This can be expensive (5 seconds or so) for a really large repository. |
| 83 |
| --- src/leaf.c | |
| +++ src/leaf.c | |
| @@ -73,10 +73,27 @@ | |
| 73 | } |
| 74 | db_reset(&q); |
| 75 | return nNonBranch; |
| 76 | } |
| 77 | |
| 78 | /* |
| 79 | ** Return the primary parent pid given a child rid |
| 80 | */ |
| 81 | int primary_parent_pid_from_rid(int rid){ |
| 82 | static Stmt q; |
| 83 | int pid = -1; |
| 84 | |
| 85 | db_static_prepare(&q, |
| 86 | "SELECT pid FROM plink WHERE cid=:rid AND pid>0 AND isprim" |
| 87 | ); |
| 88 | db_bind_int(&q, ":rid", rid); |
| 89 | if( db_step(&q)==SQLITE_ROW ){ |
| 90 | pid = db_column_int(&q, 0); |
| 91 | } |
| 92 | db_reset(&q); |
| 93 | return pid; |
| 94 | } |
| 95 | |
| 96 | /* |
| 97 | ** Recompute the entire LEAF table. |
| 98 | ** |
| 99 | ** This can be expensive (5 seconds or so) for a really large repository. |
| 100 |
+14
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -47,10 +47,11 @@ | ||
| 47 | 47 | int nFileRcvd; /* Number of files received */ |
| 48 | 48 | int nDeltaRcvd; /* Number of deltas received */ |
| 49 | 49 | int nDanglingFile; /* Number of dangling deltas received */ |
| 50 | 50 | int mxSend; /* Stop sending "file" when pOut reaches this size */ |
| 51 | 51 | int resync; /* Send igot cards for all holdings */ |
| 52 | + int fHasFork; /* True if a fork has been seen */ | |
| 52 | 53 | u8 syncPrivate; /* True to enable syncing private content */ |
| 53 | 54 | u8 nextIsPrivate; /* If true, next "file" received is a private */ |
| 54 | 55 | time_t maxTime; /* Time when this transfer should be finished */ |
| 55 | 56 | }; |
| 56 | 57 | |
| @@ -202,10 +203,13 @@ | ||
| 202 | 203 | blob_appendf(&pXfer->err, "%s", g.zErrMsg); |
| 203 | 204 | blob_reset(&content); |
| 204 | 205 | }else{ |
| 205 | 206 | if( !isPriv ) content_make_public(rid); |
| 206 | 207 | manifest_crosslink(rid, &content, MC_NO_ERRORS); |
| 208 | + if( count_nonbranch_children(primary_parent_pid_from_rid(rid))>1 ){ | |
| 209 | + pXfer->fHasFork = 1; | |
| 210 | + } | |
| 207 | 211 | } |
| 208 | 212 | assert( blob_is_reset(&content) ); |
| 209 | 213 | remote_has(rid); |
| 210 | 214 | } |
| 211 | 215 | |
| @@ -277,10 +281,13 @@ | ||
| 277 | 281 | } |
| 278 | 282 | rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid, |
| 279 | 283 | szC, isPriv); |
| 280 | 284 | Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]), |
| 281 | 285 | blob_size(&pXfer->aToken[1])); |
| 286 | + if( count_nonbranch_children(primary_parent_pid_from_rid(rid))>1 ){ | |
| 287 | + pXfer->fHasFork = 1; | |
| 288 | + } | |
| 282 | 289 | remote_has(rid); |
| 283 | 290 | blob_reset(&content); |
| 284 | 291 | } |
| 285 | 292 | |
| 286 | 293 | /* |
| @@ -977,10 +984,11 @@ | ||
| 977 | 984 | if( zScript ){ /* NOTE: Are TH1 transfer hooks enabled? */ |
| 978 | 985 | pzUuidList = &zUuidList; |
| 979 | 986 | pnUuidList = &nUuidList; |
| 980 | 987 | } |
| 981 | 988 | while( blob_line(xfer.pIn, &xfer.line) ){ |
| 989 | + xfer.fHasFork = 0; | |
| 982 | 990 | if( blob_buffer(&xfer.line)[0]=='#' ) continue; |
| 983 | 991 | if( blob_size(&xfer.line)==0 ) continue; |
| 984 | 992 | xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); |
| 985 | 993 | |
| 986 | 994 | /* file UUID SIZE \n CONTENT |
| @@ -994,10 +1002,13 @@ | ||
| 994 | 1002 | @ error not\sauthorized\sto\swrite |
| 995 | 1003 | nErr++; |
| 996 | 1004 | break; |
| 997 | 1005 | } |
| 998 | 1006 | xfer_accept_file(&xfer, 0, pzUuidList, pnUuidList); |
| 1007 | + if( xfer.fHasFork ){ | |
| 1008 | + @ message ******\sWARNING:\sa\sfork\shas\soccurred\s****** | |
| 1009 | + } | |
| 999 | 1010 | if( blob_size(&xfer.err) ){ |
| 1000 | 1011 | cgi_reset_content(); |
| 1001 | 1012 | @ error %T(blob_str(&xfer.err)) |
| 1002 | 1013 | nErr++; |
| 1003 | 1014 | break; |
| @@ -1015,10 +1026,13 @@ | ||
| 1015 | 1026 | @ error not\sauthorized\sto\swrite |
| 1016 | 1027 | nErr++; |
| 1017 | 1028 | break; |
| 1018 | 1029 | } |
| 1019 | 1030 | xfer_accept_compressed_file(&xfer, pzUuidList, pnUuidList); |
| 1031 | + if( xfer.fHasFork ){ | |
| 1032 | + @ message ******\sWARNING:\sa\sfork\shas\soccurred\s****** | |
| 1033 | + } | |
| 1020 | 1034 | if( blob_size(&xfer.err) ){ |
| 1021 | 1035 | cgi_reset_content(); |
| 1022 | 1036 | @ error %T(blob_str(&xfer.err)) |
| 1023 | 1037 | nErr++; |
| 1024 | 1038 | break; |
| 1025 | 1039 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -47,10 +47,11 @@ | |
| 47 | int nFileRcvd; /* Number of files received */ |
| 48 | int nDeltaRcvd; /* Number of deltas received */ |
| 49 | int nDanglingFile; /* Number of dangling deltas received */ |
| 50 | int mxSend; /* Stop sending "file" when pOut reaches this size */ |
| 51 | int resync; /* Send igot cards for all holdings */ |
| 52 | u8 syncPrivate; /* True to enable syncing private content */ |
| 53 | u8 nextIsPrivate; /* If true, next "file" received is a private */ |
| 54 | time_t maxTime; /* Time when this transfer should be finished */ |
| 55 | }; |
| 56 | |
| @@ -202,10 +203,13 @@ | |
| 202 | blob_appendf(&pXfer->err, "%s", g.zErrMsg); |
| 203 | blob_reset(&content); |
| 204 | }else{ |
| 205 | if( !isPriv ) content_make_public(rid); |
| 206 | manifest_crosslink(rid, &content, MC_NO_ERRORS); |
| 207 | } |
| 208 | assert( blob_is_reset(&content) ); |
| 209 | remote_has(rid); |
| 210 | } |
| 211 | |
| @@ -277,10 +281,13 @@ | |
| 277 | } |
| 278 | rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid, |
| 279 | szC, isPriv); |
| 280 | Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]), |
| 281 | blob_size(&pXfer->aToken[1])); |
| 282 | remote_has(rid); |
| 283 | blob_reset(&content); |
| 284 | } |
| 285 | |
| 286 | /* |
| @@ -977,10 +984,11 @@ | |
| 977 | if( zScript ){ /* NOTE: Are TH1 transfer hooks enabled? */ |
| 978 | pzUuidList = &zUuidList; |
| 979 | pnUuidList = &nUuidList; |
| 980 | } |
| 981 | while( blob_line(xfer.pIn, &xfer.line) ){ |
| 982 | if( blob_buffer(&xfer.line)[0]=='#' ) continue; |
| 983 | if( blob_size(&xfer.line)==0 ) continue; |
| 984 | xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); |
| 985 | |
| 986 | /* file UUID SIZE \n CONTENT |
| @@ -994,10 +1002,13 @@ | |
| 994 | @ error not\sauthorized\sto\swrite |
| 995 | nErr++; |
| 996 | break; |
| 997 | } |
| 998 | xfer_accept_file(&xfer, 0, pzUuidList, pnUuidList); |
| 999 | if( blob_size(&xfer.err) ){ |
| 1000 | cgi_reset_content(); |
| 1001 | @ error %T(blob_str(&xfer.err)) |
| 1002 | nErr++; |
| 1003 | break; |
| @@ -1015,10 +1026,13 @@ | |
| 1015 | @ error not\sauthorized\sto\swrite |
| 1016 | nErr++; |
| 1017 | break; |
| 1018 | } |
| 1019 | xfer_accept_compressed_file(&xfer, pzUuidList, pnUuidList); |
| 1020 | if( blob_size(&xfer.err) ){ |
| 1021 | cgi_reset_content(); |
| 1022 | @ error %T(blob_str(&xfer.err)) |
| 1023 | nErr++; |
| 1024 | break; |
| 1025 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -47,10 +47,11 @@ | |
| 47 | int nFileRcvd; /* Number of files received */ |
| 48 | int nDeltaRcvd; /* Number of deltas received */ |
| 49 | int nDanglingFile; /* Number of dangling deltas received */ |
| 50 | int mxSend; /* Stop sending "file" when pOut reaches this size */ |
| 51 | int resync; /* Send igot cards for all holdings */ |
| 52 | int fHasFork; /* True if a fork has been seen */ |
| 53 | u8 syncPrivate; /* True to enable syncing private content */ |
| 54 | u8 nextIsPrivate; /* If true, next "file" received is a private */ |
| 55 | time_t maxTime; /* Time when this transfer should be finished */ |
| 56 | }; |
| 57 | |
| @@ -202,10 +203,13 @@ | |
| 203 | blob_appendf(&pXfer->err, "%s", g.zErrMsg); |
| 204 | blob_reset(&content); |
| 205 | }else{ |
| 206 | if( !isPriv ) content_make_public(rid); |
| 207 | manifest_crosslink(rid, &content, MC_NO_ERRORS); |
| 208 | if( count_nonbranch_children(primary_parent_pid_from_rid(rid))>1 ){ |
| 209 | pXfer->fHasFork = 1; |
| 210 | } |
| 211 | } |
| 212 | assert( blob_is_reset(&content) ); |
| 213 | remote_has(rid); |
| 214 | } |
| 215 | |
| @@ -277,10 +281,13 @@ | |
| 281 | } |
| 282 | rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid, |
| 283 | szC, isPriv); |
| 284 | Th_AppendToList(pzUuidList, pnUuidList, blob_str(&pXfer->aToken[1]), |
| 285 | blob_size(&pXfer->aToken[1])); |
| 286 | if( count_nonbranch_children(primary_parent_pid_from_rid(rid))>1 ){ |
| 287 | pXfer->fHasFork = 1; |
| 288 | } |
| 289 | remote_has(rid); |
| 290 | blob_reset(&content); |
| 291 | } |
| 292 | |
| 293 | /* |
| @@ -977,10 +984,11 @@ | |
| 984 | if( zScript ){ /* NOTE: Are TH1 transfer hooks enabled? */ |
| 985 | pzUuidList = &zUuidList; |
| 986 | pnUuidList = &nUuidList; |
| 987 | } |
| 988 | while( blob_line(xfer.pIn, &xfer.line) ){ |
| 989 | xfer.fHasFork = 0; |
| 990 | if( blob_buffer(&xfer.line)[0]=='#' ) continue; |
| 991 | if( blob_size(&xfer.line)==0 ) continue; |
| 992 | xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); |
| 993 | |
| 994 | /* file UUID SIZE \n CONTENT |
| @@ -994,10 +1002,13 @@ | |
| 1002 | @ error not\sauthorized\sto\swrite |
| 1003 | nErr++; |
| 1004 | break; |
| 1005 | } |
| 1006 | xfer_accept_file(&xfer, 0, pzUuidList, pnUuidList); |
| 1007 | if( xfer.fHasFork ){ |
| 1008 | @ message ******\sWARNING:\sa\sfork\shas\soccurred\s****** |
| 1009 | } |
| 1010 | if( blob_size(&xfer.err) ){ |
| 1011 | cgi_reset_content(); |
| 1012 | @ error %T(blob_str(&xfer.err)) |
| 1013 | nErr++; |
| 1014 | break; |
| @@ -1015,10 +1026,13 @@ | |
| 1026 | @ error not\sauthorized\sto\swrite |
| 1027 | nErr++; |
| 1028 | break; |
| 1029 | } |
| 1030 | xfer_accept_compressed_file(&xfer, pzUuidList, pnUuidList); |
| 1031 | if( xfer.fHasFork ){ |
| 1032 | @ message ******\sWARNING:\sa\sfork\shas\soccurred\s****** |
| 1033 | } |
| 1034 | if( blob_size(&xfer.err) ){ |
| 1035 | cgi_reset_content(); |
| 1036 | @ error %T(blob_str(&xfer.err)) |
| 1037 | nErr++; |
| 1038 | break; |
| 1039 |