Fossil SCM

Change the schema of the vmerge table so that it remembers the hash of merged artifacts, not the RID. Schema updates are automatic, but once the update occurs, you are committed to using the newer version of Fossil moving forward.

drh 2019-01-19 21:31 UTC trunk
Commit 8977dfb03295226c720683a6756db00038ed4a2991535dc5910bbadc091cdf22
+5 -8
--- src/checkin.c
+++ src/checkin.c
@@ -307,12 +307,11 @@
307307
db_finalize(&q);
308308
309309
/* If C_MERGE, put merge contributors at the end of the report. */
310310
skipFiles:
311311
if( flags & C_MERGE ){
312
- db_prepare(&q, "SELECT uuid, id FROM vmerge JOIN blob ON merge=rid"
313
- " WHERE id<=0");
312
+ db_prepare(&q, "SELECT mhash, id FROM vmerge WHERE id<=0" );
314313
while( db_step(&q)==SQLITE_ROW ){
315314
if( flags & C_COMMENT ){
316315
blob_append(report, "# ", 2);
317316
}
318317
if( flags & C_CLASSIFY ){
@@ -1635,14 +1634,13 @@
16351634
blob_appendf(pOut, "\n");
16361635
}
16371636
free(zDate);
16381637
16391638
db_prepare(&q,
1640
- "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
1641
- " FROM vmerge, blob"
1639
+ "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || mhash, merge"
1640
+ " FROM vmerge"
16421641
" WHERE (vmerge.id=-1 OR vmerge.id=-2)"
1643
- " AND blob.rid=vmerge.merge"
16441642
" ORDER BY 1");
16451643
while( db_step(&q)==SQLITE_ROW ){
16461644
const char *zCherrypickUuid = db_column_text(&q, 0);
16471645
int mid = db_column_int(&q, 1);
16481646
if( mid != vid ){
@@ -1667,11 +1665,11 @@
16671665
blob_appendf(pOut, "T +bgcolor * %F\n", zColor);
16681666
}
16691667
if( p->closeFlag ){
16701668
blob_appendf(pOut, "T +closed *\n");
16711669
}
1672
- db_prepare(&q, "SELECT uuid,merge FROM vmerge JOIN blob ON merge=rid"
1670
+ db_prepare(&q, "SELECT mhash,merge FROM vmerge"
16731671
" WHERE id %s ORDER BY 1",
16741672
p->integrateFlag ? "IN(0,-4)" : "=(-4)");
16751673
while( db_step(&q)==SQLITE_ROW ){
16761674
const char *zIntegrateUuid = db_column_text(&q, 0);
16771675
int rid = db_column_int(&q, 1);
@@ -2508,12 +2506,11 @@
25082506
}
25092507
assert( blob_is_reset(&manifest) );
25102508
content_deltify(vid, &nvid, 1, 0);
25112509
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
25122510
2513
- db_prepare(&q, "SELECT uuid,merge FROM vmerge JOIN blob ON merge=rid"
2514
- " WHERE id=-4");
2511
+ db_prepare(&q, "SELECT mhash,merge FROM vmerge WHERE id=-4");
25152512
while( db_step(&q)==SQLITE_ROW ){
25162513
const char *zIntegrateUuid = db_column_text(&q, 0);
25172514
if( is_a_leaf(db_column_int(&q, 1)) ){
25182515
fossil_print("Closed: %s\n", zIntegrateUuid);
25192516
}else{
25202517
--- src/checkin.c
+++ src/checkin.c
@@ -307,12 +307,11 @@
307 db_finalize(&q);
308
309 /* If C_MERGE, put merge contributors at the end of the report. */
310 skipFiles:
311 if( flags & C_MERGE ){
312 db_prepare(&q, "SELECT uuid, id FROM vmerge JOIN blob ON merge=rid"
313 " WHERE id<=0");
314 while( db_step(&q)==SQLITE_ROW ){
315 if( flags & C_COMMENT ){
316 blob_append(report, "# ", 2);
317 }
318 if( flags & C_CLASSIFY ){
@@ -1635,14 +1634,13 @@
1635 blob_appendf(pOut, "\n");
1636 }
1637 free(zDate);
1638
1639 db_prepare(&q,
1640 "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
1641 " FROM vmerge, blob"
1642 " WHERE (vmerge.id=-1 OR vmerge.id=-2)"
1643 " AND blob.rid=vmerge.merge"
1644 " ORDER BY 1");
1645 while( db_step(&q)==SQLITE_ROW ){
1646 const char *zCherrypickUuid = db_column_text(&q, 0);
1647 int mid = db_column_int(&q, 1);
1648 if( mid != vid ){
@@ -1667,11 +1665,11 @@
1667 blob_appendf(pOut, "T +bgcolor * %F\n", zColor);
1668 }
1669 if( p->closeFlag ){
1670 blob_appendf(pOut, "T +closed *\n");
1671 }
1672 db_prepare(&q, "SELECT uuid,merge FROM vmerge JOIN blob ON merge=rid"
1673 " WHERE id %s ORDER BY 1",
1674 p->integrateFlag ? "IN(0,-4)" : "=(-4)");
1675 while( db_step(&q)==SQLITE_ROW ){
1676 const char *zIntegrateUuid = db_column_text(&q, 0);
1677 int rid = db_column_int(&q, 1);
@@ -2508,12 +2506,11 @@
2508 }
2509 assert( blob_is_reset(&manifest) );
2510 content_deltify(vid, &nvid, 1, 0);
2511 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
2512
2513 db_prepare(&q, "SELECT uuid,merge FROM vmerge JOIN blob ON merge=rid"
2514 " WHERE id=-4");
2515 while( db_step(&q)==SQLITE_ROW ){
2516 const char *zIntegrateUuid = db_column_text(&q, 0);
2517 if( is_a_leaf(db_column_int(&q, 1)) ){
2518 fossil_print("Closed: %s\n", zIntegrateUuid);
2519 }else{
2520
--- src/checkin.c
+++ src/checkin.c
@@ -307,12 +307,11 @@
307 db_finalize(&q);
308
309 /* If C_MERGE, put merge contributors at the end of the report. */
310 skipFiles:
311 if( flags & C_MERGE ){
312 db_prepare(&q, "SELECT mhash, id FROM vmerge WHERE id<=0" );
 
313 while( db_step(&q)==SQLITE_ROW ){
314 if( flags & C_COMMENT ){
315 blob_append(report, "# ", 2);
316 }
317 if( flags & C_CLASSIFY ){
@@ -1635,14 +1634,13 @@
1634 blob_appendf(pOut, "\n");
1635 }
1636 free(zDate);
1637
1638 db_prepare(&q,
1639 "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || mhash, merge"
1640 " FROM vmerge"
1641 " WHERE (vmerge.id=-1 OR vmerge.id=-2)"
 
1642 " ORDER BY 1");
1643 while( db_step(&q)==SQLITE_ROW ){
1644 const char *zCherrypickUuid = db_column_text(&q, 0);
1645 int mid = db_column_int(&q, 1);
1646 if( mid != vid ){
@@ -1667,11 +1665,11 @@
1665 blob_appendf(pOut, "T +bgcolor * %F\n", zColor);
1666 }
1667 if( p->closeFlag ){
1668 blob_appendf(pOut, "T +closed *\n");
1669 }
1670 db_prepare(&q, "SELECT mhash,merge FROM vmerge"
1671 " WHERE id %s ORDER BY 1",
1672 p->integrateFlag ? "IN(0,-4)" : "=(-4)");
1673 while( db_step(&q)==SQLITE_ROW ){
1674 const char *zIntegrateUuid = db_column_text(&q, 0);
1675 int rid = db_column_int(&q, 1);
@@ -2508,12 +2506,11 @@
2506 }
2507 assert( blob_is_reset(&manifest) );
2508 content_deltify(vid, &nvid, 1, 0);
2509 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
2510
2511 db_prepare(&q, "SELECT mhash,merge FROM vmerge WHERE id=-4");
 
2512 while( db_step(&q)==SQLITE_ROW ){
2513 const char *zIntegrateUuid = db_column_text(&q, 0);
2514 if( is_a_leaf(db_column_int(&q, 1)) ){
2515 fossil_print("Closed: %s\n", zIntegrateUuid);
2516 }else{
2517
+69 -36
--- src/db.c
+++ src/db.c
@@ -1473,33 +1473,44 @@
14731473
** If zDbName is a valid local database file, open it and return
14741474
** true. If it is not a valid local database file, return 0.
14751475
*/
14761476
static int isValidLocalDb(const char *zDbName){
14771477
i64 lsize;
1478
- char *zVFileDef;
14791478
14801479
if( file_access(zDbName, F_OK) ) return 0;
14811480
lsize = file_size(zDbName, ExtFILE);
14821481
if( lsize%1024!=0 || lsize<4096 ) return 0;
14831482
db_open_or_attach(zDbName, "localdb");
1484
- zVFileDef = db_text(0, "SELECT sql FROM localdb.sqlite_master"
1485
- " WHERE name=='vfile'");
1486
- if( zVFileDef==0 ) return 0;
1483
+
1484
+ /* Check to see if the checkout database has the lastest schema changes.
1485
+ ** The most recent schema change (2019-01-19) is the addition of the
1486
+ ** vmerge.mhash field. If the schema has that one column, assume
1487
+ ** everything else is up-to-date.
1488
+ */
1489
+ if( db_table_has_column("localdb","vmerge","mhash") ){
1490
+ return 1; /* This is a checkout database with the latest schema */
1491
+ }
1492
+
1493
+ /* If there is no vfile table, then assume we have picked up something
1494
+ ** that is not even close to being a valid checkout database */
1495
+ if( !db_table_exists("localdb","vfile") ){
1496
+ return 0; /* Not a DB */
1497
+ }
14871498
14881499
/* If the "isexe" column is missing from the vfile table, then
14891500
** add it now. This code added on 2010-03-06. After all users have
14901501
** upgraded, this code can be safely deleted.
14911502
*/
1492
- if( sqlite3_strglob("* isexe *", zVFileDef)!=0 ){
1503
+ if( !db_table_has_column("localdb","vfile","isexe") ){
14931504
db_multi_exec("ALTER TABLE vfile ADD COLUMN isexe BOOLEAN DEFAULT 0");
14941505
}
14951506
14961507
/* If "islink"/"isLink" columns are missing from tables, then
14971508
** add them now. This code added on 2011-01-17 and 2011-08-27.
14981509
** After all users have upgraded, this code can be safely deleted.
14991510
*/
1500
- if( sqlite3_strglob("* islink *", zVFileDef)!=0 ){
1511
+ if( !db_table_has_column("localdb","vfile","isLink") ){
15011512
db_multi_exec("ALTER TABLE vfile ADD COLUMN islink BOOLEAN DEFAULT 0");
15021513
if( db_local_table_exists_but_lacks_column("stashfile", "isLink") ){
15031514
db_multi_exec("ALTER TABLE stashfile ADD COLUMN isLink BOOL DEFAULT 0");
15041515
}
15051516
if( db_local_table_exists_but_lacks_column("undo", "isLink") ){
@@ -1507,11 +1518,15 @@
15071518
}
15081519
if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){
15091520
db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0");
15101521
}
15111522
}
1512
- fossil_free(zVFileDef);
1523
+
1524
+ /* The design of the vmerge table changed on 2019-01-19, adding the mhash
1525
+ ** column and changing the UNIQUE index. However, we must ahve the
1526
+ ** repository database at hand in order to do the migration, so that
1527
+ ** step is deferred. */
15131528
return 1;
15141529
}
15151530
15161531
/*
15171532
** Locate the root directory of the local repository tree. The root
@@ -1656,41 +1671,59 @@
16561671
/* Make a change to the CHECK constraint on the BLOB table for
16571672
** version 2.0 and later.
16581673
*/
16591674
rebuild_schema_update_2_0(); /* Do the Fossil-2.0 schema updates */
16601675
1661
- /* If the checkout database was opened first, then check to make
1662
- ** sure that the repository database that was just opened has not
1663
- ** be replaced by a clone of the same project, with different RID
1664
- ** values.
1665
- */
1666
- if( g.localOpen && !db_fingerprint_ok() ){
1667
- /* Uncomment the following when we are ready for automatic recovery: */
1676
+ /* Additional checks that occur when opening the checkout database */
1677
+ if( g.localOpen ){
1678
+
1679
+ /* Ensure that the repository database that was just opened has not
1680
+ ** be replaced by a clone of the same project, with different RID
1681
+ ** values.
1682
+ */
1683
+ if( !db_fingerprint_ok() ){
1684
+ /* Uncomment the following when we are ready for automatic recovery: */
16681685
#if 0
1669
- stash_rid_renumbering_event();
1686
+ stash_rid_renumbering_event();
16701687
#else
1671
- fossil_print(
1672
- "Oops. It looks like the repository database file located at\n"
1673
- " \"%s\"\n", zDbName
1674
- );
1675
- fossil_print(
1676
- "has been swapped with a clone that may have different\n"
1677
- "integer keys for the various artifacts. As of 2019-01-11,\n"
1678
- "we are working on enhancing Fossil to be able to deal with\n"
1679
- "that automatically, but we are not there yet. Sorry.\n\n"
1680
- );
1681
- fossil_print(
1682
- "As an interim workaround, try:\n"
1683
- " %s close --force\n"
1684
- " %s open \"%s\" --keep\n"
1685
- "Noting that any STASH and UNDO information "
1686
- "WILL BE IRREVOCABLY LOST.\n\n",
1687
- g.argv[0],
1688
- g.argv[0], zDbName
1689
- );
1690
- fossil_fatal("bad fingerprint");
1688
+ fossil_print(
1689
+ "Oops. It looks like the repository database file located at\n"
1690
+ " \"%s\"\n", zDbName
1691
+ );
1692
+ fossil_print(
1693
+ "has been swapped with a clone that may have different\n"
1694
+ "integer keys for the various artifacts. As of 2019-01-11,\n"
1695
+ "we are working on enhancing Fossil to be able to deal with\n"
1696
+ "that automatically, but we are not there yet. Sorry.\n\n"
1697
+ );
1698
+ fossil_print(
1699
+ "As an interim workaround, try:\n"
1700
+ " %s close --force\n"
1701
+ " %s open \"%s\" --keep\n"
1702
+ "Noting that any STASH and UNDO information "
1703
+ "WILL BE IRREVOCABLY LOST.\n\n",
1704
+ g.argv[0],
1705
+ g.argv[0], zDbName
1706
+ );
1707
+ fossil_fatal("bad fingerprint");
16911708
#endif
1709
+ }else
1710
+
1711
+ /* Make sure the checkout database schema migration of 2019-01-19
1712
+ ** (the addition of the vmerge.mhash column and making that columns
1713
+ ** part of the PRIMARY KEY) has occurred.
1714
+ */
1715
+ if( !db_table_has_column("localdb", "vmerge", "mhash") ){
1716
+ db_multi_exec("ALTER TABLE vmerge RENAME TO old_vmerge;");
1717
+ db_multi_exec(zLocalSchemaVmerge /*works-like:""*/);
1718
+ db_multi_exec(
1719
+ "INSERT OR IGNORE INTO vmerge(id,merge,mhash)"
1720
+ " SELECT id, merge, blob.uuid FROM old_vmerge, blob"
1721
+ " WHERE old_vmerge.merge=blob.rid;"
1722
+ "DROP TABLE old_vmerge;"
1723
+ );
1724
+ }
16921725
}
16931726
}
16941727
16951728
/*
16961729
** Return true if there have been any changes to the repository
@@ -2880,11 +2913,11 @@
28802913
#if defined(_WIN32) || defined(__CYGWIN__)
28812914
# define LOCALDB_NAME "./_FOSSIL_"
28822915
#else
28832916
# define LOCALDB_NAME "./.fslckout"
28842917
#endif
2885
- db_init_database(LOCALDB_NAME, zLocalSchema,
2918
+ db_init_database(LOCALDB_NAME, zLocalSchema, zLocalSchemaVmerge,
28862919
#ifdef FOSSIL_LOCAL_WAL
28872920
"COMMIT; PRAGMA journal_mode=WAL; BEGIN;",
28882921
#endif
28892922
(char*)0);
28902923
db_delete_on_failure(LOCALDB_NAME);
28912924
--- src/db.c
+++ src/db.c
@@ -1473,33 +1473,44 @@
1473 ** If zDbName is a valid local database file, open it and return
1474 ** true. If it is not a valid local database file, return 0.
1475 */
1476 static int isValidLocalDb(const char *zDbName){
1477 i64 lsize;
1478 char *zVFileDef;
1479
1480 if( file_access(zDbName, F_OK) ) return 0;
1481 lsize = file_size(zDbName, ExtFILE);
1482 if( lsize%1024!=0 || lsize<4096 ) return 0;
1483 db_open_or_attach(zDbName, "localdb");
1484 zVFileDef = db_text(0, "SELECT sql FROM localdb.sqlite_master"
1485 " WHERE name=='vfile'");
1486 if( zVFileDef==0 ) return 0;
 
 
 
 
 
 
 
 
 
 
 
 
1487
1488 /* If the "isexe" column is missing from the vfile table, then
1489 ** add it now. This code added on 2010-03-06. After all users have
1490 ** upgraded, this code can be safely deleted.
1491 */
1492 if( sqlite3_strglob("* isexe *", zVFileDef)!=0 ){
1493 db_multi_exec("ALTER TABLE vfile ADD COLUMN isexe BOOLEAN DEFAULT 0");
1494 }
1495
1496 /* If "islink"/"isLink" columns are missing from tables, then
1497 ** add them now. This code added on 2011-01-17 and 2011-08-27.
1498 ** After all users have upgraded, this code can be safely deleted.
1499 */
1500 if( sqlite3_strglob("* islink *", zVFileDef)!=0 ){
1501 db_multi_exec("ALTER TABLE vfile ADD COLUMN islink BOOLEAN DEFAULT 0");
1502 if( db_local_table_exists_but_lacks_column("stashfile", "isLink") ){
1503 db_multi_exec("ALTER TABLE stashfile ADD COLUMN isLink BOOL DEFAULT 0");
1504 }
1505 if( db_local_table_exists_but_lacks_column("undo", "isLink") ){
@@ -1507,11 +1518,15 @@
1507 }
1508 if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){
1509 db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0");
1510 }
1511 }
1512 fossil_free(zVFileDef);
 
 
 
 
1513 return 1;
1514 }
1515
1516 /*
1517 ** Locate the root directory of the local repository tree. The root
@@ -1656,41 +1671,59 @@
1656 /* Make a change to the CHECK constraint on the BLOB table for
1657 ** version 2.0 and later.
1658 */
1659 rebuild_schema_update_2_0(); /* Do the Fossil-2.0 schema updates */
1660
1661 /* If the checkout database was opened first, then check to make
1662 ** sure that the repository database that was just opened has not
1663 ** be replaced by a clone of the same project, with different RID
1664 ** values.
1665 */
1666 if( g.localOpen && !db_fingerprint_ok() ){
1667 /* Uncomment the following when we are ready for automatic recovery: */
 
 
1668 #if 0
1669 stash_rid_renumbering_event();
1670 #else
1671 fossil_print(
1672 "Oops. It looks like the repository database file located at\n"
1673 " \"%s\"\n", zDbName
1674 );
1675 fossil_print(
1676 "has been swapped with a clone that may have different\n"
1677 "integer keys for the various artifacts. As of 2019-01-11,\n"
1678 "we are working on enhancing Fossil to be able to deal with\n"
1679 "that automatically, but we are not there yet. Sorry.\n\n"
1680 );
1681 fossil_print(
1682 "As an interim workaround, try:\n"
1683 " %s close --force\n"
1684 " %s open \"%s\" --keep\n"
1685 "Noting that any STASH and UNDO information "
1686 "WILL BE IRREVOCABLY LOST.\n\n",
1687 g.argv[0],
1688 g.argv[0], zDbName
1689 );
1690 fossil_fatal("bad fingerprint");
1691 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1692 }
1693 }
1694
1695 /*
1696 ** Return true if there have been any changes to the repository
@@ -2880,11 +2913,11 @@
2880 #if defined(_WIN32) || defined(__CYGWIN__)
2881 # define LOCALDB_NAME "./_FOSSIL_"
2882 #else
2883 # define LOCALDB_NAME "./.fslckout"
2884 #endif
2885 db_init_database(LOCALDB_NAME, zLocalSchema,
2886 #ifdef FOSSIL_LOCAL_WAL
2887 "COMMIT; PRAGMA journal_mode=WAL; BEGIN;",
2888 #endif
2889 (char*)0);
2890 db_delete_on_failure(LOCALDB_NAME);
2891
--- src/db.c
+++ src/db.c
@@ -1473,33 +1473,44 @@
1473 ** If zDbName is a valid local database file, open it and return
1474 ** true. If it is not a valid local database file, return 0.
1475 */
1476 static int isValidLocalDb(const char *zDbName){
1477 i64 lsize;
 
1478
1479 if( file_access(zDbName, F_OK) ) return 0;
1480 lsize = file_size(zDbName, ExtFILE);
1481 if( lsize%1024!=0 || lsize<4096 ) return 0;
1482 db_open_or_attach(zDbName, "localdb");
1483
1484 /* Check to see if the checkout database has the lastest schema changes.
1485 ** The most recent schema change (2019-01-19) is the addition of the
1486 ** vmerge.mhash field. If the schema has that one column, assume
1487 ** everything else is up-to-date.
1488 */
1489 if( db_table_has_column("localdb","vmerge","mhash") ){
1490 return 1; /* This is a checkout database with the latest schema */
1491 }
1492
1493 /* If there is no vfile table, then assume we have picked up something
1494 ** that is not even close to being a valid checkout database */
1495 if( !db_table_exists("localdb","vfile") ){
1496 return 0; /* Not a DB */
1497 }
1498
1499 /* If the "isexe" column is missing from the vfile table, then
1500 ** add it now. This code added on 2010-03-06. After all users have
1501 ** upgraded, this code can be safely deleted.
1502 */
1503 if( !db_table_has_column("localdb","vfile","isexe") ){
1504 db_multi_exec("ALTER TABLE vfile ADD COLUMN isexe BOOLEAN DEFAULT 0");
1505 }
1506
1507 /* If "islink"/"isLink" columns are missing from tables, then
1508 ** add them now. This code added on 2011-01-17 and 2011-08-27.
1509 ** After all users have upgraded, this code can be safely deleted.
1510 */
1511 if( !db_table_has_column("localdb","vfile","isLink") ){
1512 db_multi_exec("ALTER TABLE vfile ADD COLUMN islink BOOLEAN DEFAULT 0");
1513 if( db_local_table_exists_but_lacks_column("stashfile", "isLink") ){
1514 db_multi_exec("ALTER TABLE stashfile ADD COLUMN isLink BOOL DEFAULT 0");
1515 }
1516 if( db_local_table_exists_but_lacks_column("undo", "isLink") ){
@@ -1507,11 +1518,15 @@
1518 }
1519 if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){
1520 db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0");
1521 }
1522 }
1523
1524 /* The design of the vmerge table changed on 2019-01-19, adding the mhash
1525 ** column and changing the UNIQUE index. However, we must ahve the
1526 ** repository database at hand in order to do the migration, so that
1527 ** step is deferred. */
1528 return 1;
1529 }
1530
1531 /*
1532 ** Locate the root directory of the local repository tree. The root
@@ -1656,41 +1671,59 @@
1671 /* Make a change to the CHECK constraint on the BLOB table for
1672 ** version 2.0 and later.
1673 */
1674 rebuild_schema_update_2_0(); /* Do the Fossil-2.0 schema updates */
1675
1676 /* Additional checks that occur when opening the checkout database */
1677 if( g.localOpen ){
1678
1679 /* Ensure that the repository database that was just opened has not
1680 ** be replaced by a clone of the same project, with different RID
1681 ** values.
1682 */
1683 if( !db_fingerprint_ok() ){
1684 /* Uncomment the following when we are ready for automatic recovery: */
1685 #if 0
1686 stash_rid_renumbering_event();
1687 #else
1688 fossil_print(
1689 "Oops. It looks like the repository database file located at\n"
1690 " \"%s\"\n", zDbName
1691 );
1692 fossil_print(
1693 "has been swapped with a clone that may have different\n"
1694 "integer keys for the various artifacts. As of 2019-01-11,\n"
1695 "we are working on enhancing Fossil to be able to deal with\n"
1696 "that automatically, but we are not there yet. Sorry.\n\n"
1697 );
1698 fossil_print(
1699 "As an interim workaround, try:\n"
1700 " %s close --force\n"
1701 " %s open \"%s\" --keep\n"
1702 "Noting that any STASH and UNDO information "
1703 "WILL BE IRREVOCABLY LOST.\n\n",
1704 g.argv[0],
1705 g.argv[0], zDbName
1706 );
1707 fossil_fatal("bad fingerprint");
1708 #endif
1709 }else
1710
1711 /* Make sure the checkout database schema migration of 2019-01-19
1712 ** (the addition of the vmerge.mhash column and making that columns
1713 ** part of the PRIMARY KEY) has occurred.
1714 */
1715 if( !db_table_has_column("localdb", "vmerge", "mhash") ){
1716 db_multi_exec("ALTER TABLE vmerge RENAME TO old_vmerge;");
1717 db_multi_exec(zLocalSchemaVmerge /*works-like:""*/);
1718 db_multi_exec(
1719 "INSERT OR IGNORE INTO vmerge(id,merge,mhash)"
1720 " SELECT id, merge, blob.uuid FROM old_vmerge, blob"
1721 " WHERE old_vmerge.merge=blob.rid;"
1722 "DROP TABLE old_vmerge;"
1723 );
1724 }
1725 }
1726 }
1727
1728 /*
1729 ** Return true if there have been any changes to the repository
@@ -2880,11 +2913,11 @@
2913 #if defined(_WIN32) || defined(__CYGWIN__)
2914 # define LOCALDB_NAME "./_FOSSIL_"
2915 #else
2916 # define LOCALDB_NAME "./.fslckout"
2917 #endif
2918 db_init_database(LOCALDB_NAME, zLocalSchema, zLocalSchemaVmerge,
2919 #ifdef FOSSIL_LOCAL_WAL
2920 "COMMIT; PRAGMA journal_mode=WAL; BEGIN;",
2921 #endif
2922 (char*)0);
2923 db_delete_on_failure(LOCALDB_NAME);
2924
--- src/json_status.c
+++ src/json_status.c
@@ -154,12 +154,11 @@
154154
155155
#if 0
156156
/* TODO: add "merged with" status. First need (A) to decide on a
157157
structure and (B) to set up some tests for the multi-merge
158158
case.*/
159
- db_prepare(&q, "SELECT uuid, id FROM vmerge JOIN blob ON merge=rid"
160
- " WHERE id<=0");
159
+ db_prepare(&q, "SELECT mhash, id FROM vmerge WHERE id<=0");
161160
while( db_step(&q)==SQLITE_ROW ){
162161
const char *zLabel = "MERGED_WITH";
163162
switch( db_column_int(&q, 1) ){
164163
case -1: zLabel = "CHERRYPICK "; break;
165164
case -2: zLabel = "BACKOUT "; break;
166165
--- src/json_status.c
+++ src/json_status.c
@@ -154,12 +154,11 @@
154
155 #if 0
156 /* TODO: add "merged with" status. First need (A) to decide on a
157 structure and (B) to set up some tests for the multi-merge
158 case.*/
159 db_prepare(&q, "SELECT uuid, id FROM vmerge JOIN blob ON merge=rid"
160 " WHERE id<=0");
161 while( db_step(&q)==SQLITE_ROW ){
162 const char *zLabel = "MERGED_WITH";
163 switch( db_column_int(&q, 1) ){
164 case -1: zLabel = "CHERRYPICK "; break;
165 case -2: zLabel = "BACKOUT "; break;
166
--- src/json_status.c
+++ src/json_status.c
@@ -154,12 +154,11 @@
154
155 #if 0
156 /* TODO: add "merged with" status. First need (A) to decide on a
157 structure and (B) to set up some tests for the multi-merge
158 case.*/
159 db_prepare(&q, "SELECT mhash, id FROM vmerge WHERE id<=0");
 
160 while( db_step(&q)==SQLITE_ROW ){
161 const char *zLabel = "MERGED_WITH";
162 switch( db_column_int(&q, 1) ){
163 case -1: zLabel = "CHERRYPICK "; break;
164 case -2: zLabel = "BACKOUT "; break;
165
+15 -6
--- src/merge.c
+++ src/merge.c
@@ -164,10 +164,20 @@
164164
free(zN);
165165
free(zV);
166166
}
167167
free(aChng);
168168
}
169
+
170
+/* Make an entry in the vmerge table for the given id, and rid.
171
+*/
172
+static void vmerge_insert(int id, int rid){
173
+ db_multi_exec(
174
+ "INSERT OR IGNORE INTO vmerge(id,merge,mhash)"
175
+ "VALUES(%d,%d,(SELECT uuid FROM blob WHERE rid=%d))",
176
+ id, rid, rid
177
+ );
178
+}
169179
170180
/*
171181
** COMMAND: merge
172182
**
173183
** Usage: %fossil merge ?OPTIONS? ?VERSION?
@@ -664,12 +674,11 @@
664674
}
665675
blob_reset(&p);
666676
blob_reset(&m);
667677
blob_reset(&r);
668678
}
669
- db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(%d,%d)",
670
- idv,ridm);
679
+ vmerge_insert(idv, ridm);
671680
}
672681
db_finalize(&q);
673682
674683
/*
675684
** Drop files that are in P and V but not in M
@@ -826,24 +835,24 @@
826835
/*
827836
** Clean up the mid and pid VFILE entries. Then commit the changes.
828837
*/
829838
db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
830839
if( pickFlag ){
831
- db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(-1,%d)",mid);
840
+ vmerge_insert(-1, mid);
832841
/* For a cherry-pick merge, make the default check-in comment the same
833842
** as the check-in comment on the check-in that is being merged in. */
834843
db_multi_exec(
835844
"REPLACE INTO vvar(name,value)"
836845
" SELECT 'ci-comment', coalesce(ecomment,comment) FROM event"
837846
" WHERE type='ci' AND objid=%d",
838847
mid
839848
);
840849
}else if( backoutFlag ){
841
- db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(-2,%d)",pid);
850
+ vmerge_insert(-2, pid);
842851
}else if( integrateFlag ){
843
- db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(-4,%d)",mid);
852
+ vmerge_insert(-4, mid);
844853
}else{
845
- db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(0,%d)", mid);
854
+ vmerge_insert(0, mid);
846855
}
847856
if( !dryRunFlag ) undo_finish();
848857
db_end_transaction(dryRunFlag);
849858
}
850859
--- src/merge.c
+++ src/merge.c
@@ -164,10 +164,20 @@
164 free(zN);
165 free(zV);
166 }
167 free(aChng);
168 }
 
 
 
 
 
 
 
 
 
 
169
170 /*
171 ** COMMAND: merge
172 **
173 ** Usage: %fossil merge ?OPTIONS? ?VERSION?
@@ -664,12 +674,11 @@
664 }
665 blob_reset(&p);
666 blob_reset(&m);
667 blob_reset(&r);
668 }
669 db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(%d,%d)",
670 idv,ridm);
671 }
672 db_finalize(&q);
673
674 /*
675 ** Drop files that are in P and V but not in M
@@ -826,24 +835,24 @@
826 /*
827 ** Clean up the mid and pid VFILE entries. Then commit the changes.
828 */
829 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
830 if( pickFlag ){
831 db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(-1,%d)",mid);
832 /* For a cherry-pick merge, make the default check-in comment the same
833 ** as the check-in comment on the check-in that is being merged in. */
834 db_multi_exec(
835 "REPLACE INTO vvar(name,value)"
836 " SELECT 'ci-comment', coalesce(ecomment,comment) FROM event"
837 " WHERE type='ci' AND objid=%d",
838 mid
839 );
840 }else if( backoutFlag ){
841 db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(-2,%d)",pid);
842 }else if( integrateFlag ){
843 db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(-4,%d)",mid);
844 }else{
845 db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(0,%d)", mid);
846 }
847 if( !dryRunFlag ) undo_finish();
848 db_end_transaction(dryRunFlag);
849 }
850
--- src/merge.c
+++ src/merge.c
@@ -164,10 +164,20 @@
164 free(zN);
165 free(zV);
166 }
167 free(aChng);
168 }
169
170 /* Make an entry in the vmerge table for the given id, and rid.
171 */
172 static void vmerge_insert(int id, int rid){
173 db_multi_exec(
174 "INSERT OR IGNORE INTO vmerge(id,merge,mhash)"
175 "VALUES(%d,%d,(SELECT uuid FROM blob WHERE rid=%d))",
176 id, rid, rid
177 );
178 }
179
180 /*
181 ** COMMAND: merge
182 **
183 ** Usage: %fossil merge ?OPTIONS? ?VERSION?
@@ -664,12 +674,11 @@
674 }
675 blob_reset(&p);
676 blob_reset(&m);
677 blob_reset(&r);
678 }
679 vmerge_insert(idv, ridm);
 
680 }
681 db_finalize(&q);
682
683 /*
684 ** Drop files that are in P and V but not in M
@@ -826,24 +835,24 @@
835 /*
836 ** Clean up the mid and pid VFILE entries. Then commit the changes.
837 */
838 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
839 if( pickFlag ){
840 vmerge_insert(-1, mid);
841 /* For a cherry-pick merge, make the default check-in comment the same
842 ** as the check-in comment on the check-in that is being merged in. */
843 db_multi_exec(
844 "REPLACE INTO vvar(name,value)"
845 " SELECT 'ci-comment', coalesce(ecomment,comment) FROM event"
846 " WHERE type='ci' AND objid=%d",
847 mid
848 );
849 }else if( backoutFlag ){
850 vmerge_insert(-2, pid);
851 }else if( integrateFlag ){
852 vmerge_insert(-4, mid);
853 }else{
854 vmerge_insert(0, mid);
855 }
856 if( !dryRunFlag ) undo_finish();
857 db_end_transaction(dryRunFlag);
858 }
859
+26 -5
--- src/schema.c
+++ src/schema.c
@@ -490,11 +490,11 @@
490490
#endif
491491
492492
/*
493493
** The schema for the local FOSSIL database file found at the root
494494
** of every check-out. This database contains the complete state of
495
-** the checkout.
495
+** the checkout. See also the addendum in zLocalSchemaVmerge[].
496496
*/
497497
const char zLocalSchema[] =
498498
@ -- The VVAR table holds miscellanous information about the local database
499499
@ -- in the form of name-value pairs. This is similar to the VAR table
500500
@ -- table in the repository except that this table holds information that
@@ -539,27 +539,48 @@
539539
@ pathname TEXT, -- Full pathname relative to root
540540
@ origname TEXT, -- Original pathname. NULL if unchanged
541541
@ UNIQUE(pathname,vid)
542542
@ );
543543
@
544
+@ -- Identifier for this file type.
545
+@ -- The integer is the same as 'FSLC'.
546
+@ PRAGMA application_id=252006674;
547
+;
548
+
549
+/* Additional local database initialization following the schema
550
+** enhancement of 2019-01-19, in which the mhash column was added
551
+** to vmerge.
552
+*/
553
+const char zLocalSchemaVmerge[] =
544554
@ -- This table holds a record of uncommitted merges in the local
545555
@ -- file tree. If a VFILE entry with id has merged with another
546556
@ -- record, there is an entry in this table with (id,merge) where
547557
@ -- merge is the RECORD table entry that the file merged against.
548558
@ -- An id of 0 or <-3 here means the version record itself. When
549559
@ -- id==(-1) that is a cherrypick merge, id==(-2) that is a
550560
@ -- backout merge and id==(-4) is a integrate merge.
561
+@ --
551562
@
552563
@ CREATE TABLE vmerge(
553564
@ id INTEGER REFERENCES vfile, -- VFILE entry that has been merged
554565
@ merge INTEGER, -- Merged with this record
555
-@ UNIQUE(id, merge)
566
+@ mhash TEXT -- SHA1/SHA3 hash for merge object
556567
@ );
568
+@ CREATE UNIQUE INDEX vmergex1 ON vmerge(id,mhash);
569
+@
570
+@ -- The following trigger will prevent older versions of Fossil that
571
+@ -- do not know about the new vmerge.mhash column from updating the
572
+@ -- vmerge table. This must be done with a trigger, since legacy Fossil
573
+@ -- uses INSERT OR IGNORE to update vmerge, and the OR IGNORE will cause
574
+@ -- a NOT NULL constraint to be silently ignored.
557575
@
558
-@ -- Identifier for this file type.
559
-@ -- The integer is the same as 'FSLC'.
560
-@ PRAGMA application_id=252006674;
576
+@ CREATE TRIGGER vmerge_ck1 AFTER INSERT ON vmerge
577
+@ WHEN new.mhash IS NULL BEGIN
578
+@ SELECT raise(FAIL,
579
+@ 'trying to update a newer checkout with an older version of Fossil');
580
+@ END;
581
+@
561582
;
562583
563584
/*
564585
** The following table holds information about forum posts. It
565586
** is created on-demand whenever the manifest parser encounters
566587
--- src/schema.c
+++ src/schema.c
@@ -490,11 +490,11 @@
490 #endif
491
492 /*
493 ** The schema for the local FOSSIL database file found at the root
494 ** of every check-out. This database contains the complete state of
495 ** the checkout.
496 */
497 const char zLocalSchema[] =
498 @ -- The VVAR table holds miscellanous information about the local database
499 @ -- in the form of name-value pairs. This is similar to the VAR table
500 @ -- table in the repository except that this table holds information that
@@ -539,27 +539,48 @@
539 @ pathname TEXT, -- Full pathname relative to root
540 @ origname TEXT, -- Original pathname. NULL if unchanged
541 @ UNIQUE(pathname,vid)
542 @ );
543 @
 
 
 
 
 
 
 
 
 
 
544 @ -- This table holds a record of uncommitted merges in the local
545 @ -- file tree. If a VFILE entry with id has merged with another
546 @ -- record, there is an entry in this table with (id,merge) where
547 @ -- merge is the RECORD table entry that the file merged against.
548 @ -- An id of 0 or <-3 here means the version record itself. When
549 @ -- id==(-1) that is a cherrypick merge, id==(-2) that is a
550 @ -- backout merge and id==(-4) is a integrate merge.
 
551 @
552 @ CREATE TABLE vmerge(
553 @ id INTEGER REFERENCES vfile, -- VFILE entry that has been merged
554 @ merge INTEGER, -- Merged with this record
555 @ UNIQUE(id, merge)
556 @ );
 
 
 
 
 
 
 
557 @
558 @ -- Identifier for this file type.
559 @ -- The integer is the same as 'FSLC'.
560 @ PRAGMA application_id=252006674;
 
 
 
561 ;
562
563 /*
564 ** The following table holds information about forum posts. It
565 ** is created on-demand whenever the manifest parser encounters
566
--- src/schema.c
+++ src/schema.c
@@ -490,11 +490,11 @@
490 #endif
491
492 /*
493 ** The schema for the local FOSSIL database file found at the root
494 ** of every check-out. This database contains the complete state of
495 ** the checkout. See also the addendum in zLocalSchemaVmerge[].
496 */
497 const char zLocalSchema[] =
498 @ -- The VVAR table holds miscellanous information about the local database
499 @ -- in the form of name-value pairs. This is similar to the VAR table
500 @ -- table in the repository except that this table holds information that
@@ -539,27 +539,48 @@
539 @ pathname TEXT, -- Full pathname relative to root
540 @ origname TEXT, -- Original pathname. NULL if unchanged
541 @ UNIQUE(pathname,vid)
542 @ );
543 @
544 @ -- Identifier for this file type.
545 @ -- The integer is the same as 'FSLC'.
546 @ PRAGMA application_id=252006674;
547 ;
548
549 /* Additional local database initialization following the schema
550 ** enhancement of 2019-01-19, in which the mhash column was added
551 ** to vmerge.
552 */
553 const char zLocalSchemaVmerge[] =
554 @ -- This table holds a record of uncommitted merges in the local
555 @ -- file tree. If a VFILE entry with id has merged with another
556 @ -- record, there is an entry in this table with (id,merge) where
557 @ -- merge is the RECORD table entry that the file merged against.
558 @ -- An id of 0 or <-3 here means the version record itself. When
559 @ -- id==(-1) that is a cherrypick merge, id==(-2) that is a
560 @ -- backout merge and id==(-4) is a integrate merge.
561 @ --
562 @
563 @ CREATE TABLE vmerge(
564 @ id INTEGER REFERENCES vfile, -- VFILE entry that has been merged
565 @ merge INTEGER, -- Merged with this record
566 @ mhash TEXT -- SHA1/SHA3 hash for merge object
567 @ );
568 @ CREATE UNIQUE INDEX vmergex1 ON vmerge(id,mhash);
569 @
570 @ -- The following trigger will prevent older versions of Fossil that
571 @ -- do not know about the new vmerge.mhash column from updating the
572 @ -- vmerge table. This must be done with a trigger, since legacy Fossil
573 @ -- uses INSERT OR IGNORE to update vmerge, and the OR IGNORE will cause
574 @ -- a NOT NULL constraint to be silently ignored.
575 @
576 @ CREATE TRIGGER vmerge_ck1 AFTER INSERT ON vmerge
577 @ WHEN new.mhash IS NULL BEGIN
578 @ SELECT raise(FAIL,
579 @ 'trying to update a newer checkout with an older version of Fossil');
580 @ END;
581 @
582 ;
583
584 /*
585 ** The following table holds information about forum posts. It
586 ** is created on-demand whenever the manifest parser encounters
587
+1 -2
--- src/update.c
+++ src/update.c
@@ -529,12 +529,11 @@
529529
/* Report on conflicts
530530
*/
531531
if( !dryRunFlag ){
532532
Stmt q;
533533
int nMerge = 0;
534
- db_prepare(&q, "SELECT uuid, id FROM vmerge JOIN blob ON merge=rid"
535
- " WHERE id<=0");
534
+ db_prepare(&q, "SELECT mhash, id FROM vmerge WHERE id<=0");
536535
while( db_step(&q)==SQLITE_ROW ){
537536
const char *zLabel = "merge";
538537
switch( db_column_int(&q, 1) ){
539538
case -1: zLabel = "cherrypick merge"; break;
540539
case -2: zLabel = "backout merge"; break;
541540
--- src/update.c
+++ src/update.c
@@ -529,12 +529,11 @@
529 /* Report on conflicts
530 */
531 if( !dryRunFlag ){
532 Stmt q;
533 int nMerge = 0;
534 db_prepare(&q, "SELECT uuid, id FROM vmerge JOIN blob ON merge=rid"
535 " WHERE id<=0");
536 while( db_step(&q)==SQLITE_ROW ){
537 const char *zLabel = "merge";
538 switch( db_column_int(&q, 1) ){
539 case -1: zLabel = "cherrypick merge"; break;
540 case -2: zLabel = "backout merge"; break;
541
--- src/update.c
+++ src/update.c
@@ -529,12 +529,11 @@
529 /* Report on conflicts
530 */
531 if( !dryRunFlag ){
532 Stmt q;
533 int nMerge = 0;
534 db_prepare(&q, "SELECT mhash, id FROM vmerge WHERE id<=0");
 
535 while( db_step(&q)==SQLITE_ROW ){
536 const char *zLabel = "merge";
537 switch( db_column_int(&q, 1) ){
538 case -1: zLabel = "cherrypick merge"; break;
539 case -2: zLabel = "backout merge"; break;
540

Keyboard Shortcuts

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