Fossil

Changes On Branch clone-resume
Login

Changes On Branch clone-resume

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch clone-resume Excluding Merge-Ins

This is equivalent to a diff from 38dad38b6d to 2304041e42

2024-03-25
15:48
Update buildmsvc.bat to be able to be called in a normal command prompt and automatically load the needed MSVC build tools (x64 by default; x86 can be given as the first argument). ... (check-in: 97971b9666 user: danield tags: trunk)
2024-03-23
05:54
Updates from trunk for sync changes et al. ... (Leaf check-in: 2304041e42 user: andybradford tags: clone-resume)
2024-03-22
12:30
Fix uninitialized variable in the previous check-in. ... (check-in: 38dad38b6d user: drh tags: trunk)
12:28
The "fossil sync --all" command now makes up to two passes through the list of remote URLs to ensure that everybody gets synced up. See the discussion at [forum:/forumpost/4d6a94aca6105fc6|forum thread 4d6a94aca6105fc6]. ... (check-in: 0cd5589c09 user: drh tags: trunk)
2024-02-09
13:51
Sync up with trunk for latest improvements. ... (check-in: 12390507b1 user: andybradford tags: clone-resume)

Changes to src/clone.c.

16
17
18
19
20
21
22



23
24
25
26
27
28
29
*******************************************************************************
**
** This file contains code used to clone a repository
*/
#include "config.h"
#include "clone.h"
#include <assert.h>




/*
** If there are public BLOBs that deltas from private BLOBs, then
** undeltify the public BLOBs so that the private BLOBs may be safely
** deleted.
*/
void fix_private_blob_dependencies(int showWarning){







>
>
>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
*******************************************************************************
**
** This file contains code used to clone a repository
*/
#include "config.h"
#include "clone.h"
#include <assert.h>
#if !defined(_WIN32)
#  include <signal.h>
#endif

/*
** If there are public BLOBs that deltas from private BLOBs, then
** undeltify the public BLOBs so that the private BLOBs may be safely
** deleted.
*/
void fix_private_blob_dependencies(int showWarning){
142
143
144
145
146
147
148

149
150
151
152
153




154
155
156
157
158
159
160
** See also: [[init]], [[open]]
*/
void clone_cmd(void){
  char *zPassword;
  const char *zDefaultUser;   /* Optional name of the default user */
  const char *zHttpAuth;      /* HTTP Authorization user:pass information */
  int nErr = 0;

  int urlFlags = URL_PROMPT_PW | URL_REMEMBER;
  int syncFlags = SYNC_CLONE;
  int noCompress = find_option("nocompress",0,0)!=0;
  int noOpen = find_option("no-open",0,0)!=0;
  int allowNested = find_option("nested",0,0)!=0; /* Used by open */




  const char *zRepo = 0;      /* Name of the new local repository file */
  const char *zWorkDir = 0;   /* Open in this directory, if not zero */


  /* Also clone private branches */
  if( find_option("private",0,0)!=0 ) syncFlags |= SYNC_PRIVATE;
  if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER;







>





>
>
>
>







145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
** See also: [[init]], [[open]]
*/
void clone_cmd(void){
  char *zPassword;
  const char *zDefaultUser;   /* Optional name of the default user */
  const char *zHttpAuth;      /* HTTP Authorization user:pass information */
  int nErr = 0;
  int nResumes = 0;
  int urlFlags = URL_PROMPT_PW | URL_REMEMBER;
  int syncFlags = SYNC_CLONE;
  int noCompress = find_option("nocompress",0,0)!=0;
  int noOpen = find_option("no-open",0,0)!=0;
  int allowNested = find_option("nested",0,0)!=0; /* Used by open */
  int nResumeSeqno = 0;       /* Last seqno from which to resume clone */
  const char *zNewProjCode;   /* New Project code obtained during clone */
  const char *zOldProjCode;   /* Old project code stored in resuming clone */
  const char *zCloneCode;     /* server-code for the source of the clone */
  const char *zRepo = 0;      /* Name of the new local repository file */
  const char *zWorkDir = 0;   /* Open in this directory, if not zero */


  /* Also clone private branches */
  if( find_option("private",0,0)!=0 ) syncFlags |= SYNC_PRIVATE;
  if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER;
196
197
198
199
200
201
202




203

204
205
206
207
208
209
210
    zRepo = mprintf("./%s.fossil", zBase);
    if( zWorkDir==0 ){
      zWorkDir = mprintf("./%s", zBase);
    }
    fossil_free(zBase);
  }
  if( -1 != file_size(zRepo, ExtFILE) ){




    fossil_fatal("file already exists: %s", zRepo);

  }
  /* Fail before clone if open will fail because inside an open check-out */
  if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){
    if( db_open_local_v2(0, allowNested) ){
      fossil_fatal("there is already an open tree at %s", g.zLocalRoot);
    }
  }







>
>
>
>
|
>







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
    zRepo = mprintf("./%s.fossil", zBase);
    if( zWorkDir==0 ){
      zWorkDir = mprintf("./%s", zBase);
    }
    fossil_free(zBase);
  }
  if( -1 != file_size(zRepo, ExtFILE) ){
    db_open_repository(zRepo);
    nResumeSeqno = db_get_int("aux-clone-seqno",0);
    db_close(0);
    if( !nResumeSeqno ){
      fossil_fatal("file already exists: %s", zRepo);
    }
  }
  /* Fail before clone if open will fail because inside an open check-out */
  if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){
    if( db_open_local_v2(0, allowNested) ){
      fossil_fatal("there is already an open tree at %s", g.zLocalRoot);
    }
  }
