Fossil SCM
Catch SIGINT during sync so that when pressing ctrl-c during a clone of a large repository it doesn't dispose of all the progress that was made during, thus enabling resume from an user interrupt. When the handler returns, the last sync will complete and then exit the loop.
Commit
ad2e148541fe0716b534eab267cce993cb78e564b40c192b22d921143ffc3708
Parent
5d12d42680fef64…
2 files changed
+21
-7
+18
+21
-7
| --- src/clone.c | ||
| +++ src/clone.c | ||
| @@ -18,10 +18,11 @@ | ||
| 18 | 18 | ** This file contains code used to clone a repository |
| 19 | 19 | */ |
| 20 | 20 | #include "config.h" |
| 21 | 21 | #include "clone.h" |
| 22 | 22 | #include <assert.h> |
| 23 | +#include <signal.h> | |
| 23 | 24 | |
| 24 | 25 | /* |
| 25 | 26 | ** If there are public BLOBs that deltas from private BLOBs, then |
| 26 | 27 | ** undeltify the public BLOBs so that the private BLOBs may be safely |
| 27 | 28 | ** deleted. |
| @@ -282,33 +283,46 @@ | ||
| 282 | 283 | db_protect_pop(); |
| 283 | 284 | url_enable_proxy(0); |
| 284 | 285 | clone_ssh_db_set_options(); |
| 285 | 286 | url_get_password_if_needed(); |
| 286 | 287 | g.xlinkClusterOnly = 1; |
| 287 | - while( nResumes++<3 && (nErr = client_sync(syncFlags,CONFIGSET_ALL,0,0)) ){ | |
| 288 | - fossil_warning("cloning encountered errors, trying again."); | |
| 289 | - sqlite3_sleep(500); | |
| 288 | + while( nResumes++<3 && sync_interrupted()==0 | |
| 289 | + && (nErr = client_sync(syncFlags,CONFIGSET_ALL,0,0)) | |
| 290 | + ){ | |
| 291 | + if( sync_interrupted()!=0 ){ | |
| 292 | + fossil_warning("cloning encountered errors, trying again."); | |
| 293 | + sqlite3_sleep(500); | |
| 294 | + } | |
| 290 | 295 | } |
| 291 | 296 | g.xlinkClusterOnly = 0; |
| 292 | 297 | verify_cancel(); |
| 293 | 298 | if( nErr ){ |
| 294 | 299 | fossil_warning("server returned an error - clone incomplete"); |
| 300 | + }else if( sync_interrupted()==1 ){ | |
| 301 | + fossil_warning("clone was interrupted"); | |
| 295 | 302 | }else{ |
| 296 | 303 | db_unprotect(PROTECT_CONFIG); |
| 297 | 304 | db_multi_exec("DELETE FROM config WHERE name = 'aux-clone-seqno';"); |
| 298 | 305 | db_protect_pop(); |
| 299 | 306 | } |
| 300 | 307 | db_end_transaction(0); |
| 301 | 308 | db_close(1); |
| 302 | 309 | db_open_repository(zRepo); |
| 310 | +#if !defined(_WIN32) | |
| 311 | + signal(SIGINT, SIG_DFL); | |
| 312 | +#endif | |
| 303 | 313 | } |
| 304 | 314 | db_begin_transaction(); |
| 305 | 315 | if( db_exists("SELECT 1 FROM delta WHERE srcId IN phantom") ){ |
| 306 | - fossil_warning("there are unresolved deltas -" | |
| 307 | - " the clone is probably incomplete and unusable.\n" | |
| 308 | - "It may be possible to resume the clone by running the" | |
| 309 | - " same command."); | |
| 316 | + if( db_get_int("aux-clone-seqno",0)==0 ){ | |
| 317 | + fossil_fatal("there are unresolved deltas -" | |
| 318 | + " the clone is probabaly incomplete and unusable."); | |
| 319 | + } | |
| 320 | + } | |
| 321 | + if( db_get_int("aux-clone-seqno",0)>0 ){ | |
| 322 | + fossil_warning("Clone incomplete - it may be possible to resume the" | |
| 323 | + " clone by running the same command again."); | |
| 310 | 324 | } |
| 311 | 325 | fossil_print("Rebuilding repository meta-data...\n"); |
| 312 | 326 | rebuild_db(1, 0); |
| 313 | 327 | if( !noCompress ){ |
| 314 | 328 | int nDelta = 0; |
| 315 | 329 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -18,10 +18,11 @@ | |
| 18 | ** This file contains code used to clone a repository |
| 19 | */ |
| 20 | #include "config.h" |
| 21 | #include "clone.h" |
| 22 | #include <assert.h> |
| 23 | |
| 24 | /* |
| 25 | ** If there are public BLOBs that deltas from private BLOBs, then |
| 26 | ** undeltify the public BLOBs so that the private BLOBs may be safely |
| 27 | ** deleted. |
| @@ -282,33 +283,46 @@ | |
| 282 | db_protect_pop(); |
| 283 | url_enable_proxy(0); |
| 284 | clone_ssh_db_set_options(); |
| 285 | url_get_password_if_needed(); |
| 286 | g.xlinkClusterOnly = 1; |
| 287 | while( nResumes++<3 && (nErr = client_sync(syncFlags,CONFIGSET_ALL,0,0)) ){ |
| 288 | fossil_warning("cloning encountered errors, trying again."); |
| 289 | sqlite3_sleep(500); |
| 290 | } |
| 291 | g.xlinkClusterOnly = 0; |
| 292 | verify_cancel(); |
| 293 | if( nErr ){ |
| 294 | fossil_warning("server returned an error - clone incomplete"); |
| 295 | }else{ |
| 296 | db_unprotect(PROTECT_CONFIG); |
| 297 | db_multi_exec("DELETE FROM config WHERE name = 'aux-clone-seqno';"); |
| 298 | db_protect_pop(); |
| 299 | } |
| 300 | db_end_transaction(0); |
| 301 | db_close(1); |
| 302 | db_open_repository(zRepo); |
| 303 | } |
| 304 | db_begin_transaction(); |
| 305 | if( db_exists("SELECT 1 FROM delta WHERE srcId IN phantom") ){ |
| 306 | fossil_warning("there are unresolved deltas -" |
| 307 | " the clone is probably incomplete and unusable.\n" |
| 308 | "It may be possible to resume the clone by running the" |
| 309 | " same command."); |
| 310 | } |
| 311 | fossil_print("Rebuilding repository meta-data...\n"); |
| 312 | rebuild_db(1, 0); |
| 313 | if( !noCompress ){ |
| 314 | int nDelta = 0; |
| 315 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -18,10 +18,11 @@ | |
| 18 | ** This file contains code used to clone a repository |
| 19 | */ |
| 20 | #include "config.h" |
| 21 | #include "clone.h" |
| 22 | #include <assert.h> |
| 23 | #include <signal.h> |
| 24 | |
| 25 | /* |
| 26 | ** If there are public BLOBs that deltas from private BLOBs, then |
| 27 | ** undeltify the public BLOBs so that the private BLOBs may be safely |
| 28 | ** deleted. |
| @@ -282,33 +283,46 @@ | |
| 283 | db_protect_pop(); |
| 284 | url_enable_proxy(0); |
| 285 | clone_ssh_db_set_options(); |
| 286 | url_get_password_if_needed(); |
| 287 | g.xlinkClusterOnly = 1; |
| 288 | while( nResumes++<3 && sync_interrupted()==0 |
| 289 | && (nErr = client_sync(syncFlags,CONFIGSET_ALL,0,0)) |
| 290 | ){ |
| 291 | if( sync_interrupted()!=0 ){ |
| 292 | fossil_warning("cloning encountered errors, trying again."); |
| 293 | sqlite3_sleep(500); |
| 294 | } |
| 295 | } |
| 296 | g.xlinkClusterOnly = 0; |
| 297 | verify_cancel(); |
| 298 | if( nErr ){ |
| 299 | fossil_warning("server returned an error - clone incomplete"); |
| 300 | }else if( sync_interrupted()==1 ){ |
| 301 | fossil_warning("clone was interrupted"); |
| 302 | }else{ |
| 303 | db_unprotect(PROTECT_CONFIG); |
| 304 | db_multi_exec("DELETE FROM config WHERE name = 'aux-clone-seqno';"); |
| 305 | db_protect_pop(); |
| 306 | } |
| 307 | db_end_transaction(0); |
| 308 | db_close(1); |
| 309 | db_open_repository(zRepo); |
| 310 | #if !defined(_WIN32) |
| 311 | signal(SIGINT, SIG_DFL); |
| 312 | #endif |
| 313 | } |
| 314 | db_begin_transaction(); |
| 315 | if( db_exists("SELECT 1 FROM delta WHERE srcId IN phantom") ){ |
| 316 | if( db_get_int("aux-clone-seqno",0)==0 ){ |
| 317 | fossil_fatal("there are unresolved deltas -" |
| 318 | " the clone is probabaly incomplete and unusable."); |
| 319 | } |
| 320 | } |
| 321 | if( db_get_int("aux-clone-seqno",0)>0 ){ |
| 322 | fossil_warning("Clone incomplete - it may be possible to resume the" |
| 323 | " clone by running the same command again."); |
| 324 | } |
| 325 | fossil_print("Rebuilding repository meta-data...\n"); |
| 326 | rebuild_db(1, 0); |
| 327 | if( !noCompress ){ |
| 328 | int nDelta = 0; |
| 329 |
+18
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -1940,10 +1940,24 @@ | ||
| 1940 | 1940 | ** Floating-point absolute value |
| 1941 | 1941 | */ |
| 1942 | 1942 | static double fossil_fabs(double x){ |
| 1943 | 1943 | return x>0.0 ? x : -x; |
| 1944 | 1944 | } |
| 1945 | + | |
| 1946 | +/* | |
| 1947 | +** Used during cloning to exit the sync loop prematurely | |
| 1948 | +*/ | |
| 1949 | +static int bSyncGotIntr = 0; | |
| 1950 | +static void sync_sigint_handler(int x){ | |
| 1951 | + bSyncGotIntr = 1; | |
| 1952 | +} | |
| 1953 | +/* | |
| 1954 | +** Interface to check whether sync was interrupted by SIGINT | |
| 1955 | +*/ | |
| 1956 | +int sync_interrupted() { | |
| 1957 | + return bSyncGotIntr; | |
| 1958 | +} | |
| 1945 | 1959 | |
| 1946 | 1960 | /* |
| 1947 | 1961 | ** Sync to the host identified in g.url.name and g.url.path. This |
| 1948 | 1962 | ** routine is called by the client. |
| 1949 | 1963 | ** |
| @@ -2096,10 +2110,13 @@ | ||
| 2096 | 2110 | */ |
| 2097 | 2111 | blob_appendf(&send, "pragma client-version %d %d %d\n", |
| 2098 | 2112 | RELEASE_VERSION_NUMBER, MANIFEST_NUMERIC_DATE, |
| 2099 | 2113 | MANIFEST_NUMERIC_TIME); |
| 2100 | 2114 | if( syncFlags & SYNC_CLONE ){ |
| 2115 | +#if !defined(_WIN32) | |
| 2116 | + signal(SIGINT, sync_sigint_handler); | |
| 2117 | +#endif | |
| 2101 | 2118 | blob_appendf(&send, "clone 3 %d\n", cloneSeqno); |
| 2102 | 2119 | syncFlags &= ~(SYNC_PUSH|SYNC_PULL); |
| 2103 | 2120 | nCardSent++; |
| 2104 | 2121 | /* TBD: Request all transferable configuration values */ |
| 2105 | 2122 | content_enable_dephantomize(0); |
| @@ -2852,10 +2869,11 @@ | ||
| 2852 | 2869 | /* Continue the clone until we see the clone_seqno 0" card or |
| 2853 | 2870 | ** until we stop receiving artifacts */ |
| 2854 | 2871 | go = 1; |
| 2855 | 2872 | } |
| 2856 | 2873 | } |
| 2874 | + if( go && bSyncGotIntr ) go = 0; | |
| 2857 | 2875 | |
| 2858 | 2876 | nCardRcvd = 0; |
| 2859 | 2877 | xfer.nFileRcvd = 0; |
| 2860 | 2878 | xfer.nDeltaRcvd = 0; |
| 2861 | 2879 | xfer.nDanglingFile = 0; |
| 2862 | 2880 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -1940,10 +1940,24 @@ | |
| 1940 | ** Floating-point absolute value |
| 1941 | */ |
| 1942 | static double fossil_fabs(double x){ |
| 1943 | return x>0.0 ? x : -x; |
| 1944 | } |
| 1945 | |
| 1946 | /* |
| 1947 | ** Sync to the host identified in g.url.name and g.url.path. This |
| 1948 | ** routine is called by the client. |
| 1949 | ** |
| @@ -2096,10 +2110,13 @@ | |
| 2096 | */ |
| 2097 | blob_appendf(&send, "pragma client-version %d %d %d\n", |
| 2098 | RELEASE_VERSION_NUMBER, MANIFEST_NUMERIC_DATE, |
| 2099 | MANIFEST_NUMERIC_TIME); |
| 2100 | if( syncFlags & SYNC_CLONE ){ |
| 2101 | blob_appendf(&send, "clone 3 %d\n", cloneSeqno); |
| 2102 | syncFlags &= ~(SYNC_PUSH|SYNC_PULL); |
| 2103 | nCardSent++; |
| 2104 | /* TBD: Request all transferable configuration values */ |
| 2105 | content_enable_dephantomize(0); |
| @@ -2852,10 +2869,11 @@ | |
| 2852 | /* Continue the clone until we see the clone_seqno 0" card or |
| 2853 | ** until we stop receiving artifacts */ |
| 2854 | go = 1; |
| 2855 | } |
| 2856 | } |
| 2857 | |
| 2858 | nCardRcvd = 0; |
| 2859 | xfer.nFileRcvd = 0; |
| 2860 | xfer.nDeltaRcvd = 0; |
| 2861 | xfer.nDanglingFile = 0; |
| 2862 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -1940,10 +1940,24 @@ | |
| 1940 | ** Floating-point absolute value |
| 1941 | */ |
| 1942 | static double fossil_fabs(double x){ |
| 1943 | return x>0.0 ? x : -x; |
| 1944 | } |
| 1945 | |
| 1946 | /* |
| 1947 | ** Used during cloning to exit the sync loop prematurely |
| 1948 | */ |
| 1949 | static int bSyncGotIntr = 0; |
| 1950 | static void sync_sigint_handler(int x){ |
| 1951 | bSyncGotIntr = 1; |
| 1952 | } |
| 1953 | /* |
| 1954 | ** Interface to check whether sync was interrupted by SIGINT |
| 1955 | */ |
| 1956 | int sync_interrupted() { |
| 1957 | return bSyncGotIntr; |
| 1958 | } |
| 1959 | |
| 1960 | /* |
| 1961 | ** Sync to the host identified in g.url.name and g.url.path. This |
| 1962 | ** routine is called by the client. |
| 1963 | ** |
| @@ -2096,10 +2110,13 @@ | |
| 2110 | */ |
| 2111 | blob_appendf(&send, "pragma client-version %d %d %d\n", |
| 2112 | RELEASE_VERSION_NUMBER, MANIFEST_NUMERIC_DATE, |
| 2113 | MANIFEST_NUMERIC_TIME); |
| 2114 | if( syncFlags & SYNC_CLONE ){ |
| 2115 | #if !defined(_WIN32) |
| 2116 | signal(SIGINT, sync_sigint_handler); |
| 2117 | #endif |
| 2118 | blob_appendf(&send, "clone 3 %d\n", cloneSeqno); |
| 2119 | syncFlags &= ~(SYNC_PUSH|SYNC_PULL); |
| 2120 | nCardSent++; |
| 2121 | /* TBD: Request all transferable configuration values */ |
| 2122 | content_enable_dephantomize(0); |
| @@ -2852,10 +2869,11 @@ | |
| 2869 | /* Continue the clone until we see the clone_seqno 0" card or |
| 2870 | ** until we stop receiving artifacts */ |
| 2871 | go = 1; |
| 2872 | } |
| 2873 | } |
| 2874 | if( go && bSyncGotIntr ) go = 0; |
| 2875 | |
| 2876 | nCardRcvd = 0; |
| 2877 | xfer.nFileRcvd = 0; |
| 2878 | xfer.nDeltaRcvd = 0; |
| 2879 | xfer.nDanglingFile = 0; |
| 2880 |