Fossil

Check-in [a9463a71]
Login

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

Overview
Comment:Incremental check-in. (Saving my place in order to go work on other things.) Changes are untested.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | unversioned-files
Files: files | file ages | folders
SHA1: a9463a7157129ee3cb6ecd1ca681c3b6f5a256a1
User & Date: drh 2016-08-05 08:30:18
Context
2016-08-05
12:30
Add the /uv webpage. check-in: 440defe2 user: drh tags: unversioned-files
08:30
Incremental check-in. (Saving my place in order to go work on other things.) Changes are untested. check-in: a9463a71 user: drh tags: unversioned-files
2016-08-04
22:49
Begin work on the ability to store and sync files for which no history is kept. check-in: 4ce1c9b2 user: drh tags: unversioned-files
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/content.c.

450
451
452
453
454
455
456














457
458
459
460
461
462
463
...
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549

/*
** Turn dephantomization processing on or off.
*/
void content_enable_dephantomize(int onoff){
  ignoreDephantomizations = !onoff;
}















/*
** Write content into the database.  Return the record ID.  If the
** content is already in the database, just return the record ID.
**
** If srcId is specified, then pBlob is delta content from
** the srcId record.  srcId might be a phantom.
................................................................................
  }else{
    rid = 0;  /* No entry with the same UUID currently exists */
    markAsUnclustered = 1;
  }
  db_finalize(&s1);

  /* Construct a received-from ID if we do not already have one */
  if( g.rcvid==0 ){
    db_multi_exec(
       "INSERT INTO rcvfrom(uid, mtime, nonce, ipaddr)"
       "VALUES(%d, julianday('now'), %Q, %Q)",
       g.userUid, g.zNonce, g.zIpAddr
    );
    g.rcvid = db_last_insert_rowid();
  }

  if( nBlob ){
    cmpr = pBlob[0];
  }else{
    blob_compress(pBlob, &cmpr);
  }
  if( rid>0 ){







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







 







|
<
<
<
<
<
<
<







450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
...
542
543
544
545
546
547
548
549







550
551
552
553
554
555
556

/*
** Turn dephantomization processing on or off.
*/
void content_enable_dephantomize(int onoff){
  ignoreDephantomizations = !onoff;
}

/*
** Make sure the g.rcvid global variable has been initialized.
*/
void content_rcvid_init(void){
  if( g.rcvid==0 ){
    db_multi_exec(
       "INSERT INTO rcvfrom(uid, mtime, nonce, ipaddr)"
       "VALUES(%d, julianday('now'), %Q, %Q)",
       g.userUid, g.zNonce, g.zIpAddr
    );
    g.rcvid = db_last_insert_rowid();
  }
}

/*
** Write content into the database.  Return the record ID.  If the
** content is already in the database, just return the record ID.
**
** If srcId is specified, then pBlob is delta content from
** the srcId record.  srcId might be a phantom.
................................................................................
  }else{
    rid = 0;  /* No entry with the same UUID currently exists */
    markAsUnclustered = 1;
  }
  db_finalize(&s1);

  /* Construct a received-from ID if we do not already have one */
  content_rcvid_init();








  if( nBlob ){
    cmpr = pBlob[0];
  }else{
    blob_compress(pBlob, &cmpr);
  }
  if( rid>0 ){

Changes to src/unversioned.c.

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
...
102
103
104
105
106
107
108



































109
110

















111
112
113
114
115
116
117
...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#else
#  include <zlib.h>
#endif
#include "unversioned.h"
#include <time.h>

/*
** SQL code to implement the tables needed by the unverioned.
*/
static const char zUnversionedInit[] =
@ CREATE TABLE IF NOT EXISTS "%w".unversioned(
@   name TEXT PRIMARY KEY,       -- Name of the uv file
@   rcvid INTEGER,               -- Where received from
@   mtime DATETIME,              -- timestamp.  Seconds since 1970.
@   hash TEXT,                   -- Content hash
................................................................................
  if( zMtime==0 ){
    mtime = time(0);
  }else{
    mtime = db_int(0, "SELECT strftime('%%s',%Q)", zMtime);
    if( mtime<=0 ) fossil_fatal("bad timestamp: %Q", zMtime);
  }
  if( memcmp(zCmd, "add", nCmd)==0 ){



































  }else if( memcmp(zCmd, "cat", nCmd)==0 ){
  }else if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){

















  }else if( memcmp(zCmd, "revert", nCmd)==0 || memcmp(zCmd,"sync",nCmd)==0 ){
    fossil_fatal("not yet implemented...");
  }else if( memcmp(zCmd, "rm", nCmd)==0 ){
  }else{
    usage("add|cat|ls|revert|rm|sync");
  }
}
................................................................................

    uvfile NAME TIMESTAMP SIZE FLAGS \n CONTENT

