Fossil

Check-in [3be414357f]
Login

Check-in [3be414357f]

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

Overview
Comment:Change the synclog to keep timestamps with unixepoch(). This requires SQLite 3.38.0.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | synclog
Files: files | file ages | folders
SHA3-256: 3be414357f8056651eb7da6d5d78b3949060b6ef228370daa470704fabad8dee
User & Date: drh 2021-12-20 08:37:02.159
Context
2021-12-20
08:39
Merge latest changes from trunk. ... (check-in: 3348c66e3d user: drh tags: synclog)
08:37
Change the synclog to keep timestamps with unixepoch(). This requires SQLite 3.38.0. ... (check-in: 3be414357f user: drh tags: synclog)
2021-12-19
23:07
Avoid a possibly unnecessary call to db_prepare() when doing a config sync. ... (check-in: d57a63254c user: drh tags: synclog)
Changes
Unified Diff Ignore Whitespace Patch
Changes to auto.def.
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
    no-opt=0             => {Build without optimization}
    json=0               => {Build with fossil JSON API enabled}
}

# Update the minimum required SQLite version number here, and also
# in src/main.c near the sqlite3_libversion_number() call.  Take care
# that both places agree!
define MINIMUM_SQLITE_VERSION "3.37.0"

# This is useful for people wanting Fossil to use an external SQLite library
# to compare the one they have against the minimum required
if {[opt-bool print-minimum-sqlite-version]} {
    puts [get-define MINIMUM_SQLITE_VERSION]
    exit 0
}







|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
    no-opt=0             => {Build without optimization}
    json=0               => {Build with fossil JSON API enabled}
}

# Update the minimum required SQLite version number here, and also
# in src/main.c near the sqlite3_libversion_number() call.  Take care
# that both places agree!
define MINIMUM_SQLITE_VERSION "3.38.0"

# This is useful for people wanting Fossil to use an external SQLite library
# to compare the one they have against the minimum required
if {[opt-bool print-minimum-sqlite-version]} {
    puts [get-define MINIMUM_SQLITE_VERSION]
    exit 0
}
Changes to src/export.c.
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
    const char *zRepack = "git repack -adf";
    gitmirror_message(VERB_NORMAL, "%s\n", zRepack);
    fossil_system(zRepack);
  }

  /* Record this export into the sync log */
  zMirrorAbs = file_canonical_name_dup(zMirror);
  sync_log_entry(SYNC_PUSH, zMirrorAbs, "git");
  fossil_free(zMirrorAbs);

  /* Optionally do a "git push" */
  zPushUrl = db_text(0, "SELECT value FROM mconfig WHERE key='autopush'");
  if( zPushUrl ){
    char *zPushCmd;
    UrlData url;







|







1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
    const char *zRepack = "git repack -adf";
    gitmirror_message(VERB_NORMAL, "%s\n", zRepack);
    fossil_system(zRepack);
  }

  /* Record this export into the sync log */
  zMirrorAbs = file_canonical_name_dup(zMirror);
  sync_log_entry(SYNC_PUSH, zMirrorAbs, "git", 0);
  fossil_free(zMirrorAbs);

  /* Optionally do a "git push" */
  zPushUrl = db_text(0, "SELECT value FROM mconfig WHERE key='autopush'");
  if( zPushUrl ){
    char *zPushCmd;
    UrlData url;
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
    if( rc ){
      fossil_fatal("cannot push content using: %s", zPushCmd);
    }else if( db_is_writeable("repository") ){
      db_unprotect(PROTECT_CONFIG);
      db_multi_exec("REPLACE INTO config(name,value,mtime)"
                    "VALUES('gitpush:%q',1,now())", zPushUrl);
      db_protect_pop();
      sync_log_entry(SYNC_PUSH, zPushUrl, "git-push");
    }
    fossil_free(zPushCmd);
  }
}

/*
** Implementation of the "fossil git status" command.







|







1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
    if( rc ){
      fossil_fatal("cannot push content using: %s", zPushCmd);
    }else if( db_is_writeable("repository") ){
      db_unprotect(PROTECT_CONFIG);
      db_multi_exec("REPLACE INTO config(name,value,mtime)"
                    "VALUES('gitpush:%q',1,now())", zPushUrl);
      db_protect_pop();
      sync_log_entry(SYNC_PUSH, zPushUrl, "git-push", 0);
    }
    fossil_free(zPushCmd);
  }
}

/*
** Implementation of the "fossil git status" command.
Changes to src/main.c.
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
  fossil_printf_selfcheck();
  fossil_limit_memory(1);

  /* When updating the minimum SQLite version, change the number here,
  ** and also MINIMUM_SQLITE_VERSION value set in ../auto.def.  Take
  ** care that both places agree! */
  if( sqlite3_libversion_number()<3037000 ){
    fossil_panic("Unsuitable SQLite version %s, must be at least 3.37.0",
                 sqlite3_libversion());
  }

  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
  sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
  memset(&g, 0, sizeof(g));
  g.now = time(0);







