-C Port\ssome\sof\sthe\sshell's\sCLI\sflag-handling\scode\sinto\ssqlite3-rsync\sto\smake\sthe\sarg\shandling\smore\srobust.
-D 2024-09-12T18:15:28.846
+C Convert\ssqlite3-rsync.c\sto\suse\sthe\sext/consio\sI/O\slibrary.\sThe\scaveat\sis\sthat\sit\srequires\sdirect\sinclusion\sof\sthe\sconsio\ssource\scode,\smaking\ssqlite3-rsync.c\sno\slonger\sa\sstandalone\sfile.
+D 2024-09-12T20:50:16.673
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
-F Makefile.in 4ac84300552e9ab8245288dec9941b6b820b48e15cbcd7c87db2ce45998c62f8
+F Makefile.in dd8e98b6437b73a8a3bdbb1cc3812d8965e46759d0c6b0d84cfdc848f0b860cb
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
F Makefile.msc f25c476f22a25f23af8dc7260e9f95896250e7fceb621388ca8ae4f096bd3fda
F README.md c3c0f19532ce28f6297a71870f3c7b424729f0e6d9ab889616d3587dd2332159
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
F tool/split-sqlite3c.tcl 5aa60643afca558bc732b1444ae81a522326f91e1dc5665b369c54f09e20de60
F tool/sqldiff.c 847fc8fcfddf5ce4797b7394cad6372f2f5dc17d8186e2ef8fb44d50fae4f44a
-F tool/sqlite3-rsync.c 20783cd979df8c32d33eab3c38c44a79343be63a73b6cbd1ee56a0a14d73b3fe
+F tool/sqlite3-rsync.c a0521dbb5dd335834a101f9e562a35c4fbd3a844bc3ba989d3463fa81abcf84d
F tool/sqlite3_analyzer.c.in 8da2b08f56eeac331a715036cf707cc20f879f231362be0c22efd682e2b89b4f
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P e385525793c7d74ce8ee139c9d6cfc1248834754598f3fd45b22b9426ff106ee
-R 2634868962b675f42ebfd90b6ccf2615
+P 53fb9b11807ff7accd8cd41f9cb6516d2503f161ea976940437a1d3aae868665
+R 4bb3e75cba104380172bbda59929fb5d
+T *branch * sqlite3-rsync-consio
+T *sym-sqlite3-rsync-consio *
+T -sym-sqlite3-rsync * Cancelled\sby\sbranch.
U stephan
-Z ca092fee4c8dab92860037cbb2c82076
+Z 9e59548ff1a12e5f4219e9ef4eda27f0
# Remove this line to create a well-formed Fossil manifest.
#include <stdarg.h>
#include "sqlite3.h"
-static const char zUsage[] =
+static const char zUsage[] =
"sqlite3-rsync ORIGIN REPLICA ?OPTIONS?\n"
"\n"
"One of ORIGIN or REPLICA is a pathname to a database on the local\n"
#define REPLICA_READY 0x65 /* Read to receive page content */
#define REPLICA_MSG 0x66 /* Informational message */
+/* From here onward, fgets() is redirected to the console_io library. */
+# define fgets(b,n,f) fGetsUtf8(b,n,f)
+/*
+ * Define macros for emitting output text in various ways:
+ * sputz(s, z) => emit 0-terminated string z to given stream s
+ * sputf(s, f, ...) => emit varargs per format f to given stream s
+ * oputz(z) => emit 0-terminated string z to default stream
+ * oputf(f, ...) => emit varargs per format f to default stream
+ * eputz(z) => emit 0-terminated string z to error stream
+ * eputf(f, ...) => emit varargs per format f to error stream
+ * oputb(b, n) => emit char buffer b[0..n-1] to default stream
+ *
+ * Note that the default stream is whatever has been last set via:
+ * setOutputStream(FILE *pf)
+ * This is normally the stream that CLI normal output goes to.
+ * For the stand-alone CLI, it is stdout with no .output redirect.
+ *
+ * The ?putz(z) forms are for unformatted strings.
+ */
+# define sputz(s,z) fPutsUtf8(z,s)
+# define sputf fPrintfUtf8
+# define oputz(z) oPutsUtf8(z)
+# define oputf oPrintfUtf8
+# define eputz(z) ePutsUtf8(z)
+# define eputf ePrintfUtf8
+# define oputb(buf,na) oPutbUtf8(buf,na)
/****************************************************************************
** Beginning of the popen2() implementation copied from Fossil *************
** Print a fatal error and quit.
*/
static void win32_fatal_error(const char *zMsg){
- fprintf(stderr, "%s", zMsg);
+ eputz("%s\n", zMsg);
exit(1);
}
#else
#include <sys/wait.h>
#endif
+#define SQLITE_INTERNAL_LINKAGE static
+#define CONSIO_SET_ERROR_STREAM
+#include "ext/consio/console_io.c"
+#define fflush(s) fFlushBuffer(s) /* must be defined AFTER console_io.c */
+
/*
** The following macros are used to cast pointers to integers and
** integers to pointers. The way you do this varies from one compiler
close(0);
fd = dup(pout[0]);
if( fd!=0 ) {
- fprintf(stderr,"popen2() failed to open file descriptor 0");
+ eputz("popen2() failed to open file descriptor 0\n");
exit(1);
}
close(pout[0]);
close(1);
fd = dup(pin[1]);
if( fd!=1 ){
- fprintf(stderr,"popen() failed to open file descriptor 1");
+ eputz("popen() failed to open file descriptor 1\n");
exit(1);
}
close(pin[0]);
writeBytes(p, nMsg, zMsg);
fflush(p->pOut);
}else{
- fprintf(stderr, "%s\n", zMsg);
+ eputf("%s\n", zMsg);
}
sqlite3_free(zMsg);
p->nErr++;
/* Send an informational message.
**
-** If this happens on the remote side, we send back a *_MSG
+** If this happens on the remote side, we send back a *_MSG
** message. On the local side, the message goes to stdout.
*/
static void infoMsg(SQLiteRsync *p, const char *zFormat, ...){
writeBytes(p, nMsg, zMsg);
fflush(p->pOut);
}else{
- printf("%s\n", zMsg);
+ oputf("%s\n", zMsg);
}
sqlite3_free(zMsg);
}
}
readUint32(p, &n);
if( n==0 ){
- fprintf(stderr,"ERROR: unknown (possibly out-of-memory)\n");
+ eputz("ERROR: unknown (possibly out-of-memory)\n");
}else{
zMsg = sqlite3_malloc64( n+1 );
if( zMsg==0 ){
- fprintf(stderr, "ERROR: out-of-memory\n");
+ eputz("ERROR: out-of-memory\n");
return;
}
memset(zMsg, 0, n+1);
readBytes(p, n, zMsg);
- fprintf(stderr,"%s%s\n", zPrefix, zMsg);
+ eputf("%s%s\n", zPrefix, zMsg);
sqlite3_free(zMsg);
}
}
}
runSqlReturnUInt(p, &nPage, "PRAGMA page_count");
runSqlReturnUInt(p, &szPg, "PRAGMA page_size");
-
+
if( p->nErr==0 ){
/* Send the ORIGIN_BEGIN message */
writeByte(p, ORIGIN_BEGIN);
p->iProtocol = PROTOCOL_VERSION;
}
}
-
+
/* Respond to message from the replica */
while( p->nErr==0 && (c = readByte(p))!=EOF && c!=REPLICA_END ){
switch( c ){
static const char *cmdline_option_value(int argc, const char * const*argv,
int i){
if( i==argc ){
- fprintf(stderr,"%s: Error: missing argument to %s\n",
- argv[0], argv[argc-1]);
+ eputf("%s: Error: missing argument to %s\n",
+ argv[0], argv[argc-1]);
exit(1);
}
return argv[i];
#define cli_opt_val cmdline_option_value(argc, argv, ++i)
memset(&ctx, 0, sizeof(ctx));
+ setOutputStream(stdout);
+ setErrorStream(stderr);
for(i=1; i<argc; i++){
const char *z = argv[i];
if( strcmp(z,"--origin")==0 ){
if( strcmp(z, "-help")==0 || strcmp(z, "--help")==0
|| strcmp(z, "-?")==0
){
- printf("%s", zUsage);
+ oputf("%s", zUsage);
return 0;
}
if( z[0]=='-' ){
for(k=0; k<argc; k++){
append_escaped_arg(pStr, argv[k], i!=k);
}
- printf("%s\n", sqlite3_str_value(pStr));
+ oputf("%s\n", sqlite3_str_value(pStr));
return 0;
}
- fprintf(stderr,
- "unknown option: \"%s\". Use --help for more detail.\n", z);
+ eputf("unknown option: \"%s\". Use --help for more detail.\n", z);
return 1;
}
if( ctx.zOrigin==0 ){
}else if( ctx.zReplica==0 ){
ctx.zReplica = z;
}else{
- fprintf(stderr, "Unknown argument: \"%s\"\n", z);
+ eputf("Unknown argument: \"%s\"\n", z);
return 1;
}
}
if( ctx.zOrigin==0 ){
- fprintf(stderr, "missing ORIGIN database filename\n");
+ eputz("missing ORIGIN database filename\n");
return 1;
}
if( ctx.zReplica==0 ){
- fprintf(stderr, "missing REPLICA database filename\n");
+ eputz("missing REPLICA database filename\n");
return 1;
}
if( isOrigin && isReplica ){
- fprintf(stderr, "bad option combination\n");
+ eputz("bad option combination\n");
return 1;
}
if( isOrigin ){
return 0;
}
if( ctx.zReplica==0 ){
- fprintf(stderr, "missing REPLICA database filename\n");
+ eputz("missing REPLICA database filename\n");
return 1;
}
zDiv = strchr(ctx.zOrigin,':');
if( zDiv ){
if( strchr(ctx.zReplica,':')!=0 ){
- fprintf(stderr,
+ eputz(
"At least one of ORIGIN and REPLICA must be a local database\n"
"You provided two remote databases.\n");
return 1;
append_escaped_arg(pStr, zDiv, 1);
append_escaped_arg(pStr, file_tail(ctx.zReplica), 1);
zCmd = sqlite3_str_finish(pStr);
- if( ctx.eVerbose ) printf("%s\n", zCmd);
+ if( ctx.eVerbose ) oputf("%s\n", zCmd);
if( popen2(zCmd, &ctx.pIn, &ctx.pOut, &childPid, 0) ){
- fprintf(stderr, "Could not start auxiliary process: %s\n", zCmd);
+ eputf("Could not start auxiliary process: %s\n", zCmd);
return 1;
}
replicaSide(&ctx);
append_escaped_arg(pStr, file_tail(ctx.zOrigin), 1);
append_escaped_arg(pStr, zDiv, 1);
zCmd = sqlite3_str_finish(pStr);
- if( ctx.eVerbose ) printf("%s\n", zCmd);
+ if( ctx.eVerbose ) oputf("%s\n", zCmd);
if( popen2(zCmd, &ctx.pIn, &ctx.pOut, &childPid, 0) ){
- fprintf(stderr, "Could not start auxiliary process: %s\n", zCmd);
+ eputf("Could not start auxiliary process: %s\n", zCmd);
return 1;
}
originSide(&ctx);
append_escaped_arg(pStr, ctx.zOrigin, 1);
append_escaped_arg(pStr, ctx.zReplica, 1);
zCmd = sqlite3_str_finish(pStr);
- if( ctx.eVerbose ) printf("%s\n", zCmd);
+ if( ctx.eVerbose ) oputf("%s\n", zCmd);
if( popen2(zCmd, &ctx.pIn, &ctx.pOut, &childPid, 0) ){
- fprintf(stderr, "Could not start auxiliary process: %s\n", zCmd);
+ eputf("Could not start auxiliary process: %s\n", zCmd);
return 1;
}
originSide(&ctx);
}
if( ctx.eVerbose ){
- if( ctx.nErr ) printf("%d errors, ", ctx.nErr);
- printf("%lld bytes sent, %lld bytes received\n", ctx.nOut, ctx.nIn);
+ if( ctx.nErr ) oputf("%d errors, ", ctx.nErr);
+ oputf("%lld bytes sent, %lld bytes received\n", ctx.nOut, ctx.nIn);
if( ctx.eVerbose>=2 ){
- printf("Database is %u pages of %u bytes each.\n",
+ oputf("Database is %u pages of %u bytes each.\n",
ctx.nPage, ctx.szPage);
- printf("Sent %u hashes, %u page contents\n",
+ oputf("Sent %u hashes, %u page contents\n",
ctx.nHashSent, ctx.nPageSent);
}
}