224
225
226
227
228
229
230




















231
232
233
234
235
236
237
238
239


240
241
242
243
244
245
246
      g.zLogin = zDefaultUser;
    }else{
      g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'");
    }
    fossil_print("Repository cloned into %s\n", zRepo);
  }else{
    db_close_config();




















    db_create_repository(zRepo);
    db_open_repository(zRepo);
    db_open_config(0,0);
    db_begin_transaction();
    db_record_repository_filename(zRepo);
    db_initial_setup(0, 0, zDefaultUser);
    user_select();
    db_set("content-schema", CONTENT_SCHEMA, 0);
    db_set("aux-schema", AUX_SCHEMA_MAX, 0);


    db_set("rebuilt", get_version(), 0);
    db_unset("hash-policy", 0);
    remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, g.argv[2]);
    url_remember();
    if( g.zSSLIdentity!=0 ){
      /* If the --ssl-identity option was specified, store it as a setting */
      Blob fn;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
>
>







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
      g.zLogin = zDefaultUser;
    }else{
      g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'");
    }
    fossil_print("Repository cloned into %s\n", zRepo);
  }else{
    db_close_config();
    if( nResumeSeqno>1 ){
      db_open_repository(zRepo);
      db_open_config(0,0);
      db_begin_transaction();
      zOldProjCode = db_get("project-code",0);
      zCloneCode = db_get("aux-clone-code",0);
      if( zOldProjCode==0 ) fossil_fatal("project-id missing from repository");
      if( zCloneCode==0 ) fossil_fatal("clone-code missing from repository");
      fossil_print("Resuming clone of project-id %s\n",zOldProjCode);
      db_unprotect(PROTECT_USER);
      db_multi_exec("DELETE FROM user WHERE cap LIKE '%%s%%'");
      db_protect_pop();
      db_create_default_users(1, zDefaultUser);
      if( zDefaultUser ){
        g.zLogin = zDefaultUser;
      }else{
        g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'");
      }
      user_select();
    }else{
      db_create_repository(zRepo);
      db_open_repository(zRepo);
      db_open_config(0,0);
      db_begin_transaction();
      db_record_repository_filename(zRepo);
      db_initial_setup(0, 0, zDefaultUser);
      user_select();
      db_set("content-schema", CONTENT_SCHEMA, 0);
      db_set("aux-schema", AUX_SCHEMA_MAX, 0);
      db_set_int("aux-clone-seqno", 1, 0);
    }
    db_set("rebuilt", get_version(), 0);
    db_unset("hash-policy", 0);
    remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, g.argv[2]);
    url_remember();
    if( g.zSSLIdentity!=0 ){
      /* If the --ssl-identity option was specified, store it as a setting */
      Blob fn;
258
259
260
261
262
263
264
265













266
267


























268
269
270
271
272
273
274



275
276
277
278

279
280






281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324

325
326
327
328
329
330
331
      "DELETE FROM config WHERE name='project-code';"
    );
    db_protect_pop();
    url_enable_proxy(0);
    clone_ssh_db_set_options();
    url_get_password_if_needed();
    g.xlinkClusterOnly = 1;
    nErr = client_sync(syncFlags,CONFIGSET_ALL,0,0,0);













    g.xlinkClusterOnly = 0;
    verify_cancel();


























    db_end_transaction(0);
    db_close(1);
    if( nErr ){
      file_delete(zRepo);
      fossil_fatal("server returned an error - clone aborted");
    }
    db_open_repository(zRepo);



  }
  db_begin_transaction();
  if( db_exists("SELECT 1 FROM delta WHERE srcId IN phantom") ){
    fossil_fatal("there are unresolved deltas -"

                 " the clone is probably incomplete and unusable.");
  }






  fossil_print("Rebuilding repository meta-data...\n");
  rebuild_db(1, 0);
  if( !noCompress ){
    int nDelta = 0;
    i64 nByte;
    fossil_print("Extra delta compression... "); fflush(stdout);
    nByte = extra_deltification(&nDelta);
    if( nDelta==1 ){
      fossil_print("1 delta saves %,lld bytes\n", nByte);
    }else if( nDelta>1 ){
      fossil_print("%d deltas save %,lld bytes\n", nDelta, nByte);
    }else{
      fossil_print("none found\n");
    }
  }
  db_end_transaction(0);
  fossil_print("Vacuuming the database... "); fflush(stdout);
  if( db_int(0, "PRAGMA page_count")>1000
   && db_int(0, "PRAGMA page_size")<8192 ){
     db_multi_exec("PRAGMA page_size=8192;");
  }
  db_unprotect(PROTECT_ALL);
  db_multi_exec("VACUUM");
  db_protect_pop();
  fossil_print("\nproject-id: %s\n", db_get("project-code", 0));
  fossil_print("server-id:  %s\n", db_get("server-code", 0));
  zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
  fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
  hash_user_password(g.zLogin);
  if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){
    Blob cmd;
    fossil_print("opening the new %s repository in directory %s...\n",
       zRepo, zWorkDir);
    blob_init(&cmd, 0, 0);
    blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
    blob_append(&cmd, " open ", -1);
    blob_append_escaped_arg(&cmd, zRepo, 1);
    blob_append(&cmd, " --nosync --workdir ", -1);
    blob_append_escaped_arg(&cmd, zWorkDir, 1);
    if( allowNested ){
      blob_append(&cmd, " --nested", -1);
    }
    fossil_system(blob_str(&cmd));
    blob_reset(&cmd);

  }
}

