Fossil SCM

Bug fix in the "mv" command. Add filename change tracking to the check-in information screens. <b>You must run <i>rebuild</i> on existing respositories when upgrading to this version of fossil.</b>

drh 2008-11-09 22:43 trunk
Commit 9fd80090073cc5e781c07d5debab7a3a030503cd
+6 -1
--- src/add.c
+++ src/add.c
@@ -194,10 +194,15 @@
194194
file_tree_name(g.argv[2], &orig, 1);
195195
db_multi_exec(
196196
"INSERT INTO mv VALUES(%B,%B)", &orig, &dest
197197
);
198198
}else{
199
+ if( blob_eq(&dest, ".") ){
200
+ blob_reset(&dest);
201
+ }else{
202
+ blob_append(&dest, "/", 1);
203
+ }
199204
for(i=2; i<g.argc-1; i++){
200205
Blob orig;
201206
char *zOrig;
202207
int nOrig;
203208
file_tree_name(g.argv[i], &orig, 1);
@@ -218,11 +223,11 @@
218223
zTail = file_tail(zPath);
219224
}else{
220225
zTail = &zPath[nOrig+1];
221226
}
222227
db_multi_exec(
223
- "INSERT INTO mv VALUES('%s','%s/%s')",
228
+ "INSERT INTO mv VALUES('%s','%s%s')",
224229
zPath, blob_str(&dest), zTail
225230
);
226231
}
227232
db_finalize(&q);
228233
}
229234
--- src/add.c
+++ src/add.c
@@ -194,10 +194,15 @@
194 file_tree_name(g.argv[2], &orig, 1);
195 db_multi_exec(
196 "INSERT INTO mv VALUES(%B,%B)", &orig, &dest
197 );
198 }else{
 
 
 
 
 
199 for(i=2; i<g.argc-1; i++){
200 Blob orig;
201 char *zOrig;
202 int nOrig;
203 file_tree_name(g.argv[i], &orig, 1);
@@ -218,11 +223,11 @@
218 zTail = file_tail(zPath);
219 }else{
220 zTail = &zPath[nOrig+1];
221 }
222 db_multi_exec(
223 "INSERT INTO mv VALUES('%s','%s/%s')",
224 zPath, blob_str(&dest), zTail
225 );
226 }
227 db_finalize(&q);
228 }
229
--- src/add.c
+++ src/add.c
@@ -194,10 +194,15 @@
194 file_tree_name(g.argv[2], &orig, 1);
195 db_multi_exec(
196 "INSERT INTO mv VALUES(%B,%B)", &orig, &dest
197 );
198 }else{
199 if( blob_eq(&dest, ".") ){
200 blob_reset(&dest);
201 }else{
202 blob_append(&dest, "/", 1);
203 }
204 for(i=2; i<g.argc-1; i++){
205 Blob orig;
206 char *zOrig;
207 int nOrig;
208 file_tree_name(g.argv[i], &orig, 1);
@@ -218,11 +223,11 @@
223 zTail = file_tail(zPath);
224 }else{
225 zTail = &zPath[nOrig+1];
226 }
227 db_multi_exec(
228 "INSERT INTO mv VALUES('%s','%s%s')",
229 zPath, blob_str(&dest), zTail
230 );
231 }
232 db_finalize(&q);
233 }
234
+27 -7
--- src/info.c
+++ src/info.c
@@ -394,30 +394,50 @@
394394
style_header("Baseline Information");
395395
login_anonymous_available();
396396
}
397397
db_finalize(&q);
398398
showTags(rid, "");
399
- @ <div class="section">Files Changed</div>
399
+ @ <div class="section">File Changes</div>
400400
@ <ul>
401401
db_prepare(&q,
402
- "SELECT name, pid, fid"
402
+ "SELECT a.name, b.name"
403
+ " FROM mlink, filename AS a, filename AS b"
404
+ " WHERE mid=%d"
405
+ " AND a.fnid=mlink.fnid"
406
+ " AND b.fnid=mlink.pfnid",
407
+ rid
408
+ );
409
+ while( db_step(&q)==SQLITE_ROW ){
410
+ const char *zName = db_column_text(&q, 0);
411
+ const char *zPrior = db_column_text(&q, 1);
412
+ @ <li><b>Renamed:</b>
413
+ if( g.okHistory ){
414
+ @ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zPrior)</a> to
415
+ @ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a></li>
416
+ }else{
417
+ @ %h(zPrior) to %h(zName)</li>
418
+ }
419
+ }
420
+ db_finalize(&q);
421
+ db_prepare(&q,
422
+ "SELECT name, pid, fid "
403423
" FROM mlink, filename"
404424
" WHERE mid=%d"
425
+ " AND fid!=pid"
405426
" AND filename.fnid=mlink.fnid",
406427
rid
407428
);
408429
while( db_step(&q)==SQLITE_ROW ){
409430
const char *zName = db_column_text(&q, 0);
410431
int pid = db_column_int(&q, 1);
411432
int fid = db_column_int(&q, 2);
412
- @ <li>
413433
if( pid && fid ){
414
- @ <b>Modified:</b>
434
+ @ <li><b>Modified:</b>
415435
}else if( fid ){
416
- @ <b>Added:</b>
417
- }else{
418
- @ <b>Deleted:</b>
436
+ @ <li><b>Added:</b>
437
+ }else if( pid ){
438
+ @ <li><b>Deleted:</b>
419439
}
420440
if( g.okHistory ){
421441
@ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a></li>
422442
}else{
423443
@ %h(zName)</li>
424444
--- src/info.c
+++ src/info.c
@@ -394,30 +394,50 @@
394 style_header("Baseline Information");
395 login_anonymous_available();
396 }
397 db_finalize(&q);
398 showTags(rid, "");
399 @ <div class="section">Files Changed</div>
400 @ <ul>
401 db_prepare(&q,
402 "SELECT name, pid, fid"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
403 " FROM mlink, filename"
404 " WHERE mid=%d"
 
405 " AND filename.fnid=mlink.fnid",
406 rid
407 );
408 while( db_step(&q)==SQLITE_ROW ){
409 const char *zName = db_column_text(&q, 0);
410 int pid = db_column_int(&q, 1);
411 int fid = db_column_int(&q, 2);
412 @ <li>
413 if( pid && fid ){
414 @ <b>Modified:</b>
415 }else if( fid ){
416 @ <b>Added:</b>
417 }else{
418 @ <b>Deleted:</b>
419 }
420 if( g.okHistory ){
421 @ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a></li>
422 }else{
423 @ %h(zName)</li>
424
--- src/info.c
+++ src/info.c
@@ -394,30 +394,50 @@
394 style_header("Baseline Information");
395 login_anonymous_available();
396 }
397 db_finalize(&q);
398 showTags(rid, "");
399 @ <div class="section">File Changes</div>
400 @ <ul>
401 db_prepare(&q,
402 "SELECT a.name, b.name"
403 " FROM mlink, filename AS a, filename AS b"
404 " WHERE mid=%d"
405 " AND a.fnid=mlink.fnid"
406 " AND b.fnid=mlink.pfnid",
407 rid
408 );
409 while( db_step(&q)==SQLITE_ROW ){
410 const char *zName = db_column_text(&q, 0);
411 const char *zPrior = db_column_text(&q, 1);
412 @ <li><b>Renamed:</b>
413 if( g.okHistory ){
414 @ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zPrior)</a> to
415 @ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a></li>
416 }else{
417 @ %h(zPrior) to %h(zName)</li>
418 }
419 }
420 db_finalize(&q);
421 db_prepare(&q,
422 "SELECT name, pid, fid "
423 " FROM mlink, filename"
424 " WHERE mid=%d"
425 " AND fid!=pid"
426 " AND filename.fnid=mlink.fnid",
427 rid
428 );
429 while( db_step(&q)==SQLITE_ROW ){
430 const char *zName = db_column_text(&q, 0);
431 int pid = db_column_int(&q, 1);
432 int fid = db_column_int(&q, 2);
 
433 if( pid && fid ){
434 @ <li><b>Modified:</b>
435 }else if( fid ){
436 @ <li><b>Added:</b>
437 }else if( pid ){
438 @ <li><b>Deleted:</b>
439 }
440 if( g.okHistory ){
441 @ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a></li>
442 }else{
443 @ %h(zName)</li>
444
+90 -15
--- src/manifest.c
+++ src/manifest.c
@@ -65,10 +65,12 @@
6565
int nFileAlloc; /* Slots allocated in aFile[] */
6666
struct {
6767
char *zName; /* Name of a file */
6868
char *zUuid; /* UUID of the file */
6969
char *zPerm; /* File permissions */
70
+ char *zPrior; /* Prior name if the name was changed */
71
+ int iRename; /* index of renamed name in prior/next manifest */
7072
} *aFile;
7173
int nParent; /* Number of parents */
7274
int nParentAlloc; /* Slots allocated in azParent[] */
7375
char **azParent; /* UUIDs of parents */
7476
int nCChild; /* Number of cluster children */
@@ -300,10 +302,12 @@
300302
if( zPriorName[0] ){
301303
defossilize(zPriorName);
302304
if( !file_is_simple_pathname(zPriorName) ){
303305
goto manifest_syntax_error;
304306
}
307
+ }else{
308
+ zPriorName = 0;
305309
}
306310
if( p->nFile>=p->nFileAlloc ){
307311
p->nFileAlloc = p->nFileAlloc*2 + 10;
308312
p->aFile = realloc(p->aFile, p->nFileAlloc*sizeof(p->aFile[0]) );
309313
if( p->aFile==0 ) fossil_panic("out of memory");
@@ -310,10 +314,12 @@
310314
}
311315
i = p->nFile++;
312316
p->aFile[i].zName = zName;
313317
p->aFile[i].zUuid = zUuid;
314318
p->aFile[i].zPerm = zPerm;
319
+ p->aFile[i].zPrior = zPriorName;
320
+ p->aFile[i].iRename = -1;
315321
if( i>0 && strcmp(p->aFile[i-1].zName, zName)>=0 ){
316322
goto manifest_syntax_error;
317323
}
318324
break;
319325
}
@@ -701,18 +707,28 @@
701707
*/
702708
static void add_one_mlink(
703709
int mid, /* The record ID of the manifest */
704710
const char *zFromUuid, /* UUID for the mlink.pid field */
705711
const char *zToUuid, /* UUID for the mlink.fid field */
706
- const char *zFilename /* Filename */
712
+ const char *zFilename, /* Filename */
713
+ const char *zPrior /* Previous filename. NULL if unchanged */
707714
){
708
- int fnid, pid, fid;
715
+ int fnid, pfnid, pid, fid;
709716
710717
fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
711718
if( fnid==0 ){
712719
db_multi_exec("INSERT INTO filename(name) VALUES(%Q)", zFilename);
713720
fnid = db_last_insert_rowid();
721
+ }
722
+ if( zPrior==0 ){
723
+ pfnid = 0;
724
+ }else{
725
+ pfnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zPrior);
726
+ if( pfnid==0 ){
727
+ db_multi_exec("INSERT INTO filename(name) VALUES(%Q)", zPrior);
728
+ pfnid = db_last_insert_rowid();
729
+ }
714730
}
715731
if( zFromUuid==0 ){
716732
pid = 0;
717733
}else{
718734
pid = uuid_to_rid(zFromUuid, 1);
@@ -721,22 +737,50 @@
721737
fid = 0;
722738
}else{
723739
fid = uuid_to_rid(zToUuid, 1);
724740
}
725741
db_multi_exec(
726
- "INSERT INTO mlink(mid,pid,fid,fnid)"
727
- "VALUES(%d,%d,%d,%d)", mid, pid, fid, fnid
742
+ "INSERT INTO mlink(mid,pid,fid,fnid,pfnid)"
743
+ "VALUES(%d,%d,%d,%d,%d)", mid, pid, fid, fnid, pfnid
728744
);
729745
if( pid && fid ){
730746
content_deltify(pid, fid, 0);
731747
}
732748
}
733749
734750
/*
735
-** Add mlink table entries associated with manifest cid.
736
-** There is an mlink entry for every file that changed going
737
-** from pid to cid.
751
+** Locate a file named zName in the aFile[] array of the given
752
+** manifest. We assume that filenames are in sorted order.
753
+** Use a binary search. Return turn the index of the matching
754
+** entry. Or return -1 if not found.
755
+*/
756
+static int find_file_in_manifest(Manifest *p, const char *zName){
757
+ int lwr, upr;
758
+ int c;
759
+ int i;
760
+ lwr = 0;
761
+ upr = p->nFile - 1;
762
+ while( lwr<=upr ){
763
+ i = (lwr+upr)/2;
764
+ c = strcmp(p->aFile[i].zName, zName);
765
+ if( c<0 ){
766
+ lwr = i+1;
767
+ }else if( c>0 ){
768
+ upr = i-1;
769
+ }else{
770
+ return i;
771
+ }
772
+ }
773
+ return -1;
774
+}
775
+
776
+/*
777
+** Add mlink table entries associated with manifest cid. The
778
+** parent manifest is pid.
779
+**
780
+** A single mlink entry is added for every file that changed content
781
+** and/or name going from pid to cid.
738782
**
739783
** Deleted files have mlink.fid=0.
740784
** Added files have mlink.pid=0.
741785
** Edited files have both mlink.pid!=0 and mlink.fid!=0
742786
*/
@@ -757,33 +801,64 @@
757801
content_get(cid, &otherContent);
758802
}
759803
if( blob_size(&otherContent)==0 ) return;
760804
if( manifest_parse(&other, &otherContent)==0 ) return;
761805
content_deltify(pid, cid, 0);
806
+
807
+ /* Use the iRename fields to find the cross-linkage between
808
+ ** renamed files. */
809
+ for(j=0; j<pChild->nFile; j++){
810
+ const char *zPrior = pChild->aFile[j].zPrior;
811
+ if( zPrior && zPrior[0] ){
812
+ i = find_file_in_manifest(pParent, zPrior);
813
+ if( i>=0 ){
814
+ pChild->aFile[j].iRename = i;
815
+ pParent->aFile[i].iRename = j;
816
+ }
817
+ }
818
+ }
819
+
820
+ /* Construct the mlink entries */
762821
for(i=j=0; i<pParent->nFile && j<pChild->nFile; ){
763
- int c = strcmp(pParent->aFile[i].zName, pChild->aFile[j].zName);
764
- if( c<0 ){
765
- add_one_mlink(cid, pParent->aFile[i].zUuid, 0, pParent->aFile[i].zName);
822
+ int c;
823
+ if( pParent->aFile[i].iRename>=0 ){
824
+ i++;
825
+ }else if( (c = strcmp(pParent->aFile[i].zName, pChild->aFile[j].zName))<0 ){
826
+ add_one_mlink(cid, pParent->aFile[i].zUuid,0,pParent->aFile[i].zName,0);
766827
i++;
767828
}else if( c>0 ){
768
- add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName);
829
+ int rn = pChild->aFile[j].iRename;
830
+ if( rn>=0 ){
831
+ add_one_mlink(cid, pParent->aFile[rn].zUuid, pChild->aFile[j].zUuid,
832
+ pChild->aFile[j].zName, pParent->aFile[rn].zName);
833
+ }else{
834
+ add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName,0);
835
+ }
769836
j++;
770837
}else{
771838
if( strcmp(pParent->aFile[i].zUuid, pChild->aFile[j].zUuid)!=0 ){
772
- add_one_mlink(cid, pParent->aFile[i].zUuid, pChild->aFile[j].zUuid,
773
- pChild->aFile[j].zName);
839
+ add_one_mlink(cid, pParent->aFile[i].zUuid, pChild->aFile[j].zUuid,
840
+ pChild->aFile[j].zName, 0);
774841
}
775842
i++;
776843
j++;
777844
}
778845
}
779846
while( i<pParent->nFile ){
780
- add_one_mlink(cid, pParent->aFile[i].zUuid, 0, pParent->aFile[i].zName);
847
+ if( pParent->aFile[i].iRename<0 ){
848
+ add_one_mlink(cid, pParent->aFile[i].zUuid, 0, pParent->aFile[i].zName,0);
849
+ }
781850
i++;
782851
}
783852
while( j<pChild->nFile ){
784
- add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName);
853
+ int rn = pChild->aFile[j].iRename;
854
+ if( rn>=0 ){
855
+ add_one_mlink(cid, pParent->aFile[rn].zUuid, pChild->aFile[j].zUuid,
856
+ pChild->aFile[j].zName, pParent->aFile[rn].zName);
857
+ }else{
858
+ add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName,0);
859
+ }
785860
j++;
786861
}
787862
manifest_clear(&other);
788863
}
789864
790865
--- src/manifest.c
+++ src/manifest.c
@@ -65,10 +65,12 @@
65 int nFileAlloc; /* Slots allocated in aFile[] */
66 struct {
67 char *zName; /* Name of a file */
68 char *zUuid; /* UUID of the file */
69 char *zPerm; /* File permissions */
 
 
70 } *aFile;
71 int nParent; /* Number of parents */
72 int nParentAlloc; /* Slots allocated in azParent[] */
73 char **azParent; /* UUIDs of parents */
74 int nCChild; /* Number of cluster children */
@@ -300,10 +302,12 @@
300 if( zPriorName[0] ){
301 defossilize(zPriorName);
302 if( !file_is_simple_pathname(zPriorName) ){
303 goto manifest_syntax_error;
304 }
 
 
305 }
306 if( p->nFile>=p->nFileAlloc ){
307 p->nFileAlloc = p->nFileAlloc*2 + 10;
308 p->aFile = realloc(p->aFile, p->nFileAlloc*sizeof(p->aFile[0]) );
309 if( p->aFile==0 ) fossil_panic("out of memory");
@@ -310,10 +314,12 @@
310 }
311 i = p->nFile++;
312 p->aFile[i].zName = zName;
313 p->aFile[i].zUuid = zUuid;
314 p->aFile[i].zPerm = zPerm;
 
 
315 if( i>0 && strcmp(p->aFile[i-1].zName, zName)>=0 ){
316 goto manifest_syntax_error;
317 }
318 break;
319 }
@@ -701,18 +707,28 @@
701 */
702 static void add_one_mlink(
703 int mid, /* The record ID of the manifest */
704 const char *zFromUuid, /* UUID for the mlink.pid field */
705 const char *zToUuid, /* UUID for the mlink.fid field */
706 const char *zFilename /* Filename */
 
707 ){
708 int fnid, pid, fid;
709
710 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
711 if( fnid==0 ){
712 db_multi_exec("INSERT INTO filename(name) VALUES(%Q)", zFilename);
713 fnid = db_last_insert_rowid();
 
 
 
 
 
 
 
 
 
714 }
715 if( zFromUuid==0 ){
716 pid = 0;
717 }else{
718 pid = uuid_to_rid(zFromUuid, 1);
@@ -721,22 +737,50 @@
721 fid = 0;
722 }else{
723 fid = uuid_to_rid(zToUuid, 1);
724 }
725 db_multi_exec(
726 "INSERT INTO mlink(mid,pid,fid,fnid)"
727 "VALUES(%d,%d,%d,%d)", mid, pid, fid, fnid
728 );
729 if( pid && fid ){
730 content_deltify(pid, fid, 0);
731 }
732 }
733
734 /*
735 ** Add mlink table entries associated with manifest cid.
736 ** There is an mlink entry for every file that changed going
737 ** from pid to cid.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
738 **
739 ** Deleted files have mlink.fid=0.
740 ** Added files have mlink.pid=0.
741 ** Edited files have both mlink.pid!=0 and mlink.fid!=0
742 */
@@ -757,33 +801,64 @@
757 content_get(cid, &otherContent);
758 }
759 if( blob_size(&otherContent)==0 ) return;
760 if( manifest_parse(&other, &otherContent)==0 ) return;
761 content_deltify(pid, cid, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
762 for(i=j=0; i<pParent->nFile && j<pChild->nFile; ){
763 int c = strcmp(pParent->aFile[i].zName, pChild->aFile[j].zName);
764 if( c<0 ){
765 add_one_mlink(cid, pParent->aFile[i].zUuid, 0, pParent->aFile[i].zName);
 
 
766 i++;
767 }else if( c>0 ){
768 add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName);
 
 
 
 
 
 
769 j++;
770 }else{
771 if( strcmp(pParent->aFile[i].zUuid, pChild->aFile[j].zUuid)!=0 ){
772 add_one_mlink(cid, pParent->aFile[i].zUuid, pChild->aFile[j].zUuid,
773 pChild->aFile[j].zName);
774 }
775 i++;
776 j++;
777 }
778 }
779 while( i<pParent->nFile ){
780 add_one_mlink(cid, pParent->aFile[i].zUuid, 0, pParent->aFile[i].zName);
 
 
781 i++;
782 }
783 while( j<pChild->nFile ){
784 add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName);
 
 
 
 
 
 
785 j++;
786 }
787 manifest_clear(&other);
788 }
789
790
--- src/manifest.c
+++ src/manifest.c
@@ -65,10 +65,12 @@
65 int nFileAlloc; /* Slots allocated in aFile[] */
66 struct {
67 char *zName; /* Name of a file */
68 char *zUuid; /* UUID of the file */
69 char *zPerm; /* File permissions */
70 char *zPrior; /* Prior name if the name was changed */
71 int iRename; /* index of renamed name in prior/next manifest */
72 } *aFile;
73 int nParent; /* Number of parents */
74 int nParentAlloc; /* Slots allocated in azParent[] */
75 char **azParent; /* UUIDs of parents */
76 int nCChild; /* Number of cluster children */
@@ -300,10 +302,12 @@
302 if( zPriorName[0] ){
303 defossilize(zPriorName);
304 if( !file_is_simple_pathname(zPriorName) ){
305 goto manifest_syntax_error;
306 }
307 }else{
308 zPriorName = 0;
309 }
310 if( p->nFile>=p->nFileAlloc ){
311 p->nFileAlloc = p->nFileAlloc*2 + 10;
312 p->aFile = realloc(p->aFile, p->nFileAlloc*sizeof(p->aFile[0]) );
313 if( p->aFile==0 ) fossil_panic("out of memory");
@@ -310,10 +314,12 @@
314 }
315 i = p->nFile++;
316 p->aFile[i].zName = zName;
317 p->aFile[i].zUuid = zUuid;
318 p->aFile[i].zPerm = zPerm;
319 p->aFile[i].zPrior = zPriorName;
320 p->aFile[i].iRename = -1;
321 if( i>0 && strcmp(p->aFile[i-1].zName, zName)>=0 ){
322 goto manifest_syntax_error;
323 }
324 break;
325 }
@@ -701,18 +707,28 @@
707 */
708 static void add_one_mlink(
709 int mid, /* The record ID of the manifest */
710 const char *zFromUuid, /* UUID for the mlink.pid field */
711 const char *zToUuid, /* UUID for the mlink.fid field */
712 const char *zFilename, /* Filename */
713 const char *zPrior /* Previous filename. NULL if unchanged */
714 ){
715 int fnid, pfnid, pid, fid;
716
717 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
718 if( fnid==0 ){
719 db_multi_exec("INSERT INTO filename(name) VALUES(%Q)", zFilename);
720 fnid = db_last_insert_rowid();
721 }
722 if( zPrior==0 ){
723 pfnid = 0;
724 }else{
725 pfnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zPrior);
726 if( pfnid==0 ){
727 db_multi_exec("INSERT INTO filename(name) VALUES(%Q)", zPrior);
728 pfnid = db_last_insert_rowid();
729 }
730 }
731 if( zFromUuid==0 ){
732 pid = 0;
733 }else{
734 pid = uuid_to_rid(zFromUuid, 1);
@@ -721,22 +737,50 @@
737 fid = 0;
738 }else{
739 fid = uuid_to_rid(zToUuid, 1);
740 }
741 db_multi_exec(
742 "INSERT INTO mlink(mid,pid,fid,fnid,pfnid)"
743 "VALUES(%d,%d,%d,%d,%d)", mid, pid, fid, fnid, pfnid
744 );
745 if( pid && fid ){
746 content_deltify(pid, fid, 0);
747 }
748 }
749
750 /*
751 ** Locate a file named zName in the aFile[] array of the given
752 ** manifest. We assume that filenames are in sorted order.
753 ** Use a binary search. Return turn the index of the matching
754 ** entry. Or return -1 if not found.
755 */
756 static int find_file_in_manifest(Manifest *p, const char *zName){
757 int lwr, upr;
758 int c;
759 int i;
760 lwr = 0;
761 upr = p->nFile - 1;
762 while( lwr<=upr ){
763 i = (lwr+upr)/2;
764 c = strcmp(p->aFile[i].zName, zName);
765 if( c<0 ){
766 lwr = i+1;
767 }else if( c>0 ){
768 upr = i-1;
769 }else{
770 return i;
771 }
772 }
773 return -1;
774 }
775
776 /*
777 ** Add mlink table entries associated with manifest cid. The
778 ** parent manifest is pid.
779 **
780 ** A single mlink entry is added for every file that changed content
781 ** and/or name going from pid to cid.
782 **
783 ** Deleted files have mlink.fid=0.
784 ** Added files have mlink.pid=0.
785 ** Edited files have both mlink.pid!=0 and mlink.fid!=0
786 */
@@ -757,33 +801,64 @@
801 content_get(cid, &otherContent);
802 }
803 if( blob_size(&otherContent)==0 ) return;
804 if( manifest_parse(&other, &otherContent)==0 ) return;
805 content_deltify(pid, cid, 0);
806
807 /* Use the iRename fields to find the cross-linkage between
808 ** renamed files. */
809 for(j=0; j<pChild->nFile; j++){
810 const char *zPrior = pChild->aFile[j].zPrior;
811 if( zPrior && zPrior[0] ){
812 i = find_file_in_manifest(pParent, zPrior);
813 if( i>=0 ){
814 pChild->aFile[j].iRename = i;
815 pParent->aFile[i].iRename = j;
816 }
817 }
818 }
819
820 /* Construct the mlink entries */
821 for(i=j=0; i<pParent->nFile && j<pChild->nFile; ){
822 int c;
823 if( pParent->aFile[i].iRename>=0 ){
824 i++;
825 }else if( (c = strcmp(pParent->aFile[i].zName, pChild->aFile[j].zName))<0 ){
826 add_one_mlink(cid, pParent->aFile[i].zUuid,0,pParent->aFile[i].zName,0);
827 i++;
828 }else if( c>0 ){
829 int rn = pChild->aFile[j].iRename;
830 if( rn>=0 ){
831 add_one_mlink(cid, pParent->aFile[rn].zUuid, pChild->aFile[j].zUuid,
832 pChild->aFile[j].zName, pParent->aFile[rn].zName);
833 }else{
834 add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName,0);
835 }
836 j++;
837 }else{
838 if( strcmp(pParent->aFile[i].zUuid, pChild->aFile[j].zUuid)!=0 ){
839 add_one_mlink(cid, pParent->aFile[i].zUuid, pChild->aFile[j].zUuid,
840 pChild->aFile[j].zName, 0);
841 }
842 i++;
843 j++;
844 }
845 }
846 while( i<pParent->nFile ){
847 if( pParent->aFile[i].iRename<0 ){
848 add_one_mlink(cid, pParent->aFile[i].zUuid, 0, pParent->aFile[i].zName,0);
849 }
850 i++;
851 }
852 while( j<pChild->nFile ){
853 int rn = pChild->aFile[j].iRename;
854 if( rn>=0 ){
855 add_one_mlink(cid, pParent->aFile[rn].zUuid, pChild->aFile[j].zUuid,
856 pChild->aFile[j].zName, pParent->aFile[rn].zName);
857 }else{
858 add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName,0);
859 }
860 j++;
861 }
862 manifest_clear(&other);
863 }
864
865
+2 -1
--- src/schema.c
+++ src/schema.c
@@ -178,11 +178,12 @@
178178
@ --
179179
@ CREATE TABLE mlink(
180180
@ mid INTEGER REFERENCES blob, -- Manifest ID where change occurs
181181
@ pid INTEGER REFERENCES blob, -- File ID in parent manifest
182182
@ fid INTEGER REFERENCES blob, -- Changed file ID in this manifest
183
-@ fnid INTEGER REFERENCES filename -- Name of the file
183
+@ fnid INTEGER REFERENCES filename, -- Name of the file
184
+@ pfnid INTEGER REFERENCES filename -- Previous name. 0 if unchanged
184185
@ );
185186
@ CREATE INDEX mlink_i1 ON mlink(mid);
186187
@ CREATE INDEX mlink_i2 ON mlink(fnid);
187188
@ CREATE INDEX mlink_i3 ON mlink(fid);
188189
@ CREATE INDEX mlink_i4 ON mlink(pid);
189190
--- src/schema.c
+++ src/schema.c
@@ -178,11 +178,12 @@
178 @ --
179 @ CREATE TABLE mlink(
180 @ mid INTEGER REFERENCES blob, -- Manifest ID where change occurs
181 @ pid INTEGER REFERENCES blob, -- File ID in parent manifest
182 @ fid INTEGER REFERENCES blob, -- Changed file ID in this manifest
183 @ fnid INTEGER REFERENCES filename -- Name of the file
 
184 @ );
185 @ CREATE INDEX mlink_i1 ON mlink(mid);
186 @ CREATE INDEX mlink_i2 ON mlink(fnid);
187 @ CREATE INDEX mlink_i3 ON mlink(fid);
188 @ CREATE INDEX mlink_i4 ON mlink(pid);
189
--- src/schema.c
+++ src/schema.c
@@ -178,11 +178,12 @@
178 @ --
179 @ CREATE TABLE mlink(
180 @ mid INTEGER REFERENCES blob, -- Manifest ID where change occurs
181 @ pid INTEGER REFERENCES blob, -- File ID in parent manifest
182 @ fid INTEGER REFERENCES blob, -- Changed file ID in this manifest
183 @ fnid INTEGER REFERENCES filename, -- Name of the file
184 @ pfnid INTEGER REFERENCES filename -- Previous name. 0 if unchanged
185 @ );
186 @ CREATE INDEX mlink_i1 ON mlink(mid);
187 @ CREATE INDEX mlink_i2 ON mlink(fnid);
188 @ CREATE INDEX mlink_i3 ON mlink(fid);
189 @ CREATE INDEX mlink_i4 ON mlink(pid);
190

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button