Index: src/branch.c ================================================================== --- src/branch.c +++ src/branch.c @@ -176,11 +176,11 @@ /* Commit */ db_end_transaction(0); /* Do an autosync push, if requested */ - if( !isPrivate ) autosync(AUTOSYNC_PUSH); + if( !isPrivate ) autosync(SYNC_PUSH); } /* ** Prepare a query that will list branches. ** Index: src/checkin.c ================================================================== --- src/checkin.c +++ src/checkin.c @@ -1108,11 +1108,11 @@ /* ** Autosync if autosync is enabled and this is not a private check-in. */ if( !g.markPrivate ){ - if( autosync(AUTOSYNC_PULL) ){ + if( autosync(SYNC_PULL) ){ blob_zero(&ans); prompt_user("continue in spite of sync failure (y/N)? ", &ans); cReply = blob_str(&ans)[0]; if( cReply!='y' && cReply!='Y' ){ fossil_exit(1); @@ -1459,11 +1459,11 @@ exit(1); } db_end_transaction(0); if( !g.markPrivate ){ - autosync(AUTOSYNC_PUSH); + autosync(SYNC_PUSH); } if( count_nonbranch_children(vid)>1 ){ fossil_print("**** warning: a fork has occurred *****\n"); } } Index: src/clone.c ================================================================== --- src/clone.c +++ src/clone.c @@ -99,15 +99,15 @@ ** See also: init */ void clone_cmd(void){ char *zPassword; const char *zDefaultUser; /* Optional name of the default user */ - const char *zPw; /* The user clone password */ + const char *zPw; /* The user clone password */ int nErr = 0; - int bPrivate; /* Also clone private branches */ + int bPrivate = 0; /* Also clone private branches */ - bPrivate = find_option("private",0,0)!=0; + if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE; url_proxy_options(); if( g.argc < 4 ){ usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY"); } db_open_config(0); @@ -162,11 +162,11 @@ " VALUES('server-code', lower(hex(randomblob(20))), now());" ); url_enable_proxy(0); url_get_password_if_needed(); g.xlinkClusterOnly = 1; - nErr = client_sync(0,0,1,bPrivate,CONFIGSET_ALL,0); + nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0); g.xlinkClusterOnly = 0; verify_cancel(); db_end_transaction(0); db_close(1); if( nErr ){ Index: src/configure.c ================================================================== --- src/configure.c +++ src/configure.c @@ -906,15 +906,15 @@ user_select(); url_enable_proxy("via proxy: "); if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT; if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE; if( strncmp(zMethod, "push", n)==0 ){ - client_sync(0,0,0,0,0,mask); + client_sync(0,0,(unsigned)mask); }else if( strncmp(zMethod, "pull", n)==0 ){ - client_sync(0,0,0,0,mask,0); + client_sync(0,(unsigned)mask,0); }else{ - client_sync(0,0,0,0,mask,mask); + client_sync(0,(unsigned)mask,(unsigned)mask); } }else if( strncmp(zMethod, "reset", n)==0 ){ int mask, i; char *zBackup; Index: src/json_branch.c ================================================================== --- src/json_branch.c +++ src/json_branch.c @@ -305,11 +305,11 @@ /* Commit */ db_end_transaction(0); #if 0 /* Do an autosync push, if requested */ /* arugable for JSON mode? */ - if( !g.isHTTP && !isPrivate ) autosync(AUTOSYNC_PUSH); + if( !g.isHTTP && !isPrivate ) autosync(SYNC_PUSH); #endif return 0; } Index: src/sync.c ================================================================== --- src/sync.c +++ src/sync.c @@ -19,19 +19,10 @@ */ #include "config.h" #include "sync.h" #include <assert.h> -#if INTERFACE -/* -** Flags used to determine which direction(s) an autosync goes in. -*/ -#define AUTOSYNC_PUSH 1 -#define AUTOSYNC_PULL 2 - -#endif /* INTERFACE */ - /* ** If the repository is configured for autosyncing, then do an ** autosync. This will be a pull if the argument is true or a push ** if the argument is false. ** @@ -44,16 +35,16 @@ int rc; int configSync = 0; /* configuration changes transferred */ if( g.fNoSync ){ return 0; } - if( flags==AUTOSYNC_PUSH && db_get_boolean("dont-push",0) ){ + if( flags==SYNC_PUSH && db_get_boolean("dont-push",0) ){ return 0; } zAutosync = db_get("autosync", 0); if( zAutosync ){ - if( (flags & AUTOSYNC_PUSH)!=0 && memcmp(zAutosync,"pull",4)==0 ){ + if( (flags & SYNC_PUSH)!=0 && memcmp(zAutosync,"pull",4)==0 ){ return 0; /* Do not auto-push when autosync=pullonly */ } if( is_false(zAutosync) ){ return 0; /* Autosync is completely off */ } @@ -81,11 +72,11 @@ configSync = CONFIGSET_SHUN; } #endif fossil_print("Autosync: %s\n", g.urlCanonical); url_enable_proxy("via proxy: "); - rc = client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0, 0, configSync, 0); + rc = client_sync(flags, configSync, 0); if( rc ) fossil_warning("Autosync failed"); return rc; } /* @@ -92,17 +83,22 @@ ** This routine processes the command-line argument for push, pull, ** and sync. If a command-line argument is given, that is the URL ** of a server to sync against. If no argument is given, use the ** most recently synced URL. Remember the current URL for next time. */ -static void process_sync_args(int *pConfigSync, int *pPrivate){ +static void process_sync_args(unsigned *pConfigFlags, unsigned *pSyncFlags){ const char *zUrl = 0; const char *zPw = 0; - int configSync = 0; + unsigned configSync = 0; int urlOptional = find_option("autourl",0,0)!=0; g.dontKeepUrl = find_option("once",0,0)!=0; - *pPrivate = find_option("private",0,0)!=0; + if( find_option("private",0,0)!=0 ){ + *pSyncFlags |= SYNC_PRIVATE; + } + if( find_option("verbose","v",0)!=0 ){ + *pSyncFlags |= SYNC_VERBOSE; + } url_proxy_options(); db_find_and_open_repository(0, 0); db_open_config(0); if( g.argc==2 ){ zUrl = db_get("last-sync-url", 0); @@ -127,14 +123,20 @@ db_set("last-sync-url", g.urlCanonical, 0); if( g.urlPasswd ) db_set("last-sync-pw", obscure(g.urlPasswd), 0); } user_select(); if( g.argc==2 ){ - fossil_print("Server: %s\n", g.urlCanonical); + if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){ + fossil_print("Sync with %s\n", g.urlCanonical); + }else if( (*pSyncFlags) & SYNC_PUSH ){ + fossil_print("Push to %s\n", g.urlCanonical); + }else if( (*pSyncFlags) & SYNC_PULL ){ + fossil_print("Pull from %s\n", g.urlCanonical); + } } url_enable_proxy("via proxy: "); - *pConfigSync = configSync; + *pConfigFlags |= configSync; } /* ** COMMAND: pull ** @@ -156,14 +158,14 @@ ** remote repository. ** ** See also: clone, push, sync, remote-url */ void pull_cmd(void){ - int syncFlags; - int bPrivate; - process_sync_args(&syncFlags, &bPrivate); - client_sync(0,1,0,bPrivate,syncFlags,0); + unsigned configFlags = 0; + unsigned syncFlags = SYNC_PULL; + process_sync_args(&configFlags, &syncFlags); + client_sync(syncFlags, configFlags, 0); } /* ** COMMAND: push ** @@ -185,17 +187,17 @@ ** remote repository. ** ** See also: clone, pull, sync, remote-url */ void push_cmd(void){ - int syncFlags; - int bPrivate; - process_sync_args(&syncFlags, &bPrivate); + unsigned configFlags = 0; + unsigned syncFlags = SYNC_PUSH; + process_sync_args(&configFlags, &syncFlags); if( db_get_boolean("dont-push",0) ){ fossil_fatal("pushing is prohibited: the 'dont-push' option is set"); } - client_sync(1,0,0,bPrivate,0,0); + client_sync(syncFlags, 0, 0); } /* ** COMMAND: sync @@ -223,17 +225,16 @@ ** remote repository. ** ** See also: clone, push, pull, remote-url */ void sync_cmd(void){ - int syncFlags; - int bPrivate; - int pushFlag = 1; - process_sync_args(&syncFlags, &bPrivate); - if( db_get_boolean("dont-push",0) ) pushFlag = 0; - client_sync(pushFlag,1,0,bPrivate,syncFlags,0); - if( pushFlag==0 ){ + unsigned configFlags = 0; + unsigned syncFlags = SYNC_PUSH|SYNC_PULL; + process_sync_args(&configFlags, &syncFlags); + if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH; + client_sync(syncFlags, configFlags, 0); + if( (syncFlags & SYNC_PUSH)==0 ){ fossil_warning("pull only: the 'dont-push' option is set"); } } /* Index: src/update.c ================================================================== --- src/update.c +++ src/update.c @@ -123,11 +123,11 @@ db_must_be_within_tree(); vid = db_lget_int("checkout", 0); if( vid==0 ){ fossil_fatal("cannot find current version"); } - if( !nochangeFlag && !internalUpdate ) autosync(AUTOSYNC_PULL); + if( !nochangeFlag && !internalUpdate ) autosync(SYNC_PULL); /* Create any empty directories now, as well as after the update, ** so changes in settings are reflected now */ if( !nochangeFlag ) ensure_empty_dirs_created(); Index: src/xfer.c ================================================================== --- src/xfer.c +++ src/xfer.c @@ -1266,11 +1266,23 @@ /* ** Format strings for progress reporting. */ static const char zLabelFormat[] = "%-10s %10s %10s %10s %10s\n"; static const char zValueFormat[] = "\r%-10s %10d %10d %10d %10d\n"; +static const char zBriefFormat[] = + "Round-trips: %d Artifacts sent: %d received: %d\r"; +#if INTERFACE +/* +** Flag options for controlling client_sync() +*/ +#define SYNC_PUSH 0x0001 +#define SYNC_PULL 0x0002 +#define SYNC_CLONE 0x0004 +#define SYNC_PRIVATE 0x0008 +#define SYNC_VERBOSE 0x0010 +#endif /* ** Sync to the host identified in g.urlName and g.urlPath. This ** routine is called by the client. ** @@ -1277,16 +1289,13 @@ ** Records are pushed to the server if pushFlag is true. Records ** are pulled if pullFlag is true. A full sync occurs if both are ** true. */ int client_sync( - int pushFlag, /* True to do a push (or a sync) */ - int pullFlag, /* True to do a pull (or a sync) */ - int cloneFlag, /* True if this is a clone */ - int privateFlag, /* True to exchange private branches */ - int configRcvMask, /* Receive these configuration items */ - int configSendMask /* Send these configuration items */ + unsigned syncFlags, /* Mask of SYNC_* flags */ + unsigned configRcvMask, /* Receive these configuration items */ + unsigned configSendMask /* Send these configuration items */ ){ int go = 1; /* Loop until zero */ int nCardSent = 0; /* Number of cards sent */ int nCardRcvd = 0; /* Number of cards received */ int nCycle = 0; /* Number of round trips to the server */ @@ -1304,27 +1313,30 @@ 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 */ - if( db_get_boolean("dont-push", 0) ) pushFlag = 0; - if( pushFlag + pullFlag + cloneFlag == 0 + 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); - if( privateFlag ){ + if( syncFlags & SYNC_PRIVATE ){ g.perm.Private = 1; xfer.syncPrivate = 1; } - assert( pushFlag | pullFlag | cloneFlag | configRcvMask | configSendMask ); db_begin_transaction(); db_record_repository_filename(0); db_multi_exec( "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" ); @@ -1335,33 +1347,39 @@ blob_zero(&xfer.line); origConfigRcvMask = 0; /* Send the send-private pragma if we are trying to sync private data */ - if( privateFlag ) blob_append(&send, "pragma send-private\n", -1); + if( syncFlags & SYNC_PRIVATE ){ + blob_append(&send, "pragma send-private\n", -1); + } /* ** Always begin with a clone, pull, or push message */ - if( cloneFlag ){ + if( syncFlags & SYNC_CLONE ){ blob_appendf(&send, "clone 3 %d\n", cloneSeqno); - pushFlag = 0; - pullFlag = 0; + syncFlags &= ~(SYNC_PUSH|SYNC_PULL); nCardSent++; /* TBD: Request all transferable configuration values */ content_enable_dephantomize(0); - }else if( pullFlag ){ + zOpType = "Clone"; + }else if( syncFlags & SYNC_PULL ){ blob_appendf(&send, "pull %s %s\n", zSCode, zPCode); nCardSent++; + zOpType = "Pull"; } - if( pushFlag ){ + if( syncFlags & SYNC_PUSH ){ blob_appendf(&send, "push %s %s\n", zSCode, zPCode); nCardSent++; + if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push"; } manifest_crosslink_begin(); transport_global_startup(); - fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas"); + if( syncFlags & SYNC_VERBOSE ){ + fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas"); + } while( go ){ int newPhantom = 0; char *zRandomness; @@ -1374,25 +1392,28 @@ } /* Generate gimme cards for phantoms and leaf cards ** for all leaves. */ - if( pullFlag || (cloneFlag && cloneSeqno==1) ){ + if( (syncFlags & SYNC_PULL)!=0 + || ((syncFlags & SYNC_CLONE)!=0 && cloneSeqno==1) + ){ request_phantoms(&xfer, mxPhantomReq); } - if( pushFlag ){ + if( syncFlags & SYNC_PUSH ){ send_unsent(&xfer); nCardSent += send_unclustered(&xfer); - if( privateFlag ) send_private(&xfer); + if( syncFlags & SYNC_PRIVATE ) send_private(&xfer); } /* Send configuration parameter requests. On a clone, delay sending ** this until the second cycle since the login card might fail on ** the first cycle. */ - if( configRcvMask && (cloneFlag==0 || nCycle>0) ){ + if( configRcvMask && ((syncFlags & SYNC_CLONE)==0 || nCycle>0) ){ const char *zName; + if( zOpType==0 ) zOpType = "Pull"; zName = configure_first_name(configRcvMask); while( zName ){ blob_appendf(&send, "reqconfig %s\n", zName); zName = configure_next_name(configRcvMask); nCardSent++; @@ -1407,10 +1428,11 @@ configRcvMask = 0; } /* Send configuration parameters being pushed */ if( configSendMask ){ + if( zOpType==0 ) zOpType = "Push"; if( configSendMask & CONFIGSET_OLDFORMAT ){ const char *zName; zName = configure_first_name(configSendMask); while( zName ){ send_legacy_config_card(&xfer, zName); @@ -1430,42 +1452,50 @@ zRandomness = db_text(0, "SELECT hex(randomblob(20))"); blob_appendf(&send, "# %s\n", zRandomness); free(zRandomness); /* Exchange messages with the server */ - fossil_print(zValueFormat, "Sent:", - blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent, - xfer.nFileSent, xfer.nDeltaSent); + if( syncFlags & SYNC_VERBOSE ){ + fossil_print(zValueFormat, "Sent:", + blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent, + xfer.nFileSent, xfer.nDeltaSent); + }else{ + nRoundtrip++; + nArtifactSent += xfer.nFileSent + xfer.nDeltaSent; + fossil_print(zBriefFormat, nRoundtrip, nArtifactSent, nArtifactRcvd); + } nCardSent = 0; nCardRcvd = 0; xfer.nFileSent = 0; xfer.nDeltaSent = 0; xfer.nGimmeSent = 0; xfer.nIGotSent = 0; - if( !g.cgiOutput && !g.fQuiet ){ + if( syncFlags & SYNC_VERBOSE ){ fossil_print("waiting for server..."); } fflush(stdout); - if( http_exchange(&send, &recv, cloneFlag==0 || nCycle>0) ){ + if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0) ){ nErr++; break; } lastPctDone = -1; blob_reset(&send); rArrivalTime = db_double(0.0, "SELECT julianday('now')"); /* Send the send-private pragma if we are trying to sync private data */ - if( privateFlag ) blob_append(&send, "pragma send-private\n", -1); + if( syncFlags & SYNC_PRIVATE ){ + blob_append(&send, "pragma send-private\n", -1); + } /* Begin constructing the next message (which might never be ** sent) by beginning with the pull or push cards */ - if( pullFlag ){ + if( syncFlags & SYNC_PULL ){ blob_appendf(&send, "pull %s %s\n", zSCode, zPCode); nCardSent++; } - if( pushFlag ){ + if( syncFlags & SYNC_PUSH ){ blob_appendf(&send, "push %s %s\n", zSCode, zPCode); nCardSent++; } go = 0; @@ -1493,11 +1523,11 @@ nCardRcvd++; continue; } xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); nCardRcvd++; - if( !g.cgiOutput && !g.fQuiet && recv.nUsed>0 ){ + 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); @@ -1508,20 +1538,22 @@ ** file UUID DELTASRC SIZE \n CONTENT ** ** Receive a file transmitted from the server. */ if( blob_eq(&xfer.aToken[0],"file") ){ - xfer_accept_file(&xfer, cloneFlag); + xfer_accept_file(&xfer, (syncFlags & SYNC_CLONE)!=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); + nArtifactRcvd++; }else /* gimme UUID ** ** Server is requesting a file. If the file is a manifest, assume @@ -1530,11 +1562,11 @@ */ if( blob_eq(&xfer.aToken[0], "gimme") && xfer.nToken==2 && blob_is_uuid(&xfer.aToken[1]) ){ - if( pushFlag ){ + if( syncFlags & SYNC_PUSH ){ int rid = rid_from_uuid(&xfer.aToken[1], 0, 0); if( rid ) send_file(&xfer, rid, &xfer.aToken[1], 0); } }else @@ -1559,11 +1591,11 @@ rid = rid_from_uuid(&xfer.aToken[1], 0, 0); if( rid>0 ){ if( !isPriv ) content_make_public(rid); }else if( isPriv && !g.perm.Private ){ /* ignore private files */ - }else if( pullFlag || cloneFlag ){ + }else if( (syncFlags & (SYNC_PULL|SYNC_CLONE))!=0 ){ rid = content_new(blob_str(&xfer.aToken[1]), isPriv); if( rid ) newPhantom = 1; } remote_has(rid); }else @@ -1574,11 +1606,11 @@ ** Should only happen in response to a clone. This message tells ** the client what product to use for the new database. */ if( blob_eq(&xfer.aToken[0],"push") && xfer.nToken==3 - && cloneFlag + && (syncFlags & SYNC_CLONE)!=0 && blob_is_uuid(&xfer.aToken[1]) && blob_is_uuid(&xfer.aToken[2]) ){ if( blob_eq_str(&xfer.aToken[1], zSCode, -1) ){ fossil_fatal("server loop"); @@ -1604,11 +1636,12 @@ Blob content; blob_zero(&content); blob_extract(xfer.pIn, size, &content); g.perm.Admin = g.perm.RdAddr = 1; configure_receive(zName, &content, origConfigRcvMask); - nCardSent++; + nCardRcvd++; + nArtifactRcvd++; blob_reset(&content); blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR); }else @@ -1655,12 +1688,12 @@ ** to the next cycle. */ if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){ char *zMsg = blob_terminate(&xfer.aToken[1]); defossilize(zMsg); - if( pushFlag && zMsg && strglob("pull only *", zMsg) ){ - pushFlag = 0; + if( (syncFlags & SYNC_PUSH) && zMsg && strglob("pull only *", zMsg) ){ + syncFlags &= ~SYNC_PUSH; zMsg = 0; } fossil_print("\rServer says: %s\n", zMsg); }else @@ -1683,11 +1716,11 @@ ** is returned in the reply before the error card, so second and ** subsequent messages should be OK. Nevertheless, we need to ignore ** the error card on the first message of a clone. */ if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){ - if( !cloneFlag || nCycle>0 ){ + if( (syncFlags & SYNC_CLONE)==0 || nCycle>0 ){ char *zMsg = blob_terminate(&xfer.aToken[1]); defossilize(zMsg); if( fossil_strcmp(zMsg, "login failed")==0 ){ if( nCycle<2 ){ if( !g.dontKeepUrl ) db_unset("last-sync-pw", 0); @@ -1727,14 +1760,16 @@ && (configRcvMask & CONFIGSET_OLDFORMAT)!=0 ){ configure_finalize_receive(); } origConfigRcvMask = 0; - if( nCardRcvd>0 ){ + if( nCardRcvd>0 && (syncFlags & SYNC_VERBOSE) ){ fossil_print(zValueFormat, "Received:", blob_size(&recv), nCardRcvd, xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile); + }else{ + fossil_print(zBriefFormat, nRoundtrip, nArtifactSent, nArtifactRcvd); } blob_reset(&recv); nCycle++; /* If we received one or more files on the previous exchange but @@ -1743,11 +1778,11 @@ nFileRecv = xfer.nFileRcvd + xfer.nDeltaRcvd + xfer.nDanglingFile; if( (nFileRecv>0 || newPhantom) && db_exists("SELECT 1 FROM phantom") ){ go = 1; mxPhantomReq = nFileRecv*2; if( mxPhantomReq<200 ) mxPhantomReq = 200; - }else if( cloneFlag && nFileRecv>0 ){ + }else if( (syncFlags & SYNC_CLONE)!=0 && nFileRecv>0 ){ go = 1; } nCardRcvd = 0; xfer.nFileRcvd = 0; xfer.nDeltaRcvd = 0; @@ -1759,25 +1794,27 @@ if( xfer.nFileSent+xfer.nDeltaSent>0 ){ go = 1; } /* If this is a clone, the go at least two rounds */ - if( cloneFlag && nCycle==1 ) go = 1; + if( (syncFlags & SYNC_CLONE)!=0 && nCycle==1 ) go = 1; /* Stop the cycle if the server sends a "clone_seqno 0" card and ** we have gone at least two rounds. Always go at least two rounds ** on a clone in order to be sure to retrieve the configuration ** information which is only sent on the second round. */ if( cloneSeqno<=0 && nCycle>1 ) go = 0; }; transport_stats(&nSent, &nRcvd, 1); - fossil_print("Total network traffic: %lld bytes sent, %lld bytes received\n", - nSent, nRcvd); + if( (syncFlags & SYNC_VERBOSE)==0 ) fossil_print("\n"); + fossil_print( + "%s finished with %lld bytes sent, %lld bytes received\n", + zOpType, nSent, nRcvd); transport_close(); transport_global_shutdown(); db_multi_exec("DROP TABLE onremote"); manifest_crosslink_end(); content_enable_dephantomize(1); db_end_transaction(0); return nErr; }