|







699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
  fossil_printf_selfcheck();
  fossil_limit_memory(1);

  /* When updating the minimum SQLite version, change the number here,
  ** and also MINIMUM_SQLITE_VERSION value set in ../auto.def.  Take
  ** care that both places agree! */
  if( sqlite3_libversion_number()<3037000 ){
    fossil_panic("Unsuitable SQLite version %s, must be at least 3.38.0",
                 sqlite3_libversion());
  }

  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
  sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
  memset(&g, 0, sizeof(g));
  g.now = time(0);
Changes to src/schema.c.
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
/*
** The following table holds information about servers with which
** this repository has synced, as well as servers with which those 
** servers have synced, and so forth.
*/
static const char zSynclogSchema[] =
@ CREATE TABLE repository.synclog(
@   sfrom TEXT,        -- Sync client. "self" means this repo
@   sto TEXT,          -- Sync server
@   stime DATETIME,    -- Time of transfer (julian day)
@   stype TEXT,        -- "push", "pull", "git", "backup", "import", etc...
@   PRIMARY KEY(sfrom,sto)
@ ) WITHOUT ROWID;
;

/* Create the forum-post schema if it does not already exist */
void schema_synclog(void){
  if( !db_table_exists("repository","synclog") ){







|
|
|
|







624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
/*
** The following table holds information about servers with which
** this repository has synced, as well as servers with which those 
** servers have synced, and so forth.
*/
static const char zSynclogSchema[] =
@ CREATE TABLE repository.synclog(
@   sfrom TEXT,          -- Sync client. "self" means this repo
@   sto TEXT,            -- Sync server
@   stime INT NOT NULL,  -- Time of transfer (unixepoch)
@   stype TEXT,          -- "push", "pull", "git", "backup", "import", etc...
@   PRIMARY KEY(sfrom,sto)
@ ) WITHOUT ROWID;
;

/* Create the forum-post schema if it does not already exist */
void schema_synclog(void){
  if( !db_table_exists("repository","synclog") ){
Changes to src/sync.c.
107
108
109
110
111
112
113
114

115
116


117
118
119
120

121


122





123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
** the zRemote parameter.  sto+sfrom form the primary key.  If an entry
** already exists with the same primary key, then the spull or spush times
** are updated (or both).
*/
void sync_log_entry(
  int syncFlags,            /* Indicates whether a PUSH or PULL or both */
  const char *zRemote,      /* Server with which we push or pull */
  const char *zType         /* Type of sync.  NULL for normal */

){
  Stmt s;


  db_prepare(&s,
    "INSERT INTO repository.synclog(sfrom,sto,stime,stype)"
    " VALUES(:sfrom,:sto,julianday(),:stype)"
    " ON CONFLICT DO UPDATE SET stime=julianday()"

  );


  schema_synclog();





  if( syncFlags & (SYNC_PULL|SYNC_CLONE) ){
    db_bind_text(&s, ":sfrom", zRemote);
    db_bind_text(&s, ":sto", "this");
    db_bind_text(&s, ":stype", zType);
    db_step(&s);
    db_reset(&s);
  }
  if( syncFlags & (SYNC_PUSH) ){
    db_bind_text(&s, ":sfrom", "this");
    db_bind_text(&s, ":sto", zRemote);
    db_bind_text(&s, ":stype", zType);
    db_step(&s);
  }
  db_finalize(&s);
}


/*







|
>


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



<






<







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

137
138
139
140
141
142

143
144
145
146
147
148
149
** the zRemote parameter.  sto+sfrom form the primary key.  If an entry
** already exists with the same primary key, then the spull or spush times
** are updated (or both).
*/
void sync_log_entry(
  int syncFlags,            /* Indicates whether a PUSH or PULL or both */
  const char *zRemote,      /* Server with which we push or pull */
  const char *zType,        /* Type of sync.  NULL for normal */
  i64 iTime                 /* Seconds since 1970, or 0 for "now" */
){
  Stmt s;
  schema_synclog();
  if( iTime<=0 ){
    db_prepare(&s,
      "INSERT INTO repository.synclog(sfrom,sto,stime,stype)"
      " VALUES(:sfrom,:sto,unixepoch(),%Q)"
      " ON CONFLICT DO UPDATE SET stime=unixepoch()",
      zType
    );
  }else{
    db_prepare(&s,
      "INSERT INTO repository.synclog(sfrom,sto,stime,stype)"
      " VALUES(:sfrom,:sto,%lld,%Q)"
      " ON CONFLICT DO UPDATE SET stime=%lld WHERE stime<%lld",
      iTime, zType, iTime, iTime
    );
  }
  if( syncFlags & (SYNC_PULL|SYNC_CLONE) ){
    db_bind_text(&s, ":sfrom", zRemote);
    db_bind_text(&s, ":sto", "this");

    db_step(&s);
    db_reset(&s);
  }
  if( syncFlags & (SYNC_PUSH) ){
    db_bind_text(&s, ":sfrom", "this");
    db_bind_text(&s, ":sto", zRemote);

    db_step(&s);
  }
  db_finalize(&s);
}


/*
271
272
273
274
275
276
277



278
279
280
281
282
283
284
    *pSyncFlags |= SYNC_VERBOSE;
  }
  if( find_option("no-http-compression",0,0)!=0 ){
    *pSyncFlags |= SYNC_NOHTTPCOMPRESS;
  }
  if( find_option("all",0,0)!=0 ){
    *pSyncFlags |= SYNC_ALLURL;



  }
  url_proxy_options();
  clone_ssh_find_options();
  if( !uvOnly ) db_find_and_open_repository(0, 0);
  db_open_config(0, 1);
  if( g.argc==2 ){
    if( db_get_boolean("auto-shun",0) ) configSync = CONFIGSET_SHUN;







>
>
>







280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
    *pSyncFlags |= SYNC_VERBOSE;
  }
  if( find_option("no-http-compression",0,0)!=0 ){
    *pSyncFlags |= SYNC_NOHTTPCOMPRESS;
  }
  if( find_option("all",0,0)!=0 ){
    *pSyncFlags |= SYNC_ALLURL;
  }
  if( find_option("synclog",0,0)!=0 ){
    *pSyncFlags |= SYNC_PUSH_SYNCLOG;
  }
  url_proxy_options();
  clone_ssh_find_options();
  if( !uvOnly ) db_find_and_open_repository(0, 0);
  db_open_config(0, 1);
  if( g.argc==2 ){
    if( db_get_boolean("auto-shun",0) ) configSync = CONFIGSET_SHUN;
745
746
747
748
749
750
751
752
753
754
    }else{
      fossil_fatal("backup \"%s\" already exists", zDest);
    }
  }
  db_unprotect(PROTECT_ALL);
  db_multi_exec("VACUUM repository INTO %Q", zDest);
  zFullName = file_canonical_name_dup(zDest);
  sync_log_entry(SYNC_PUSH, zFullName, "backup");
  fossil_free(zFullName);
}







|


757
758
759
760
761
762
763
764
765
766
    }else{
      fossil_fatal("backup \"%s\" already exists", zDest);
    }
  }
  db_unprotect(PROTECT_ALL);
  db_multi_exec("VACUUM repository INTO %Q", zDest);
  zFullName = file_canonical_name_dup(zDest);
  sync_log_entry(SYNC_PUSH, zFullName, "backup", 0);
  fossil_free(zFullName);
}
Changes to src/xfer.c.
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826

1827
1828
1829
1830
1831
1832
1833
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    /* push content client to server */
#define SYNC_PULL           0x0002    /* pull content server to client */
#define SYNC_CLONE          0x0004    /* clone the repository */
#define SYNC_PRIVATE        0x0008    /* Also transfer private content */
#define SYNC_VERBOSE        0x0010    /* Extra diagnostics */
#define SYNC_RESYNC         0x0020    /* --verily */
#define SYNC_FROMPARENT     0x0040    /* Pull from the parent project */
#define SYNC_UNVERSIONED    0x0100    /* Sync unversioned content */
#define SYNC_UV_REVERT      0x0200    /* Copy server unversioned to client */
#define SYNC_UV_TRACE       0x0400    /* Describe UV activities */
#define SYNC_UV_DRYRUN      0x0800    /* Do not actually exchange files */
#define SYNC_IFABLE         0x1000    /* Inability to sync is not fatal */
#define SYNC_CKIN_LOCK      0x2000    /* Lock the current check-in */
#define SYNC_NOHTTPCOMPRESS 0x4000    /* Do not compression HTTP messages */
#define SYNC_ALLURL         0x8000    /* The --all flag - sync to all URLs */

#endif

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







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







1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
static const char zBriefFormat[] =
   "Round-trips: %d   Artifacts sent: %d  received: %d\r";

#if INTERFACE
/*
** Flag options for controlling client_sync()
*/
#define SYNC_PUSH           0x00001    /* push content client to server */
#define SYNC_PULL           0x00002    /* pull content server to client */
#define SYNC_CLONE          0x00004    /* clone the repository */
#define SYNC_PRIVATE        0x00008    /* Also transfer private content */
#define SYNC_VERBOSE        0x00010    /* Extra diagnostics */
#define SYNC_RESYNC         0x00020    /* --verily */
#define SYNC_FROMPARENT     0x00040    /* Pull from the parent project */
#define SYNC_UNVERSIONED    0x00100    /* Sync unversioned content */
#define SYNC_UV_REVERT      0x00200    /* Copy server unversioned to client */
#define SYNC_UV_TRACE       0x00400    /* Describe UV activities */
#define SYNC_UV_DRYRUN      0x00800    /* Do not actually exchange files */
#define SYNC_IFABLE         0x01000    /* Inability to sync is not fatal */
#define SYNC_CKIN_LOCK      0x02000    /* Lock the current check-in */
#define SYNC_NOHTTPCOMPRESS 0x04000    /* Do not compression HTTP messages */
#define SYNC_ALLURL         0x08000    /* The --all flag - sync to all URLs */
#define SYNC_PUSH_SYNCLOG   0x10000    /* Uplink SYNCLOG info */
#endif

/*
** Floating-point absolute value
*/
static double fossil_fabs(double x){
  return x>0.0 ? x : -x;
2520
2521
2522
2523
2524
2525
2526











2527
2528
2529
2530
2531
2532
2533
        if( xfer.nToken>=3 && blob_eq(&xfer.aToken[1], "server-version") ){
          xfer.remoteVersion = atoi(blob_str(&xfer.aToken[2]));
          if( xfer.nToken>=5 ){
            xfer.remoteDate = atoi(blob_str(&xfer.aToken[3]));
            xfer.remoteTime = atoi(blob_str(&xfer.aToken[4]));
          }
        }












        /*   pragma uv-pull-only
        **   pragma uv-push-ok
        **
        ** If the server is unwill to accept new unversioned content (because
        ** this client lacks the necessary permissions) then it sends a
        ** "uv-pull-only" pragma so that the client will know not to waste







>
>
>
>
>
>
>
>
>
>
>







2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
        if( xfer.nToken>=3 && blob_eq(&xfer.aToken[1], "server-version") ){
          xfer.remoteVersion = atoi(blob_str(&xfer.aToken[2]));
          if( xfer.nToken>=5 ){
            xfer.remoteDate = atoi(blob_str(&xfer.aToken[3]));
            xfer.remoteTime = atoi(blob_str(&xfer.aToken[4]));
          }
        }

        /*   pragma synclog FROM TO MTIME TYPE
        **
        ** The server is downloading an entry from its SYNCLOG table.  Merge
        ** this into the local SYNCLOG table if appropriate.
        ** is running.  The DATE and TIME are a pure numeric ISO8601 time
        ** for the specific check-in of the client.
        */
        if( xfer.nToken==5 && blob_eq(&xfer.aToken[1], "synclog") ){
          /* TBD */
        }

        /*   pragma uv-pull-only
        **   pragma uv-push-ok
        **
        ** If the server is unwill to accept new unversioned content (because
        ** this client lacks the necessary permissions) then it sends a
        ** "uv-pull-only" pragma so that the client will know not to waste
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
  }else if( rSkew*24.0*3600.0 < -10.0 ){
     fossil_warning("*** time skew *** server is slow by %s",
                    db_timespan_name(-rSkew));
     g.clockSkewSeen = 1;
  }

  if( nErr==0 ){
    sync_log_entry(syncFlags, g.url.canonical,  zAltPCode!=0 ? "import" : 0);
  }

  fossil_force_newline();
  fossil_print(
     "%s done, wire bytes sent: %lld  received: %lld  ip: %s\n",
     zOpType, nSent, nRcvd, g.zIpAddr);
  if( syncFlags & SYNC_VERBOSE ){







|







2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
  }else if( rSkew*24.0*3600.0 < -10.0 ){
     fossil_warning("*** time skew *** server is slow by %s",
                    db_timespan_name(-rSkew));
     g.clockSkewSeen = 1;
  }

  if( nErr==0 ){
    sync_log_entry(syncFlags, g.url.canonical,  zAltPCode!=0 ? "import" : 0, 0);
  }

  fossil_force_newline();
  fossil_print(
     "%s done, wire bytes sent: %lld  received: %lld  ip: %s\n",
     zOpType, nSent, nRcvd, g.zIpAddr);
  if( syncFlags & SYNC_VERBOSE ){