Fossil SCM
Prevent resuming a clone from a different server by preserving the remote server-code and comparing on resume. This is a crude heuristic to determine whether or not it is likely that the remote server still has the same rids. A better heuristic may be to probe the server for known rids that have been received (e.g. each clone seqno that is send by the server could be recorded and then probed with a pragma request by the client later on.
Commit
aa54ea41168c703cd51a524d563327885c70fcdfdaee09e7a699cb6cbd5c4257
Parent
63af8da3554e923…
2 files changed
+11
-1
+5
+11
-1
| --- src/clone.c | ||
| +++ src/clone.c | ||
| @@ -154,10 +154,11 @@ | ||
| 154 | 154 | int noOpen = find_option("no-open",0,0)!=0; |
| 155 | 155 | int allowNested = find_option("nested",0,0)!=0; /* Used by open */ |
| 156 | 156 | int nResumeSeqno = 0; /* Last seqno from which to resume clone */ |
| 157 | 157 | const char *zNewProjCode; /* New Project code obtained during clone */ |
| 158 | 158 | const char *zOldProjCode; /* Old project code stored in resuming clone */ |
| 159 | + const char *zCloneCode; /* server-code for the source of the clone */ | |
| 159 | 160 | const char *zRepo = 0; /* Name of the new local repository file */ |
| 160 | 161 | const char *zWorkDir = 0; /* Open in this directory, if not zero */ |
| 161 | 162 | |
| 162 | 163 | |
| 163 | 164 | /* Also clone private branches */ |
| @@ -241,11 +242,13 @@ | ||
| 241 | 242 | if( nResumeSeqno>1 ){ |
| 242 | 243 | db_open_repository(zRepo); |
| 243 | 244 | db_open_config(0,0); |
| 244 | 245 | db_begin_transaction(); |
| 245 | 246 | zOldProjCode = db_get("project-code",0); |
| 247 | + zCloneCode = db_get("aux-clone-code",0); | |
| 246 | 248 | if( zOldProjCode==0 ) fossil_fatal("project-id missing from repository"); |
| 249 | + if( zCloneCode==0 ) fossil_fatal("clone-code missing from repository"); | |
| 247 | 250 | fossil_print("Resuming clone of project-id %s\n",zOldProjCode); |
| 248 | 251 | db_create_default_users(1, zDefaultUser); |
| 249 | 252 | if( zDefaultUser ) g.zLogin = zDefaultUser; |
| 250 | 253 | user_select(); |
| 251 | 254 | }else{ |
| @@ -306,18 +309,25 @@ | ||
| 306 | 309 | && fossil_strcmp(zOldProjCode, zNewProjCode)!=0 ){ |
| 307 | 310 | fossil_fatal("project-id changed\nwas %s\nis %s" |
| 308 | 311 | "\nrolling back changes", |
| 309 | 312 | zOldProjCode, zNewProjCode); |
| 310 | 313 | } |
| 314 | + if( zCloneCode!=0 && zCloneCode[0]!=0 | |
| 315 | + && fossil_strcmp(zCloneCode, db_get("aux-clone-code",0))!=0 ){ | |
| 316 | + fossil_fatal("clone resume from different server not allowed"); | |
| 317 | + } | |
| 311 | 318 | } |
| 312 | 319 | if( nErr ){ |
| 313 | 320 | fossil_warning("server returned an error - clone incomplete"); |
| 314 | 321 | }else if( sync_interrupted()==1 ){ |
| 315 | 322 | fossil_warning("clone was interrupted"); |
| 316 | 323 | }else{ |
| 317 | 324 | db_unprotect(PROTECT_CONFIG); |
| 318 | - db_multi_exec("DELETE FROM config WHERE name = 'aux-clone-seqno';"); | |
| 325 | + db_multi_exec( | |
| 326 | + "DELETE FROM config WHERE name = 'aux-clone-seqno';" | |
| 327 | + "DELETE FROM config WHERE name = 'aux-clone-code';" | |
| 328 | + ); | |
| 319 | 329 | db_protect_pop(); |
| 320 | 330 | } |
| 321 | 331 | db_end_transaction(0); |
| 322 | 332 | db_close(1); |
| 323 | 333 | db_open_repository(zRepo); |
| 324 | 334 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -154,10 +154,11 @@ | |
| 154 | int noOpen = find_option("no-open",0,0)!=0; |
| 155 | int allowNested = find_option("nested",0,0)!=0; /* Used by open */ |
| 156 | int nResumeSeqno = 0; /* Last seqno from which to resume clone */ |
| 157 | const char *zNewProjCode; /* New Project code obtained during clone */ |
| 158 | const char *zOldProjCode; /* Old project code stored in resuming clone */ |
| 159 | const char *zRepo = 0; /* Name of the new local repository file */ |
| 160 | const char *zWorkDir = 0; /* Open in this directory, if not zero */ |
| 161 | |
| 162 | |
| 163 | /* Also clone private branches */ |
| @@ -241,11 +242,13 @@ | |
| 241 | if( nResumeSeqno>1 ){ |
| 242 | db_open_repository(zRepo); |
| 243 | db_open_config(0,0); |
| 244 | db_begin_transaction(); |
| 245 | zOldProjCode = db_get("project-code",0); |
| 246 | if( zOldProjCode==0 ) fossil_fatal("project-id missing from repository"); |
| 247 | fossil_print("Resuming clone of project-id %s\n",zOldProjCode); |
| 248 | db_create_default_users(1, zDefaultUser); |
| 249 | if( zDefaultUser ) g.zLogin = zDefaultUser; |
| 250 | user_select(); |
| 251 | }else{ |
| @@ -306,18 +309,25 @@ | |
| 306 | && fossil_strcmp(zOldProjCode, zNewProjCode)!=0 ){ |
| 307 | fossil_fatal("project-id changed\nwas %s\nis %s" |
| 308 | "\nrolling back changes", |
| 309 | zOldProjCode, zNewProjCode); |
| 310 | } |
| 311 | } |
| 312 | if( nErr ){ |
| 313 | fossil_warning("server returned an error - clone incomplete"); |
| 314 | }else if( sync_interrupted()==1 ){ |
| 315 | fossil_warning("clone was interrupted"); |
| 316 | }else{ |
| 317 | db_unprotect(PROTECT_CONFIG); |
| 318 | db_multi_exec("DELETE FROM config WHERE name = 'aux-clone-seqno';"); |
| 319 | db_protect_pop(); |
| 320 | } |
| 321 | db_end_transaction(0); |
| 322 | db_close(1); |
| 323 | db_open_repository(zRepo); |
| 324 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -154,10 +154,11 @@ | |
| 154 | int noOpen = find_option("no-open",0,0)!=0; |
| 155 | int allowNested = find_option("nested",0,0)!=0; /* Used by open */ |
| 156 | int nResumeSeqno = 0; /* Last seqno from which to resume clone */ |
| 157 | const char *zNewProjCode; /* New Project code obtained during clone */ |
| 158 | const char *zOldProjCode; /* Old project code stored in resuming clone */ |
| 159 | const char *zCloneCode; /* server-code for the source of the clone */ |
| 160 | const char *zRepo = 0; /* Name of the new local repository file */ |
| 161 | const char *zWorkDir = 0; /* Open in this directory, if not zero */ |
| 162 | |
| 163 | |
| 164 | /* Also clone private branches */ |
| @@ -241,11 +242,13 @@ | |
| 242 | if( nResumeSeqno>1 ){ |
| 243 | db_open_repository(zRepo); |
| 244 | db_open_config(0,0); |
| 245 | db_begin_transaction(); |
| 246 | zOldProjCode = db_get("project-code",0); |
| 247 | zCloneCode = db_get("aux-clone-code",0); |
| 248 | if( zOldProjCode==0 ) fossil_fatal("project-id missing from repository"); |
| 249 | if( zCloneCode==0 ) fossil_fatal("clone-code missing from repository"); |
| 250 | fossil_print("Resuming clone of project-id %s\n",zOldProjCode); |
| 251 | db_create_default_users(1, zDefaultUser); |
| 252 | if( zDefaultUser ) g.zLogin = zDefaultUser; |
| 253 | user_select(); |
| 254 | }else{ |
| @@ -306,18 +309,25 @@ | |
| 309 | && fossil_strcmp(zOldProjCode, zNewProjCode)!=0 ){ |
| 310 | fossil_fatal("project-id changed\nwas %s\nis %s" |
| 311 | "\nrolling back changes", |
| 312 | zOldProjCode, zNewProjCode); |
| 313 | } |
| 314 | if( zCloneCode!=0 && zCloneCode[0]!=0 |
| 315 | && fossil_strcmp(zCloneCode, db_get("aux-clone-code",0))!=0 ){ |
| 316 | fossil_fatal("clone resume from different server not allowed"); |
| 317 | } |
| 318 | } |
| 319 | if( nErr ){ |
| 320 | fossil_warning("server returned an error - clone incomplete"); |
| 321 | }else if( sync_interrupted()==1 ){ |
| 322 | fossil_warning("clone was interrupted"); |
| 323 | }else{ |
| 324 | db_unprotect(PROTECT_CONFIG); |
| 325 | db_multi_exec( |
| 326 | "DELETE FROM config WHERE name = 'aux-clone-seqno';" |
| 327 | "DELETE FROM config WHERE name = 'aux-clone-code';" |
| 328 | ); |
| 329 | db_protect_pop(); |
| 330 | } |
| 331 | db_end_transaction(0); |
| 332 | db_close(1); |
| 333 | db_open_repository(zRepo); |
| 334 |
+5
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -1989,10 +1989,11 @@ | ||
| 1989 | 1989 | int pctDone; /* Percentage done with a message */ |
| 1990 | 1990 | int lastPctDone = -1; /* Last displayed pctDone */ |
| 1991 | 1991 | double rArrivalTime; /* Time at which a message arrived */ |
| 1992 | 1992 | const char *zSCode = db_get("server-code", "x"); |
| 1993 | 1993 | const char *zPCode = db_get("project-code", 0); |
| 1994 | + const char *zCCode = db_get("aux-clone-code",0); | |
| 1994 | 1995 | int nErr = 0; /* Number of errors */ |
| 1995 | 1996 | int nRoundtrip= 0; /* Number of HTTP requests */ |
| 1996 | 1997 | int nArtifactSent = 0; /* Total artifacts sent */ |
| 1997 | 1998 | int nArtifactRcvd = 0; /* Total artifacts received */ |
| 1998 | 1999 | int nPriorArtifact = 0; /* Artifacts received on prior round-trips */ |
| @@ -2580,10 +2581,14 @@ | ||
| 2580 | 2581 | ){ |
| 2581 | 2582 | if( zPCode==0 ){ |
| 2582 | 2583 | zPCode = mprintf("%b", &xfer.aToken[2]); |
| 2583 | 2584 | db_set("project-code", zPCode, 0); |
| 2584 | 2585 | } |
| 2586 | + if( blob_is_hname(&xfer.aToken[1]) ){ | |
| 2587 | + zCCode = mprintf("%b", &xfer.aToken[1]); | |
| 2588 | + db_set("aux-clone-code", zCCode, 0); | |
| 2589 | + } | |
| 2585 | 2590 | if( cloneSeqno>0 ) blob_appendf(&send, "clone 3 %d\n", cloneSeqno); |
| 2586 | 2591 | nCardSent++; |
| 2587 | 2592 | }else |
| 2588 | 2593 | |
| 2589 | 2594 | /* config NAME SIZE \n CONTENT |
| 2590 | 2595 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -1989,10 +1989,11 @@ | |
| 1989 | int pctDone; /* Percentage done with a message */ |
| 1990 | int lastPctDone = -1; /* Last displayed pctDone */ |
| 1991 | double rArrivalTime; /* Time at which a message arrived */ |
| 1992 | const char *zSCode = db_get("server-code", "x"); |
| 1993 | const char *zPCode = db_get("project-code", 0); |
| 1994 | int nErr = 0; /* Number of errors */ |
| 1995 | int nRoundtrip= 0; /* Number of HTTP requests */ |
| 1996 | int nArtifactSent = 0; /* Total artifacts sent */ |
| 1997 | int nArtifactRcvd = 0; /* Total artifacts received */ |
| 1998 | int nPriorArtifact = 0; /* Artifacts received on prior round-trips */ |
| @@ -2580,10 +2581,14 @@ | |
| 2580 | ){ |
| 2581 | if( zPCode==0 ){ |
| 2582 | zPCode = mprintf("%b", &xfer.aToken[2]); |
| 2583 | db_set("project-code", zPCode, 0); |
| 2584 | } |
| 2585 | if( cloneSeqno>0 ) blob_appendf(&send, "clone 3 %d\n", cloneSeqno); |
| 2586 | nCardSent++; |
| 2587 | }else |
| 2588 | |
| 2589 | /* config NAME SIZE \n CONTENT |
| 2590 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -1989,10 +1989,11 @@ | |
| 1989 | int pctDone; /* Percentage done with a message */ |
| 1990 | int lastPctDone = -1; /* Last displayed pctDone */ |
| 1991 | double rArrivalTime; /* Time at which a message arrived */ |
| 1992 | const char *zSCode = db_get("server-code", "x"); |
| 1993 | const char *zPCode = db_get("project-code", 0); |
| 1994 | const char *zCCode = db_get("aux-clone-code",0); |
| 1995 | int nErr = 0; /* Number of errors */ |
| 1996 | int nRoundtrip= 0; /* Number of HTTP requests */ |
| 1997 | int nArtifactSent = 0; /* Total artifacts sent */ |
| 1998 | int nArtifactRcvd = 0; /* Total artifacts received */ |
| 1999 | int nPriorArtifact = 0; /* Artifacts received on prior round-trips */ |
| @@ -2580,10 +2581,14 @@ | |
| 2581 | ){ |
| 2582 | if( zPCode==0 ){ |
| 2583 | zPCode = mprintf("%b", &xfer.aToken[2]); |
| 2584 | db_set("project-code", zPCode, 0); |
| 2585 | } |
| 2586 | if( blob_is_hname(&xfer.aToken[1]) ){ |
| 2587 | zCCode = mprintf("%b", &xfer.aToken[1]); |
| 2588 | db_set("aux-clone-code", zCCode, 0); |
| 2589 | } |
| 2590 | if( cloneSeqno>0 ) blob_appendf(&send, "clone 3 %d\n", cloneSeqno); |
| 2591 | nCardSent++; |
| 2592 | }else |
| 2593 | |
| 2594 | /* config NAME SIZE \n CONTENT |
| 2595 |