/*
** If user chooses to use HTTP Authentication over unencrypted HTTP,
** remember decision.  Otherwise, if the URL is being changed and no
** preference has been indicated, err on the safe side and revert the







|
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


<
<
<
<

>
>
>

<

|
>
|
|
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>







293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343




344
345
346
347
348

349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
      "DELETE FROM config WHERE name='project-code';"
    );
    db_protect_pop();
    url_enable_proxy(0);
    clone_ssh_db_set_options();
    url_get_password_if_needed();
    g.xlinkClusterOnly = 1;
    while( nResumes++<3 && (nErr = client_sync(syncFlags,CONFIGSET_ALL,0,0,0))
    ){
      if( db_get_int("aux-clone-seqno",1)==1 ){
        fossil_fatal("server returned an error - clone aborted");
      }
      if( sync_interrupted() ){
        fossil_warning("clone was interrupted");
        break;
      }
      if( nResumes<3 ){
        fossil_warning("cloning encountered errors, trying again.");
        sqlite3_sleep(500);
      }
    }
    g.xlinkClusterOnly = 0;
    verify_cancel();
    if( nResumeSeqno>1 ){
      if( nResumeSeqno==db_get_int("aux-clone-seqno",0) ){
        fossil_fatal("No progress was made - aborting");
      }
      zNewProjCode = db_get("project-code",0);
      if( zOldProjCode!=0 && zOldProjCode[0]!=0
          && fossil_strcmp(zOldProjCode, zNewProjCode)!=0 ){
        fossil_fatal("project-id changed\nwas %s\nis  %s"
               "\nrolling back changes",
               zOldProjCode, zNewProjCode);
      }
      if( zCloneCode!=0 && zCloneCode[0]!=0
          && fossil_strcmp(zCloneCode, db_get("aux-clone-code",0))!=0 ){
        fossil_fatal("clone resume from different server not allowed");
      }
    }
    if( nErr ){
      fossil_warning("server returned an error - clone incomplete");
    }else{
      db_unprotect(PROTECT_CONFIG);
      db_multi_exec(
        "DELETE FROM config WHERE name = 'aux-clone-seqno';"
        "DELETE FROM config WHERE name = 'aux-clone-code';"
      );
      db_protect_pop();
    }
    db_end_transaction(0);
    db_close(1);




    db_open_repository(zRepo);
#if !defined(_WIN32)
    signal(SIGINT, SIG_DFL);
#endif
  }

  if( db_exists("SELECT 1 FROM delta WHERE srcId IN phantom") ){
    fossil_warning("there are unresolved deltas -");
    if( db_get_int("aux-clone-seqno",0)==0 ){
      fossil_fatal("the clone is probabaly incomplete and unusable.");
    }
  }
  if( db_get_int("aux-clone-seqno",0)>1 ){
    fossil_warning("It may be possible to resume the"
           " clone by running the same command again.");
  }else{
    db_begin_transaction();
    fossil_print("Rebuilding repository meta-data...\n");
    rebuild_db(1, 0);
    if( !noCompress ){
      int nDelta = 0;
      i64 nByte;
      fossil_print("Extra delta compression... "); fflush(stdout);
      nByte = extra_deltification(&nDelta);
      if( nDelta==1 ){
        fossil_print("1 delta saves %,lld bytes\n", nByte);
      }else if( nDelta>1 ){
        fossil_print("%d deltas save %,lld bytes\n", nDelta, nByte);
      }else{
        fossil_print("none found\n");
      }
    }
    db_end_transaction(0);
    fossil_print("Vacuuming the database... "); fflush(stdout);
    if( db_int(0, "PRAGMA page_count")>1000
     && db_int(0, "PRAGMA page_size")<8192 ){
       db_multi_exec("PRAGMA page_size=8192;");
    }
    db_unprotect(PROTECT_ALL);
    db_multi_exec("VACUUM");
    db_protect_pop();
    fossil_print("\nproject-id: %s\n", db_get("project-code", 0));
    fossil_print("server-id:  %s\n", db_get("server-code", 0));
    zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
    fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
    hash_user_password(g.zLogin);
    if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){
      Blob cmd;
      fossil_print("opening the new %s repository in directory %s...\n",
         zRepo, zWorkDir);
      blob_init(&cmd, 0, 0);
      blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
      blob_append(&cmd, " open ", -1);
      blob_append_escaped_arg(&cmd, zRepo, 1);
      blob_append(&cmd, " --nosync --workdir ", -1);
      blob_append_escaped_arg(&cmd, zWorkDir, 1);
      if( allowNested ){
        blob_append(&cmd, " --nested", -1);
      }
      fossil_system(blob_str(&cmd));
      blob_reset(&cmd);
    }
  }
}

/*
** If user chooses to use HTTP Authentication over unencrypted HTTP,
** remember decision.  Otherwise, if the URL is being changed and no
** preference has been indicated, err on the safe side and revert the

Changes to src/db.c.

4234
4235
4236
4237
4238
4239
4240



4241
4242
4243
4244
4245
4246
4247
    fossil_fatal("the --repodir option only makes sense if the REPOSITORY "
                 "argument is a URI that begins with http:, https:, ssh:, "
                 "or file:");
  }

  db_open_config(0,0);
  db_open_repository(zRepo);




  /* Figure out which revision to open. */
  if( !emptyFlag ){
    if( g.argc==4 ){
      g.zOpenRevision = g.argv[3];
    }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
      g.zOpenRevision = db_get("main-branch", 0);







>
>
>







4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
    fossil_fatal("the --repodir option only makes sense if the REPOSITORY "
                 "argument is a URI that begins with http:, https:, ssh:, "
                 "or file:");
  }

  db_open_config(0,0);
  db_open_repository(zRepo);
  if( db_get_int("aux-clone-seqno",0)!=0 ){
    fossil_fatal("This repository appears to be an incomplete clone.");
  }

  /* Figure out which revision to open. */
  if( !emptyFlag ){
    if( g.argc==4 ){
      g.zOpenRevision = g.argv[3];
    }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
      g.zOpenRevision = db_get("main-branch", 0);

Changes to src/xfer.c.

17
18
19
20
21
22
23



24
25
26
27
28
29
30
**
** This file contains code to implement the file transfer protocol.
*/
#include "config.h"
#include "xfer.h"

#include <time.h>




/*
** Maximum number of HTTP redirects that any http_exchange() call will
** follow before throwing a fatal error. Most browsers use a limit of 20.
*/
#define MAX_REDIRECTS 20








>
>
>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
**
** This file contains code to implement the file transfer protocol.
*/
#include "config.h"
#include "xfer.h"

#include <time.h>
#if !defined(_WIN32)
#  include <signal.h>
#endif

/*
** Maximum number of HTTP redirects that any http_exchange() call will
** follow before throwing a fatal error. Most browsers use a limit of 20.
*/
#define MAX_REDIRECTS 20

1463
1464
1465
1466
1467
1468
1469




1470
1471
1472
1473
1474
1475
1476
          cgi_set_content_type("application/x-fossil-uncompressed");
        }
        blob_is_int(&xfer.aToken[2], &seqno);
        max = db_int(0, "SELECT max(rid) FROM blob");
        while( xfer.mxSend>(int)blob_size(xfer.pOut) && seqno<=max){
          if( time(NULL) >= xfer.maxTime ) break;
          if( iVers>=3 ){




            send_compressed_file(&xfer, seqno);
          }else{
            send_file(&xfer, seqno, 0, 1);
          }
          seqno++;
        }
        if( seqno>max ) seqno = 0;







