File Annotation
Not logged in
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Copyright (c) 2007 D. Richard Hipp
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This program is free software; you can redistribute it and/or
dbda8d6ce9 2007-07-21       drh: ** modify it under the terms of the GNU General Public
dbda8d6ce9 2007-07-21       drh: ** License version 2 as published by the Free Software Foundation.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This program is distributed in the hope that it will be useful,
dbda8d6ce9 2007-07-21       drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
dbda8d6ce9 2007-07-21       drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
dbda8d6ce9 2007-07-21       drh: ** General Public License for more details.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** You should have received a copy of the GNU General Public
dbda8d6ce9 2007-07-21       drh: ** License along with this library; if not, write to the
dbda8d6ce9 2007-07-21       drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
dbda8d6ce9 2007-07-21       drh: ** Boston, MA  02111-1307, USA.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Author contact information:
dbda8d6ce9 2007-07-21       drh: **   drh@hwaci.com
dbda8d6ce9 2007-07-21       drh: **   http://www.hwaci.com/drh/
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: *******************************************************************************
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This file contains code used to cross link manifests
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: #include "config.h"
dbda8d6ce9 2007-07-21       drh: #include "manifest.h"
dbda8d6ce9 2007-07-21       drh: #include <assert.h>
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: #if INTERFACE
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** A parsed manifest
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: struct Manifest {
dbda8d6ce9 2007-07-21       drh:   Blob content;         /* The original content blob */
dbda8d6ce9 2007-07-21       drh:   char *zComment;       /* Decoded comment */
dbda8d6ce9 2007-07-21       drh:   double rDate;         /* Time in the "D" line */
dbda8d6ce9 2007-07-21       drh:   char *zUser;          /* Name of the user */
dbda8d6ce9 2007-07-21       drh:   char *zRepoCksum;     /* MD5 checksum of the baseline content */
dbda8d6ce9 2007-07-21       drh:   int nFile;            /* Number of F lines */
dbda8d6ce9 2007-07-21       drh:   int nFileAlloc;       /* Slots allocated in aFile[] */
dbda8d6ce9 2007-07-21       drh:   struct {
dbda8d6ce9 2007-07-21       drh:     char *zName;           /* Name of a file */
dbda8d6ce9 2007-07-21       drh:     char *zUuid;           /* UUID of the file */
dbda8d6ce9 2007-07-21       drh:   } *aFile;
dbda8d6ce9 2007-07-21       drh:   int nParent;          /* Number of parents */
dbda8d6ce9 2007-07-21       drh:   int nParentAlloc;     /* Slots allocated in azParent[] */
dbda8d6ce9 2007-07-21       drh:   char **azParent;      /* UUIDs of parents */
dbda8d6ce9 2007-07-21       drh: };
dbda8d6ce9 2007-07-21       drh: #endif
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Clear the memory allocated in a manifest object
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void manifest_clear(Manifest *p){
dbda8d6ce9 2007-07-21       drh:   blob_reset(&p->content);
dbda8d6ce9 2007-07-21       drh:   free(p->aFile);
dbda8d6ce9 2007-07-21       drh:   free(p->azParent);
dbda8d6ce9 2007-07-21       drh:   memset(p, 0, sizeof(*p));
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Parse a manifest blob into a Manifest object.  The Manifest
dbda8d6ce9 2007-07-21       drh: ** object takes over the input blob and will free it when the
dbda8d6ce9 2007-07-21       drh: ** Manifest object is freed.  Zeros are inserted into the blob
dbda8d6ce9 2007-07-21       drh: ** as string terminators so that blob should not be used again.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Return TRUE if the content really is a manifest.  Return FALSE
dbda8d6ce9 2007-07-21       drh: ** if there are syntax errors.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** The pContent is reset.  If TRUE is returned, then pContent will
dbda8d6ce9 2007-07-21       drh: ** be reset when the Manifest object is cleared.  If FALSE is
dbda8d6ce9 2007-07-21       drh: ** returned then the Manifest object is cleared automatically
dbda8d6ce9 2007-07-21       drh: ** and pContent is reset before the return.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: int manifest_parse(Manifest *p, Blob *pContent){
dbda8d6ce9 2007-07-21       drh:   int seenHeader = 0;
dbda8d6ce9 2007-07-21       drh:   int i;
dbda8d6ce9 2007-07-21       drh:   Blob line, token, a1, a2, a3;
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh:   memset(p, 0, sizeof(*p));
dbda8d6ce9 2007-07-21       drh:   memcpy(&p->content, pContent, sizeof(p->content));
dbda8d6ce9 2007-07-21       drh:   blob_zero(pContent);
dbda8d6ce9 2007-07-21       drh:   pContent = &p->content;
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh:   blob_zero(&a1);
dbda8d6ce9 2007-07-21       drh:   blob_zero(&a2);
dbda8d6ce9 2007-07-21       drh:   md5sum_init();
dbda8d6ce9 2007-07-21       drh:   while( blob_line(pContent, &line) ){
dbda8d6ce9 2007-07-21       drh:     char *z = blob_buffer(&line);
dbda8d6ce9 2007-07-21       drh:     if( z[0]=='-' ){
dbda8d6ce9 2007-07-21       drh:       if( strncmp(z, "-----BEGIN PGP ", 15)!=0 ){
dbda8d6ce9 2007-07-21       drh:         goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       }
dbda8d6ce9 2007-07-21       drh:       if( seenHeader ){
dbda8d6ce9 2007-07-21       drh:         break;
dbda8d6ce9 2007-07-21       drh:       }
dbda8d6ce9 2007-07-21       drh:       while( blob_line(pContent, &line)>1 ){}
dbda8d6ce9 2007-07-21       drh:       if( blob_line(pContent, &line)==0 ) break;
e37451d9c2 2007-08-01       drh:       z = blob_buffer(&line);
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:     seenHeader = 1;
dbda8d6ce9 2007-07-21       drh:     if( blob_token(&line, &token)!=1 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:     if( z[0]=='F' ){
dbda8d6ce9 2007-07-21       drh:       char *zName, *zUuid;
dbda8d6ce9 2007-07-21       drh:       md5sum_step_text(blob_buffer(&line), blob_size(&line)+1);
dbda8d6ce9 2007-07-21       drh:       if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       if( blob_token(&line, &a3)!=0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       zName = blob_terminate(&a1);
dbda8d6ce9 2007-07-21       drh:       zUuid = blob_terminate(&a2);
dbda8d6ce9 2007-07-21       drh:       if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       defossilize(zName);
dbda8d6ce9 2007-07-21       drh:       if( !file_is_simple_pathname(zName) ){
dbda8d6ce9 2007-07-21       drh:         goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       }
dbda8d6ce9 2007-07-21       drh:       if( p->nFile>=p->nFileAlloc ){
dbda8d6ce9 2007-07-21       drh:         p->nFileAlloc = p->nFileAlloc*2 + 10;
dbda8d6ce9 2007-07-21       drh:         p->aFile = realloc(p->aFile, p->nFileAlloc*sizeof(p->aFile[0]) );
dbda8d6ce9 2007-07-21       drh:         if( p->aFile==0 ) fossil_panic("out of memory");
dbda8d6ce9 2007-07-21       drh:       }
dbda8d6ce9 2007-07-21       drh:       i = p->nFile++;
dbda8d6ce9 2007-07-21       drh:       p->aFile[i].zName = zName;
dbda8d6ce9 2007-07-21       drh:       p->aFile[i].zUuid = zUuid;
dbda8d6ce9 2007-07-21       drh:       if( i>0 && strcmp(p->aFile[i-1].zName, zName)>=0 ){
dbda8d6ce9 2007-07-21       drh:         goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       }
dbda8d6ce9 2007-07-21       drh:     }else if( z[0]=='C' ){
dbda8d6ce9 2007-07-21       drh:       md5sum_step_text(blob_buffer(&line), blob_size(&line)+1);
dbda8d6ce9 2007-07-21       drh:       if( p->zComment!=0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       p->zComment = blob_terminate(&a1);
dbda8d6ce9 2007-07-21       drh:       defossilize(p->zComment);
dbda8d6ce9 2007-07-21       drh:     }else if( z[0]=='D' ){
dbda8d6ce9 2007-07-21       drh:       char *zDate;
dbda8d6ce9 2007-07-21       drh:       md5sum_step_text(blob_buffer(&line), blob_size(&line)+1);
dbda8d6ce9 2007-07-21       drh:       if( p->rDate!=0.0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       zDate = blob_terminate(&a1);
dbda8d6ce9 2007-07-21       drh:       p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate);
dbda8d6ce9 2007-07-21       drh:     }else if( z[0]=='U' ){
dbda8d6ce9 2007-07-21       drh:       md5sum_step_text(blob_buffer(&line), blob_size(&line)+1);
dbda8d6ce9 2007-07-21       drh:       if( p->zUser!=0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       p->zUser = blob_terminate(&a1);
dbda8d6ce9 2007-07-21       drh:       defossilize(p->zUser);
dbda8d6ce9 2007-07-21       drh:     }else if( z[0]=='R' ){
dbda8d6ce9 2007-07-21       drh:       md5sum_step_text(blob_buffer(&line), blob_size(&line)+1);
dbda8d6ce9 2007-07-21       drh:       if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       p->zRepoCksum = blob_terminate(&a1);
dbda8d6ce9 2007-07-21       drh:       if( !validate16(p->zRepoCksum, 32) ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:     }else if( z[0]=='P' ){
dbda8d6ce9 2007-07-21       drh:       md5sum_step_text(blob_buffer(&line), blob_size(&line)+1);
dbda8d6ce9 2007-07-21       drh:       while( blob_token(&line, &a1) ){
dbda8d6ce9 2007-07-21       drh:         char *zUuid;
dbda8d6ce9 2007-07-21       drh:         if( blob_size(&a1)!=UUID_SIZE ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:         zUuid = blob_terminate(&a1);
dbda8d6ce9 2007-07-21       drh:         if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:         if( p->nParent>=p->nParentAlloc ){
dbda8d6ce9 2007-07-21       drh:           p->nParentAlloc = p->nParentAlloc*2 + 5;
dbda8d6ce9 2007-07-21       drh:           p->azParent = realloc(p->azParent, p->nParentAlloc*sizeof(char*));
dbda8d6ce9 2007-07-21       drh:           if( p->azParent==0 ) fossil_panic("out of memory");
dbda8d6ce9 2007-07-21       drh:         }
dbda8d6ce9 2007-07-21       drh:         i = p->nParent++;
dbda8d6ce9 2007-07-21       drh:         p->azParent[i] = zUuid;
dbda8d6ce9 2007-07-21       drh:       }
dbda8d6ce9 2007-07-21       drh:     }else if( z[0]=='Z' ){
dbda8d6ce9 2007-07-21       drh:       int rc;
dbda8d6ce9 2007-07-21       drh:       Blob hash;
dbda8d6ce9 2007-07-21       drh:       if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       if( !validate16(blob_buffer(&a1), 32) ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:       md5sum_finish(&hash);
dbda8d6ce9 2007-07-21       drh:       rc = blob_compare(&hash, &a1);
dbda8d6ce9 2007-07-21       drh:       blob_reset(&hash);
dbda8d6ce9 2007-07-21       drh:       if( rc!=0 ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:     }else{
dbda8d6ce9 2007-07-21       drh:       goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   if( !seenHeader ) goto manifest_syntax_error;
dbda8d6ce9 2007-07-21       drh:   md5sum_init();
dbda8d6ce9 2007-07-21       drh:   return 1;
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: manifest_syntax_error:
dbda8d6ce9 2007-07-21       drh:   md5sum_init();
dbda8d6ce9 2007-07-21       drh:   manifest_clear(p);
dbda8d6ce9 2007-07-21       drh:   return 0;
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Add a single entry to the mlink table.  Also add the filename to
dbda8d6ce9 2007-07-21       drh: ** the filename table if it is not there already.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: static void add_one_mlink(
dbda8d6ce9 2007-07-21       drh:   int mid,                  /* The record ID of the manifest */
dbda8d6ce9 2007-07-21       drh:   const char *zFromUuid,    /* UUID for the mlink.pid field */
dbda8d6ce9 2007-07-21       drh:   const char *zToUuid,      /* UUID for the mlink.fid field */
dbda8d6ce9 2007-07-21       drh:   const char *zFilename     /* Filename */
dbda8d6ce9 2007-07-21       drh: ){
dbda8d6ce9 2007-07-21       drh:   int fnid, pid, fid;
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh:   fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
dbda8d6ce9 2007-07-21       drh:   if( fnid==0 ){
dbda8d6ce9 2007-07-21       drh:     db_multi_exec("INSERT INTO filename(name) VALUES(%Q)", zFilename);
dbda8d6ce9 2007-07-21       drh:     fnid = db_last_insert_rowid();
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   if( zFromUuid==0 ){
dbda8d6ce9 2007-07-21       drh:     pid = 0;
dbda8d6ce9 2007-07-21       drh:   }else{
dbda8d6ce9 2007-07-21       drh:     pid = uuid_to_rid(zFromUuid, 1);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   if( zToUuid==0 ){
dbda8d6ce9 2007-07-21       drh:     fid = 0;
dbda8d6ce9 2007-07-21       drh:   }else{
dbda8d6ce9 2007-07-21       drh:     fid = uuid_to_rid(zToUuid, 1);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   db_multi_exec(
dbda8d6ce9 2007-07-21       drh:     "INSERT INTO mlink(mid,pid,fid,fnid)"
dbda8d6ce9 2007-07-21       drh:     "VALUES(%d,%d,%d,%d)", mid, pid, fid, fnid
dbda8d6ce9 2007-07-21       drh:   );
dbda8d6ce9 2007-07-21       drh:   if( pid && fid ){
dbda8d6ce9 2007-07-21       drh:     content_deltify(pid, fid, 0);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Add mlink table entries associated with manifest cid.
dbda8d6ce9 2007-07-21       drh: ** There is an mlink entry for every file that changed going
dbda8d6ce9 2007-07-21       drh: ** from pid to cid.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Deleted files have mlink.fid=0.
dbda8d6ce9 2007-07-21       drh: ** Added files have mlink.pid=0.
dbda8d6ce9 2007-07-21       drh: ** Edited files have both mlink.pid!=0 and mlink.fid!=0
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: static void add_mlink(int pid, Manifest *pParent, int cid, Manifest *pChild){
dbda8d6ce9 2007-07-21       drh:   Manifest other;
dbda8d6ce9 2007-07-21       drh:   Blob otherContent;
dbda8d6ce9 2007-07-21       drh:   int i, j;
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh:   if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", cid) ){
dbda8d6ce9 2007-07-21       drh:     return;
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   assert( pParent==0 || pChild==0 );
dbda8d6ce9 2007-07-21       drh:   if( pParent==0 ){
dbda8d6ce9 2007-07-21       drh:     pParent = &other;
dbda8d6ce9 2007-07-21       drh:     content_get(pid, &otherContent);
dbda8d6ce9 2007-07-21       drh:   }else{
dbda8d6ce9 2007-07-21       drh:     pChild = &other;
dbda8d6ce9 2007-07-21       drh:     content_get(cid, &otherContent);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   if( blob_size(&otherContent)==0 ) return;
dbda8d6ce9 2007-07-21       drh:   if( manifest_parse(&other, &otherContent)==0 ) return;
dbda8d6ce9 2007-07-21       drh:   content_deltify(pid, cid, 0);
5b58559c0c 2007-07-31       drh:   for(i=j=0; i<pParent->nFile && j<pChild->nFile; ){
dbda8d6ce9 2007-07-21       drh:     int c = strcmp(pParent->aFile[i].zName, pChild->aFile[j].zName);
dbda8d6ce9 2007-07-21       drh:     if( c<0 ){
dbda8d6ce9 2007-07-21       drh:       add_one_mlink(cid, pParent->aFile[i].zUuid, 0, pParent->aFile[i].zName);
dbda8d6ce9 2007-07-21       drh:       i++;
dbda8d6ce9 2007-07-21       drh:     }else if( c>0 ){
dbda8d6ce9 2007-07-21       drh:       add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName);
dbda8d6ce9 2007-07-21       drh:       j++;
dbda8d6ce9 2007-07-21       drh:     }else{
dbda8d6ce9 2007-07-21       drh:       if( strcmp(pParent->aFile[i].zUuid, pChild->aFile[j].zUuid)!=0 ){
dbda8d6ce9 2007-07-21       drh:       add_one_mlink(cid, pParent->aFile[i].zUuid, pChild->aFile[j].zUuid,
dbda8d6ce9 2007-07-21       drh:                     pChild->aFile[j].zName);
dbda8d6ce9 2007-07-21       drh:       }
dbda8d6ce9 2007-07-21       drh:       i++;
dbda8d6ce9 2007-07-21       drh:       j++;
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   while( i<pParent->nFile ){
dbda8d6ce9 2007-07-21       drh:     add_one_mlink(cid, pParent->aFile[i].zUuid, 0, pParent->aFile[i].zName);
dbda8d6ce9 2007-07-21       drh:     i++;
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   while( j<pChild->nFile ){
dbda8d6ce9 2007-07-21       drh:     add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName);
dbda8d6ce9 2007-07-21       drh:     j++;
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   manifest_clear(&other);
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Scan record rid/pContent to see if it is a manifest.  If
dbda8d6ce9 2007-07-21       drh: ** it is a manifest, then populate tables the mlink, plink,
dbda8d6ce9 2007-07-21       drh: ** filename, and event tables with cross-reference information.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: int manifest_crosslink(int rid, Blob *pContent){
dbda8d6ce9 2007-07-21       drh:   int i;
dbda8d6ce9 2007-07-21       drh:   Manifest m;
dbda8d6ce9 2007-07-21       drh:   Stmt q;
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh:   if( manifest_parse(&m, pContent)==0 ){
dbda8d6ce9 2007-07-21       drh:     return 0;
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   db_begin_transaction();
dbda8d6ce9 2007-07-21       drh:   for(i=0; i<m.nParent; i++){
dbda8d6ce9 2007-07-21       drh:     int pid = uuid_to_rid(m.azParent[i], 1);
dbda8d6ce9 2007-07-21       drh:     db_multi_exec("INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime)"
dbda8d6ce9 2007-07-21       drh:                   "VALUES(%d, %d, %d, %.17g)", pid, rid, i==0, m.rDate);
dbda8d6ce9 2007-07-21       drh:     if( i==0 ){
dbda8d6ce9 2007-07-21       drh:       add_mlink(pid, 0, rid, &m);
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   db_prepare(&q, "SELECT cid FROM plink WHERE pid=%d AND isprim", rid);
dbda8d6ce9 2007-07-21       drh:   while( db_step(&q)==SQLITE_ROW ){
dbda8d6ce9 2007-07-21       drh:     int cid = db_column_int(&q, 0);
dbda8d6ce9 2007-07-21       drh:     add_mlink(rid, &m, cid, 0);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   db_finalize(&q);
dbda8d6ce9 2007-07-21       drh:   db_multi_exec(
dbda8d6ce9 2007-07-21       drh:     "INSERT INTO event(type,mtime,objid,user,comment)"
dbda8d6ce9 2007-07-21       drh:     "VALUES('ci',%.17g,%d,%Q,%Q)",
dbda8d6ce9 2007-07-21       drh:     m.rDate, rid, m.zUser, m.zComment
dbda8d6ce9 2007-07-21       drh:   );
dbda8d6ce9 2007-07-21       drh:   db_end_transaction(0);
dbda8d6ce9 2007-07-21       drh:   manifest_clear(&m);
dbda8d6ce9 2007-07-21       drh:   return 1;
dbda8d6ce9 2007-07-21       drh: }