The client sends uvgimme if 

   (a) it does not possess NAME or
   (b) if the NAME it holds has an earlier timestamp than TIMESTAMP or
   (c) if the NAME it holds has the exact timestamp TIMESATMP but a
       lexicographically earliers HASH.

Otherwise the client sends a uvfile.  The client also sends uvfile
cards for each unversioned file it holds which was not named by any
uvigot card.

On the uvfile card, the FLAGS value is an unsigned integer with







|







 







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


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







 







|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
...
102
103
104
105
106
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#else
#  include <zlib.h>
#endif
#include "unversioned.h"
#include <time.h>

/*
** SQL code to implement the tables needed by the unversioned.
*/
static const char zUnversionedInit[] =
@ CREATE TABLE IF NOT EXISTS "%w".unversioned(
@   name TEXT PRIMARY KEY,       -- Name of the uv file
@   rcvid INTEGER,               -- Where received from
@   mtime DATETIME,              -- timestamp.  Seconds since 1970.
@   hash TEXT,                   -- Content hash
................................................................................
  if( zMtime==0 ){
    mtime = time(0);
  }else{
    mtime = db_int(0, "SELECT strftime('%%s',%Q)", zMtime);
    if( mtime<=0 ) fossil_fatal("bad timestamp: %Q", zMtime);
  }
  if( memcmp(zCmd, "add", nCmd)==0 ){
    const char *zFile;
    const char *zIn;
    Blob file;
    Blob hash;
    Blob compressed;
    Stmt ins;
    if( g.argc!=4 && g.argc!=5 ) usage("add FILE ?INPUT?");
    zFile = g.argv[3];
    if( !file_is_simple_pathname(zFile,1) ){
      fossil_fatal("'%Q' is not an acceptable filename", zFile);
    }
    zIn = g.argc==5 ? g.argv[4] : "-";
    blob_init(&file,0,0);
    blob_read_from_file(&file, zIn);
    sha1sum_blob(&file, &hash);
    blob_compress(&file, &compressed);
    db_begin_transaction();
    content_rcvid_init();
    db_prepare(&ins,
      "REPLACE INTO unversioned(name,rcvid,mtime,hash,sz,content)"
      " VALUES(:name,:rcvid,:mtime,:hash,:sz,:content)"
    );
    db_bind_text(&ins, ":name", zFile);
    db_bind_int(&ins, ":rcvid", g.rcvid);
    db_bind_int64(&ins, ":mtime", mtime);
    db_bind_text(&ins, ":hash", blob_str(&hash));
    db_bind_int(&ins, ":sz", blob_size(&file));
    db_bind_blob(&ins, ":content", &compressed);
    db_step(&ins);
    db_finalize(&ins);
    blob_reset(&compressed);
    blob_reset(&hash);
    blob_reset(&file);
    /* Clear the uvhash cache */
    db_end_transaction(0);
  }else if( memcmp(zCmd, "cat", nCmd)==0 ){
  }else if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){
    Stmt q;
    db_prepare(&q,
      "SELECT hash, datetime(mtime,'unixepoch'), sz, name, content IS NULL"
      "   FROM unversioned"
      "  WHERE hash IS NOT NULL"
      "  ORDER BY name;"
    );
    while( db_step(&q)==SQLITE_ROW ){
      fossil_print("%12.12s %s %8d %s%s\n",
         db_column_text(&q,0),
         db_column_text(&q,1),
         db_column_int(&q,2),
         db_column_text(&q,3),
         db_column_int(&q,4) ? " ** no content ** ": ""
      );
    }
    db_finalize(&q);
  }else if( memcmp(zCmd, "revert", nCmd)==0 || memcmp(zCmd,"sync",nCmd)==0 ){
    fossil_fatal("not yet implemented...");
  }else if( memcmp(zCmd, "rm", nCmd)==0 ){
  }else{
    usage("add|cat|ls|revert|rm|sync");
  }
}
................................................................................

    uvfile NAME TIMESTAMP SIZE FLAGS \n CONTENT

The client sends uvgimme if 

   (a) it does not possess NAME or
   (b) if the NAME it holds has an earlier timestamp than TIMESTAMP or
   (c) if the NAME it holds has the exact timestamp TIMESTAMP but a
       lexicographically earliers HASH.

Otherwise the client sends a uvfile.  The client also sends uvfile
cards for each unversioned file it holds which was not named by any
uvigot card.

On the uvfile card, the FLAGS value is an unsigned integer with