>
>
>
>







1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
          cgi_set_content_type("application/x-fossil-uncompressed");
        }
        blob_is_int(&xfer.aToken[2], &seqno);
        max = db_int(0, "SELECT max(rid) FROM blob");
        while( xfer.mxSend>(int)blob_size(xfer.pOut) && seqno<=max){
          if( time(NULL) >= xfer.maxTime ) break;
          if( iVers>=3 ){
            if( seqno==1 ){
              send_all(&xfer);
              if( xfer.syncPrivate ) send_private(&xfer);
            }
            send_compressed_file(&xfer, seqno);
          }else{
            send_file(&xfer, seqno, 0, 1);
          }
          seqno++;
        }
        if( seqno>max ) seqno = 0;
1756
1757
1758
1759
1760
1761
1762














1763
1764
1765
1766
1767
1768
1769
      /*    pragma req-links
      **
      ** The client sends this message to the server to ask the server
      ** to tell it about alternative repositories  in the reply.
      */
      if( blob_eq(&xfer.aToken[1], "req-links") ){
        bSendLinks = 1;














      }

    }else

    /* Unknown message
    */
    {







>
>
>
>
>
>
>
>
>
>
>
>
>
>







1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
      /*    pragma req-links
      **
      ** The client sends this message to the server to ask the server
      ** to tell it about alternative repositories  in the reply.
      */
      if( blob_eq(&xfer.aToken[1], "req-links") ){
        bSendLinks = 1;
      }else

      /*    pragma send-rebuilt
      **
      ** The client sends this message to the server to ask the server
      ** for the last time its database was rebuilt
      */
      if( blob_eq(&xfer.aToken[1], "send-rebuilt") ){
        Blob rcode;
        blob_zero(&rcode);
        blob_appendf(&rcode, "%s-%s", db_get("server-code",0),
                     db_get_mtime("rebuilt",0,0));
        @ pragma rebuilt %F(blob_str(&rcode))
        blob_reset(&rcode);
      }

    }else

    /* Unknown message
    */
    {
1934
1935
1936
1937
1938
1939
1940














1941
1942
1943
1944
1945
1946
1947

/*
** Floating-point absolute value
*/
static double fossil_fabs(double x){
  return x>0.0 ? x : -x;
}















/*
** Sync to the host identified in g.url.name and g.url.path.  This
** routine is called by the client.
**
** Records are pushed to the server if pushFlag is true.  Records
** are pulled if pullFlag is true.  A full sync occurs if both are







>
>
>
>
>
>
>
>
>
>
>
>
>
>







1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982

/*
** Floating-point absolute value
*/
static double fossil_fabs(double x){
  return x>0.0 ? x : -x;
}

/*
** Used during cloning to exit the sync loop prematurely
*/
static int bSyncGotIntr = 0;
static void sync_sigint_handler(int x){
  bSyncGotIntr = 1;
}
/*
** Interface to check whether sync was interrupted by SIGINT
*/
int sync_interrupted() {
  return bSyncGotIntr;
}

/*
** Sync to the host identified in g.url.name and g.url.path.  This
** routine is called by the client.
**
** Records are pushed to the server if pushFlag is true.  Records
** are pulled if pullFlag is true.  A full sync occurs if both are
1970
1971
1972
1973
1974
1975
1976

1977
1978
1979
1980
1981
1982
1983
  Blob recv;              /* Reply we got back from the server */
  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 */
  int nPriorArtifact = 0; /* Artifacts received on prior round-trips */
  const char *zOpType = 0;/* Push, Pull, Sync, Clone */
  double rSkew = 0.0;     /* Maximum time skew */







>







2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
  Blob recv;              /* Reply we got back from the server */
  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);
  const char *zCCode = 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 */
  int nPriorArtifact = 0; /* Artifacts received on prior round-trips */
  const char *zOpType = 0;/* Push, Pull, Sync, Clone */
  double rSkew = 0.0;     /* Maximum time skew */
1996
1997
1998
1999
2000
2001
2002






2003
2004
2005
2006
2007
2008
2009
  if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
  if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED))==0
     && configRcvMask==0
     && configSendMask==0
  ){
    return 0;  /* Nothing to do */
  }







  /* Compute an appropriate project code.  zPCode is the project code
  ** for the local repository.  zAltPCode will usually be NULL, but might
  ** also be an alternative project code to expect on the server.  When
  ** zAltPCode is not NULL, that means we are doing a cross-project import -
  ** in other words, reading content from one project into a different
  ** project.







>
>
>
>
>
>







2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
  if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
  if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED))==0
     && configRcvMask==0
     && configSendMask==0
  ){
    return 0;  /* Nothing to do */
  }

  if( (syncFlags & SYNC_CLONE)==0 && db_get_int("aux-clone-seqno",0)>0 ){
    fossil_fatal("Unable to synchronize due to incomplete clone.");
  }else if( (syncFlags & SYNC_CLONE)!=0 ){
    cloneSeqno = db_get_int("aux-clone-seqno",1);
  }

  /* Compute an appropriate project code.  zPCode is the project code
  ** for the local repository.  zAltPCode will usually be NULL, but might
  ** also be an alternative project code to expect on the server.  When
  ** zAltPCode is not NULL, that means we are doing a cross-project import -
  ** in other words, reading content from one project into a different
  ** project.
2085
2086
2087
2088
2089
2090
2091
2092







2093
2094
2095
2096
2097
2098
2099
  /*
  ** The request from the client always begin with a clone, pull,
  ** or push message.
  */
  blob_appendf(&send, "pragma client-version %d %d %d\n",
               RELEASE_VERSION_NUMBER, MANIFEST_NUMERIC_DATE,
               MANIFEST_NUMERIC_TIME);
  if( syncFlags & SYNC_CLONE ){







    blob_appendf(&send, "clone 3 %d\n", cloneSeqno);
    syncFlags &= ~(SYNC_PUSH|SYNC_PULL);
    nCardSent++;
    /* TBD: Request all transferable configuration values */
    content_enable_dephantomize(0);
    zOpType = "Clone";
  }else if( syncFlags & SYNC_PULL ){







|
>
>
>
>
>
>
>







2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
  /*
  ** The request from the client always begin with a clone, pull,
  ** or push message.
  */
  blob_appendf(&send, "pragma client-version %d %d %d\n",
               RELEASE_VERSION_NUMBER, MANIFEST_NUMERIC_DATE,
               MANIFEST_NUMERIC_TIME);
  if( (syncFlags & SYNC_CLONE)!=0 ){
#if !defined(_WIN32)
    signal(SIGINT, sync_sigint_handler);
#endif
    if( nCycle<2 ){
      /* Only request this at the beginning of the clone */
      blob_appendf(&send, "pragma send-rebuilt\n");
    }
    blob_appendf(&send, "clone 3 %d\n", cloneSeqno);
    syncFlags &= ~(SYNC_PUSH|SYNC_PULL);
    nCardSent++;
    /* TBD: Request all transferable configuration values */
    content_enable_dephantomize(0);
    zOpType = "Clone";
  }else if( syncFlags & SYNC_PULL ){
2552
2553
2554
2555
2556
2557
2558






2559
2560
2561
2562
2563
2564
2565
       && xfer.nToken==3
       && (syncFlags & SYNC_CLONE)!=0
       && blob_is_hname(&xfer.aToken[2])
      ){
        if( zPCode==0 ){
          zPCode = mprintf("%b", &xfer.aToken[2]);
          db_set("project-code", zPCode, 0);






        }
        if( cloneSeqno>0 ) blob_appendf(&send, "clone 3 %d\n", cloneSeqno);
        nCardSent++;
      }else

      /*   config NAME SIZE \n CONTENT
      **







>
>
>
>
>
>







2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
       && xfer.nToken==3
       && (syncFlags & SYNC_CLONE)!=0
       && blob_is_hname(&xfer.aToken[2])
      ){
        if( zPCode==0 ){
          zPCode = mprintf("%b", &xfer.aToken[2]);
          db_set("project-code", zPCode, 0);
        }
        if( zCCode==0 ){
          if( blob_is_hname(&xfer.aToken[1]) ){
            zCCode = mprintf("%b", &xfer.aToken[1]);
            db_set("aux-clone-code", zCCode, 0);
          }
        }
        if( cloneSeqno>0 ) blob_appendf(&send, "clone 3 %d\n", cloneSeqno);
        nCardSent++;
      }else

      /*   config NAME SIZE \n CONTENT
      **
2741
2742
2743
2744
2745
2746
2747













2748
2749
2750
2751
2752
2753
2754
              "   WHERE mtime<excluded.mtime;",
              zUrl, zArg, iTime
            );
            db_protect_pop();
          }
          url_unparse(&x);
        }














      }else

      /*   error MESSAGE
      **
      ** The server is reporting an error.  The client will abandon
      ** the sync session.







>
>
>
>
>
>
>
>
>
>
>
>
>







2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
              "   WHERE mtime<excluded.mtime;",
              zUrl, zArg, iTime
            );
            db_protect_pop();
          }
          url_unparse(&x);
        }

        /*    pragma rebuilt FOSSILISZESTRING
        **
        ** The server generates this message in response to a client request
        ** that is trying to resume.
        */
        else if( blob_eq(&xfer.aToken[1], "rebuilt")
              && xfer.nToken==3
              && (syncFlags & SYNC_CLONE)!=0
        ){
          zCCode = mprintf("%b", &xfer.aToken[2]);
          db_set("aux-clone-code", zCCode, 0);
        }

      }else

      /*   error MESSAGE
      **
      ** The server is reporting an error.  The client will abandon
      ** the sync session.
2810
2811
2812
2813
2814
2815
2816





2817
2818
2819
2820
2821
2822
2823
      fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
                   nRoundtrip, nArtifactSent, nArtifactRcvd);
    }
    nUncRcvd += blob_size(&recv);
    blob_reset(&recv);
    nCycle++;






    /* Set go to 1 if we need to continue the sync/push/pull/clone for
    ** another round.  Set go to 0 if it is time to quit. */
    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;







>
>
>
>
>







2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
      fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
                   nRoundtrip, nArtifactSent, nArtifactRcvd);
    }
    nUncRcvd += blob_size(&recv);
    blob_reset(&recv);
    nCycle++;

    /* Record the current cloneSeqno in the event that clone fails. This
    ** enables the ability to resume from this same point in clone. */
    if( (syncFlags & SYNC_CLONE)!=0 ){
      db_set_int("aux-clone-seqno", cloneSeqno, 0);
    }
    /* Set go to 1 if we need to continue the sync/push/pull/clone for
    ** another round.  Set go to 0 if it is time to quit. */
    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;
2836
2837
2838
2839
2840
2841
2842




2843
2844
2845
2846
2847
2848
2849
      }else if( nFileRecv>0 ){
        go = 1;
      }else if( cloneSeqno>0 && nArtifactRcvd>nPriorArtifact ){
        /* Continue the clone until we see the clone_seqno 0" card or
        ** until we stop receiving artifacts */
        go = 1;
      }




    }

    nCardRcvd = 0;
    xfer.nFileRcvd = 0;
    xfer.nDeltaRcvd = 0;
    xfer.nDanglingFile = 0;
    db_multi_exec("DROP TABLE onremote; DROP TABLE unk;");







>
>
>
>







2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
      }else if( nFileRecv>0 ){
        go = 1;
      }else if( cloneSeqno>0 && nArtifactRcvd>nPriorArtifact ){
        /* Continue the clone until we see the clone_seqno 0" card or
        ** until we stop receiving artifacts */
        go = 1;
      }
    }
    if( (syncFlags & SYNC_CLONE)!=0 && bSyncGotIntr && cloneSeqno>0 ){
      go = 0;
      nErr++;
    }

    nCardRcvd = 0;
    xfer.nFileRcvd = 0;
    xfer.nDeltaRcvd = 0;
    xfer.nDanglingFile = 0;
    db_multi_exec("DROP TABLE onremote; DROP TABLE unk;");