Fossil SCM

Add the "fossil reparent" command and the --dryrun option on "fossil tag add" and "fossil tag cancel".

drh 2016-06-10 14:41 UTC trunk merge
Commit 96164bb2b137b482894749129d9cd206d819320d
4 files changed +1 -2 +1 -2 +125 -45 +102 -11
+1 -2
--- src/import.c
+++ src/import.c
@@ -925,12 +925,11 @@
925925
/*
926926
** Returns the UUID for the RID, or NULL if not found.
927927
** The returned string is allocated via db_text() and must be
928928
** free()d by the caller.
929929
*/
930
-char * rid_to_uuid(int rid)
931
-{
930
+char *rid_to_uuid(int rid){
932931
return db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
933932
}
934933
935934
#define SVN_UNKNOWN 0
936935
#define SVN_TRUNK 1
937936
--- src/import.c
+++ src/import.c
@@ -925,12 +925,11 @@
925 /*
926 ** Returns the UUID for the RID, or NULL if not found.
927 ** The returned string is allocated via db_text() and must be
928 ** free()d by the caller.
929 */
930 char * rid_to_uuid(int rid)
931 {
932 return db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
933 }
934
935 #define SVN_UNKNOWN 0
936 #define SVN_TRUNK 1
937
--- src/import.c
+++ src/import.c
@@ -925,12 +925,11 @@
925 /*
926 ** Returns the UUID for the RID, or NULL if not found.
927 ** The returned string is allocated via db_text() and must be
928 ** free()d by the caller.
929 */
930 char *rid_to_uuid(int rid){
 
931 return db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
932 }
933
934 #define SVN_UNKNOWN 0
935 #define SVN_TRUNK 1
936
+1 -2
--- src/import.c
+++ src/import.c
@@ -925,12 +925,11 @@
925925
/*
926926
** Returns the UUID for the RID, or NULL if not found.
927927
** The returned string is allocated via db_text() and must be
928928
** free()d by the caller.
929929
*/
930
-char * rid_to_uuid(int rid)
931
-{
930
+char *rid_to_uuid(int rid){
932931
return db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
933932
}
934933
935934
#define SVN_UNKNOWN 0
936935
#define SVN_TRUNK 1
937936
--- src/import.c
+++ src/import.c
@@ -925,12 +925,11 @@
925 /*
926 ** Returns the UUID for the RID, or NULL if not found.
927 ** The returned string is allocated via db_text() and must be
928 ** free()d by the caller.
929 */
930 char * rid_to_uuid(int rid)
931 {
932 return db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
933 }
934
935 #define SVN_UNKNOWN 0
936 #define SVN_TRUNK 1
937
--- src/import.c
+++ src/import.c
@@ -925,12 +925,11 @@
925 /*
926 ** Returns the UUID for the RID, or NULL if not found.
927 ** The returned string is allocated via db_text() and must be
928 ** free()d by the caller.
929 */
930 char *rid_to_uuid(int rid){
 
931 return db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
932 }
933
934 #define SVN_UNKNOWN 0
935 #define SVN_TRUNK 1
936
+125 -45
--- src/manifest.c
+++ src/manifest.c
@@ -1542,14 +1542,126 @@
15421542
if( pmid<=0 ) continue;
15431543
add_mlink(pmid, 0, mid, pChild, 0);
15441544
}
15451545
}
15461546
}
1547
+
1548
+/*
1549
+** For a check-in with RID "rid" that has nParent parent check-ins given
1550
+** by the UUIDs in azParent[], create all appropriate plink and mlink table
1551
+** entries.
1552
+**
1553
+** The primary parent is the first UUID on the azParent[] list.
1554
+**
1555
+** Return the RID of the primary parent.
1556
+*/
1557
+static int manifest_add_checkin_linkages(
1558
+ int rid, /* The RID of the check-in */
1559
+ Manifest *p, /* Manifest for this check-in */
1560
+ int nParent, /* Number of parents for this check-in */
1561
+ char **azParent /* UUIDs for each parent */
1562
+){
1563
+ int i;
1564
+ int parentid = 0;
1565
+ char zBaseId[30]; /* Baseline manifest RID for deltas. "NULL" otherwise */
1566
+ Stmt q;
1567
+
1568
+ if( p->zBaseline ){
1569
+ sqlite3_snprintf(sizeof(zBaseId), zBaseId, "%d",
1570
+ uuid_to_rid(p->zBaseline,1));
1571
+ }else{
1572
+ sqlite3_snprintf(sizeof(zBaseId), zBaseId, "NULL");
1573
+ }
1574
+ for(i=0; i<nParent; i++){
1575
+ int pid = uuid_to_rid(azParent[i], 1);
1576
+ db_multi_exec(
1577
+ "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
1578
+ "VALUES(%d, %d, %d, %.17g, %s)",
1579
+ pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
1580
+ if( i==0 ) parentid = pid;
1581
+ }
1582
+ add_mlink(parentid, 0, rid, p, 1);
1583
+ if( nParent>1 ){
1584
+ /* Change MLINK.PID from 0 to -1 for files that are added by merge. */
1585
+ db_multi_exec(
1586
+ "UPDATE mlink SET pid=-1"
1587
+ " WHERE mid=%d"
1588
+ " AND pid=0"
1589
+ " AND fnid IN "
1590
+ " (SELECT fnid FROM mlink WHERE mid=%d GROUP BY fnid"
1591
+ " HAVING count(*)<%d)",
1592
+ rid, rid, nParent
1593
+ );
1594
+ }
1595
+ db_prepare(&q, "SELECT cid, isprim FROM plink WHERE pid=%d", rid);
1596
+ while( db_step(&q)==SQLITE_ROW ){
1597
+ int cid = db_column_int(&q, 0);
1598
+ int isprim = db_column_int(&q, 1);
1599
+ add_mlink(rid, p, cid, 0, isprim);
1600
+ }
1601
+ db_finalize(&q);
1602
+ if( nParent==0 ){
1603
+ /* For root files (files without parents) add mlink entries
1604
+ ** showing all content as new. */
1605
+ int isPublic = !content_is_private(rid);
1606
+ for(i=0; i<p->nFile; i++){
1607
+ add_one_mlink(0, 0, rid, p->aFile[i].zUuid, p->aFile[i].zName, 0,
1608
+ isPublic, 1, manifest_file_mperm(&p->aFile[i]));
1609
+ }
1610
+ }
1611
+ return parentid;
1612
+}
1613
+
1614
+/*
1615
+** There exists a "parent" tag against checkin rid that has value zValue.
1616
+** If value is well-formed (meaning that is is a list of UUIDs), then use
1617
+** zValue to reparent check-in rid.
1618
+*/
1619
+void manifest_reparent_checkin(int rid, const char *zValue){
1620
+ int nParent;
1621
+ char *zCopy = 0;
1622
+ char **azParent = 0;
1623
+ Manifest *p = 0;
1624
+ int i;
1625
+ int n = (int)strlen(zValue);
1626
+ nParent = (n+1)/(UUID_SIZE+1);
1627
+ if( nParent*(UUID_SIZE+1) - 1 !=n ) return;
1628
+ if( nParent<1 ) return;
1629
+ zCopy = fossil_strdup(zValue);
1630
+ azParent = fossil_malloc( sizeof(azParent[0])*nParent );
1631
+ for(i=0; i<nParent; i++){
1632
+ azParent[i] = &zCopy[i*(UUID_SIZE+1)];
1633
+ if( i<nParent-1 && azParent[i][UUID_SIZE]!=' ' ) break;
1634
+ azParent[i][UUID_SIZE] = 0;
1635
+ if( !validate16(azParent[i],UUID_SIZE) ) break;
1636
+ }
1637
+ if( i==nParent
1638
+ && !db_exists("SELECT 1 FROM plink WHERE cid=%d AND pid=%d",
1639
+ rid, uuid_to_rid(azParent[0],0))
1640
+ ){
1641
+ p = manifest_get(rid, CFTYPE_MANIFEST, 0);
1642
+ }
1643
+ if( p!=0 ){
1644
+ db_multi_exec(
1645
+ "DELETE FROM plink WHERE cid=%d;"
1646
+ "DELETE FROM mlink WHERE mid=%d;",
1647
+ rid, rid
1648
+ );
1649
+ manifest_add_checkin_linkages(rid,p,nParent,azParent);
1650
+ }
1651
+ manifest_destroy(p);
1652
+ fossil_free(azParent);
1653
+ fossil_free(zCopy);
1654
+}
15471655
15481656
/*
15491657
** Setup to do multiple manifest_crosslink() calls.
1550
-** This is only required if processing ticket changes.
1658
+**
1659
+** This routine creates TEMP tables for holding information for
1660
+** processing that must be deferred until all artifacts have been
1661
+** seen at least once. The deferred processing is accomplished
1662
+** by the call to manifest_crosslink_end().
15511663
*/
15521664
void manifest_crosslink_begin(void){
15531665
assert( manifest_crosslink_busy==0 );
15541666
manifest_crosslink_busy = 1;
15551667
db_begin_transaction();
@@ -1592,10 +1704,21 @@
15921704
rc = xfer_run_common_script();
15931705
if( rc==TH_OK ){
15941706
zScript = xfer_ticket_code();
15951707
}
15961708
}
1709
+ db_prepare(&q,
1710
+ "SELECT rid, value FROM tagxref"
1711
+ " WHERE tagid=%d AND tagtype=1",
1712
+ TAG_PARENT
1713
+ );
1714
+ while( db_step(&q)==SQLITE_ROW ){
1715
+ int rid = db_column_int(&q,0);
1716
+ const char *zValue = db_column_text(&q,1);
1717
+ manifest_reparent_checkin(rid, zValue);
1718
+ }
1719
+ db_finalize(&q);
15971720
db_prepare(&q, "SELECT uuid FROM pending_tkt");
15981721
while( db_step(&q)==SQLITE_ROW ){
15991722
const char *zUuid = db_column_text(&q, 0);
16001723
ticket_rebuild_entry(zUuid);
16011724
if( permitHooks && rc==TH_OK ){
@@ -1837,54 +1960,11 @@
18371960
zScript = xfer_commit_code();
18381961
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
18391962
}
18401963
if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
18411964
char *zCom;
1842
- char zBaseId[30];
1843
- if( p->zBaseline ){
1844
- sqlite3_snprintf(sizeof(zBaseId), zBaseId, "%d",
1845
- uuid_to_rid(p->zBaseline,1));
1846
- }else{
1847
- sqlite3_snprintf(sizeof(zBaseId), zBaseId, "NULL");
1848
- }
1849
- for(i=0; i<p->nParent; i++){
1850
- int pid = uuid_to_rid(p->azParent[i], 1);
1851
- db_multi_exec(
1852
- "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
1853
- "VALUES(%d, %d, %d, %.17g, %s)",
1854
- pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
1855
- if( i==0 ) parentid = pid;
1856
- }
1857
- add_mlink(parentid, 0, rid, p, 1);
1858
- if( p->nParent>1 ){
1859
- /* Change MLINK.PID from 0 to -1 for files that are added by merge. */
1860
- db_multi_exec(
1861
- "UPDATE mlink SET pid=-1"
1862
- " WHERE mid=%d"
1863
- " AND pid=0"
1864
- " AND fnid IN "
1865
- " (SELECT fnid FROM mlink WHERE mid=%d GROUP BY fnid"
1866
- " HAVING count(*)<%d)",
1867
- rid, rid, p->nParent
1868
- );
1869
- }
1870
- db_prepare(&q, "SELECT cid, isprim FROM plink WHERE pid=%d", rid);
1871
- while( db_step(&q)==SQLITE_ROW ){
1872
- int cid = db_column_int(&q, 0);
1873
- int isprim = db_column_int(&q, 1);
1874
- add_mlink(rid, p, cid, 0, isprim);
1875
- }
1876
- db_finalize(&q);
1877
- if( p->nParent==0 ){
1878
- /* For root files (files without parents) add mlink entries
1879
- ** showing all content as new. */
1880
- int isPublic = !content_is_private(rid);
1881
- for(i=0; i<p->nFile; i++){
1882
- add_one_mlink(0, 0, rid, p->aFile[i].zUuid, p->aFile[i].zName, 0,
1883
- isPublic, 1, manifest_file_mperm(&p->aFile[i]));
1884
- }
1885
- }
1965
+ parentid = manifest_add_checkin_linkages(rid,p,p->nParent,p->azParent);
18861966
search_doc_touch('c', rid, 0);
18871967
db_multi_exec(
18881968
"REPLACE INTO event(type,mtime,objid,user,comment,"
18891969
"bgcolor,euser,ecomment,omtime)"
18901970
"VALUES('ci',"
18911971
--- src/manifest.c
+++ src/manifest.c
@@ -1542,14 +1542,126 @@
1542 if( pmid<=0 ) continue;
1543 add_mlink(pmid, 0, mid, pChild, 0);
1544 }
1545 }
1546 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1547
1548 /*
1549 ** Setup to do multiple manifest_crosslink() calls.
1550 ** This is only required if processing ticket changes.
 
 
 
 
1551 */
1552 void manifest_crosslink_begin(void){
1553 assert( manifest_crosslink_busy==0 );
1554 manifest_crosslink_busy = 1;
1555 db_begin_transaction();
@@ -1592,10 +1704,21 @@
1592 rc = xfer_run_common_script();
1593 if( rc==TH_OK ){
1594 zScript = xfer_ticket_code();
1595 }
1596 }
 
 
 
 
 
 
 
 
 
 
 
1597 db_prepare(&q, "SELECT uuid FROM pending_tkt");
1598 while( db_step(&q)==SQLITE_ROW ){
1599 const char *zUuid = db_column_text(&q, 0);
1600 ticket_rebuild_entry(zUuid);
1601 if( permitHooks && rc==TH_OK ){
@@ -1837,54 +1960,11 @@
1837 zScript = xfer_commit_code();
1838 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1839 }
1840 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
1841 char *zCom;
1842 char zBaseId[30];
1843 if( p->zBaseline ){
1844 sqlite3_snprintf(sizeof(zBaseId), zBaseId, "%d",
1845 uuid_to_rid(p->zBaseline,1));
1846 }else{
1847 sqlite3_snprintf(sizeof(zBaseId), zBaseId, "NULL");
1848 }
1849 for(i=0; i<p->nParent; i++){
1850 int pid = uuid_to_rid(p->azParent[i], 1);
1851 db_multi_exec(
1852 "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
1853 "VALUES(%d, %d, %d, %.17g, %s)",
1854 pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
1855 if( i==0 ) parentid = pid;
1856 }
1857 add_mlink(parentid, 0, rid, p, 1);
1858 if( p->nParent>1 ){
1859 /* Change MLINK.PID from 0 to -1 for files that are added by merge. */
1860 db_multi_exec(
1861 "UPDATE mlink SET pid=-1"
1862 " WHERE mid=%d"
1863 " AND pid=0"
1864 " AND fnid IN "
1865 " (SELECT fnid FROM mlink WHERE mid=%d GROUP BY fnid"
1866 " HAVING count(*)<%d)",
1867 rid, rid, p->nParent
1868 );
1869 }
1870 db_prepare(&q, "SELECT cid, isprim FROM plink WHERE pid=%d", rid);
1871 while( db_step(&q)==SQLITE_ROW ){
1872 int cid = db_column_int(&q, 0);
1873 int isprim = db_column_int(&q, 1);
1874 add_mlink(rid, p, cid, 0, isprim);
1875 }
1876 db_finalize(&q);
1877 if( p->nParent==0 ){
1878 /* For root files (files without parents) add mlink entries
1879 ** showing all content as new. */
1880 int isPublic = !content_is_private(rid);
1881 for(i=0; i<p->nFile; i++){
1882 add_one_mlink(0, 0, rid, p->aFile[i].zUuid, p->aFile[i].zName, 0,
1883 isPublic, 1, manifest_file_mperm(&p->aFile[i]));
1884 }
1885 }
1886 search_doc_touch('c', rid, 0);
1887 db_multi_exec(
1888 "REPLACE INTO event(type,mtime,objid,user,comment,"
1889 "bgcolor,euser,ecomment,omtime)"
1890 "VALUES('ci',"
1891
--- src/manifest.c
+++ src/manifest.c
@@ -1542,14 +1542,126 @@
1542 if( pmid<=0 ) continue;
1543 add_mlink(pmid, 0, mid, pChild, 0);
1544 }
1545 }
1546 }
1547
1548 /*
1549 ** For a check-in with RID "rid" that has nParent parent check-ins given
1550 ** by the UUIDs in azParent[], create all appropriate plink and mlink table
1551 ** entries.
1552 **
1553 ** The primary parent is the first UUID on the azParent[] list.
1554 **
1555 ** Return the RID of the primary parent.
1556 */
1557 static int manifest_add_checkin_linkages(
1558 int rid, /* The RID of the check-in */
1559 Manifest *p, /* Manifest for this check-in */
1560 int nParent, /* Number of parents for this check-in */
1561 char **azParent /* UUIDs for each parent */
1562 ){
1563 int i;
1564 int parentid = 0;
1565 char zBaseId[30]; /* Baseline manifest RID for deltas. "NULL" otherwise */
1566 Stmt q;
1567
1568 if( p->zBaseline ){
1569 sqlite3_snprintf(sizeof(zBaseId), zBaseId, "%d",
1570 uuid_to_rid(p->zBaseline,1));
1571 }else{
1572 sqlite3_snprintf(sizeof(zBaseId), zBaseId, "NULL");
1573 }
1574 for(i=0; i<nParent; i++){
1575 int pid = uuid_to_rid(azParent[i], 1);
1576 db_multi_exec(
1577 "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
1578 "VALUES(%d, %d, %d, %.17g, %s)",
1579 pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
1580 if( i==0 ) parentid = pid;
1581 }
1582 add_mlink(parentid, 0, rid, p, 1);
1583 if( nParent>1 ){
1584 /* Change MLINK.PID from 0 to -1 for files that are added by merge. */
1585 db_multi_exec(
1586 "UPDATE mlink SET pid=-1"
1587 " WHERE mid=%d"
1588 " AND pid=0"
1589 " AND fnid IN "
1590 " (SELECT fnid FROM mlink WHERE mid=%d GROUP BY fnid"
1591 " HAVING count(*)<%d)",
1592 rid, rid, nParent
1593 );
1594 }
1595 db_prepare(&q, "SELECT cid, isprim FROM plink WHERE pid=%d", rid);
1596 while( db_step(&q)==SQLITE_ROW ){
1597 int cid = db_column_int(&q, 0);
1598 int isprim = db_column_int(&q, 1);
1599 add_mlink(rid, p, cid, 0, isprim);
1600 }
1601 db_finalize(&q);
1602 if( nParent==0 ){
1603 /* For root files (files without parents) add mlink entries
1604 ** showing all content as new. */
1605 int isPublic = !content_is_private(rid);
1606 for(i=0; i<p->nFile; i++){
1607 add_one_mlink(0, 0, rid, p->aFile[i].zUuid, p->aFile[i].zName, 0,
1608 isPublic, 1, manifest_file_mperm(&p->aFile[i]));
1609 }
1610 }
1611 return parentid;
1612 }
1613
1614 /*
1615 ** There exists a "parent" tag against checkin rid that has value zValue.
1616 ** If value is well-formed (meaning that is is a list of UUIDs), then use
1617 ** zValue to reparent check-in rid.
1618 */
1619 void manifest_reparent_checkin(int rid, const char *zValue){
1620 int nParent;
1621 char *zCopy = 0;
1622 char **azParent = 0;
1623 Manifest *p = 0;
1624 int i;
1625 int n = (int)strlen(zValue);
1626 nParent = (n+1)/(UUID_SIZE+1);
1627 if( nParent*(UUID_SIZE+1) - 1 !=n ) return;
1628 if( nParent<1 ) return;
1629 zCopy = fossil_strdup(zValue);
1630 azParent = fossil_malloc( sizeof(azParent[0])*nParent );
1631 for(i=0; i<nParent; i++){
1632 azParent[i] = &zCopy[i*(UUID_SIZE+1)];
1633 if( i<nParent-1 && azParent[i][UUID_SIZE]!=' ' ) break;
1634 azParent[i][UUID_SIZE] = 0;
1635 if( !validate16(azParent[i],UUID_SIZE) ) break;
1636 }
1637 if( i==nParent
1638 && !db_exists("SELECT 1 FROM plink WHERE cid=%d AND pid=%d",
1639 rid, uuid_to_rid(azParent[0],0))
1640 ){
1641 p = manifest_get(rid, CFTYPE_MANIFEST, 0);
1642 }
1643 if( p!=0 ){
1644 db_multi_exec(
1645 "DELETE FROM plink WHERE cid=%d;"
1646 "DELETE FROM mlink WHERE mid=%d;",
1647 rid, rid
1648 );
1649 manifest_add_checkin_linkages(rid,p,nParent,azParent);
1650 }
1651 manifest_destroy(p);
1652 fossil_free(azParent);
1653 fossil_free(zCopy);
1654 }
1655
1656 /*
1657 ** Setup to do multiple manifest_crosslink() calls.
1658 **
1659 ** This routine creates TEMP tables for holding information for
1660 ** processing that must be deferred until all artifacts have been
1661 ** seen at least once. The deferred processing is accomplished
1662 ** by the call to manifest_crosslink_end().
1663 */
1664 void manifest_crosslink_begin(void){
1665 assert( manifest_crosslink_busy==0 );
1666 manifest_crosslink_busy = 1;
1667 db_begin_transaction();
@@ -1592,10 +1704,21 @@
1704 rc = xfer_run_common_script();
1705 if( rc==TH_OK ){
1706 zScript = xfer_ticket_code();
1707 }
1708 }
1709 db_prepare(&q,
1710 "SELECT rid, value FROM tagxref"
1711 " WHERE tagid=%d AND tagtype=1",
1712 TAG_PARENT
1713 );
1714 while( db_step(&q)==SQLITE_ROW ){
1715 int rid = db_column_int(&q,0);
1716 const char *zValue = db_column_text(&q,1);
1717 manifest_reparent_checkin(rid, zValue);
1718 }
1719 db_finalize(&q);
1720 db_prepare(&q, "SELECT uuid FROM pending_tkt");
1721 while( db_step(&q)==SQLITE_ROW ){
1722 const char *zUuid = db_column_text(&q, 0);
1723 ticket_rebuild_entry(zUuid);
1724 if( permitHooks && rc==TH_OK ){
@@ -1837,54 +1960,11 @@
1960 zScript = xfer_commit_code();
1961 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1962 }
1963 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
1964 char *zCom;
1965 parentid = manifest_add_checkin_linkages(rid,p,p->nParent,p->azParent);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1966 search_doc_touch('c', rid, 0);
1967 db_multi_exec(
1968 "REPLACE INTO event(type,mtime,objid,user,comment,"
1969 "bgcolor,euser,ecomment,omtime)"
1970 "VALUES('ci',"
1971
+102 -11
--- src/tag.c
+++ src/tag.c
@@ -148,10 +148,13 @@
148148
return id;
149149
}
150150
151151
/*
152152
** Insert a tag into the database.
153
+**
154
+** Also translate zTag into a tagid and return the tagid. (In other words
155
+** if zTag is "bgcolor" then return TAG_BGCOLOR.)
153156
*/
154157
int tag_insert(
155158
const char *zTag, /* Name of the tag (w/o the "+" or "-" prefix */
156159
int tagtype, /* 0:cancel 1:singleton 2:propagated */
157160
const char *zValue, /* Value if the tag is really a property */
@@ -228,10 +231,13 @@
228231
" SET mtime=julianday(%Q),"
229232
" omtime=coalesce(omtime,mtime)"
230233
" WHERE objid=%d",
231234
zValue, rid);
232235
}
236
+ if( tagid==TAG_PARENT && tagtype==1 ){
237
+ manifest_reparent_checkin(rid, zValue);
238
+ }
233239
if( tagtype==1 ) tagtype = 0;
234240
tag_propagate(rid, tagid, tagtype, rid, zValue, mtime);
235241
return tagid;
236242
}
237243
@@ -273,13 +279,26 @@
273279
db_begin_transaction();
274280
tag_insert(zTag, tagtype, zValue, -1, 0.0, rid);
275281
db_end_transaction(0);
276282
}
277283
284
+/*
285
+** OR this value into the tagtype argument to tag_add_artifact to
286
+** cause the tag to be displayed on standard output rather than be
287
+** inserted. Used for --dryrun options and debugging.
288
+*/
289
+#if INTERFACE
290
+#define TAG_ADD_DRYRUN 0x04
291
+#endif
292
+
278293
/*
279294
** Add a control record to the repository that either creates
280295
** or cancels a tag.
296
+**
297
+** tagtype should normally be 0, 1, or 2. But if the TAG_ADD_DRYRUN bit
298
+** is also set, then simply print the text of the tag on standard output
299
+** (for testing purposes) rather than create the tag.
281300
*/
282301
void tag_add_artifact(
283302
const char *zPrefix, /* Prefix to prepend to tag name */
284303
const char *zTagname, /* The tag to add or cancel */
285304
const char *zObjName, /* Name of object attached to */
@@ -293,11 +312,16 @@
293312
char *zDate;
294313
Blob uuid;
295314
Blob ctrl;
296315
Blob cksum;
297316
static const char zTagtype[] = { '-', '+', '*' };
317
+ int dryRun = 0;
298318
319
+ if( tagtype & TAG_ADD_DRYRUN ){
320
+ tagtype &= ~TAG_ADD_DRYRUN;
321
+ dryRun = 1;
322
+ }
299323
assert( tagtype>=0 && tagtype<=2 );
300324
user_select();
301325
blob_zero(&uuid);
302326
blob_append(&uuid, zObjName, -1);
303327
if( name_to_uuid(&uuid, 9, "*") ){
@@ -327,12 +351,17 @@
327351
blob_appendf(&ctrl, "\n");
328352
}
329353
blob_appendf(&ctrl, "U %F\n", zUserOvrd ? zUserOvrd : login_name());
330354
md5sum_blob(&ctrl, &cksum);
331355
blob_appendf(&ctrl, "Z %b\n", &cksum);
332
- nrid = content_put(&ctrl);
333
- manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS);
356
+ if( dryRun ){
357
+ fossil_print("%s", blob_str(&ctrl));
358
+ blob_reset(&ctrl);
359
+ }else{
360
+ nrid = content_put(&ctrl);
361
+ manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS);
362
+ }
334363
assert( blob_is_reset(&ctrl) );
335364
}
336365
337366
/*
338367
** COMMAND: tag
@@ -347,23 +376,26 @@
347376
** be usable instead of a CHECK-IN in commands such as
348377
** update and merge. If the --propagate flag is present,
349378
** the tag value propagates to all descendants of CHECK-IN
350379
**
351380
** Options:
352
-** --raw Raw tag name.
353
-** --propagate Propagating tag.
354
-** --date-override DATETIME Set date and time added.
355
-** --user-override USER Name USER when adding the tag.
381
+** --raw Raw tag name.
382
+** --propagate Propagating tag.
383
+** --date-override DATETIME Set date and time added.
384
+** --user-override USER Name USER when adding the tag.
385
+** --dryrun|-n Display the tag text, but to not
386
+** actually insert it into the database.
356387
**
357388
** The --date-override and --user-override options support
358389
** importing history from other SCM systems. DATETIME has
359390
** the form 'YYYY-MMM-DD HH:MM:SS'.
360391
**
361392
** %fossil tag cancel ?--raw? TAGNAME CHECK-IN
362393
**
363394
** Remove the tag TAGNAME from CHECK-IN, and also remove
364
-** the propagation of the tag to any descendants.
395
+** the propagation of the tag to any descendants. Use the
396
+** the --dryrun or -n options to see what would have happened.
365397
**
366398
** %fossil tag find ?OPTIONS? TAGNAME
367399
**
368400
** List all objects that use TAGNAME. TYPE can be "ci" for
369401
** check-ins or "e" for events. The limit option limits the number
@@ -416,33 +448,37 @@
416448
goto tag_cmd_usage;
417449
}
418450
419451
if( strncmp(g.argv[2],"add",n)==0 ){
420452
char *zValue;
453
+ int dryRun = 0;
421454
const char *zDateOvrd = find_option("date-override",0,1);
422455
const char *zUserOvrd = find_option("user-override",0,1);
456
+ if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN;
423457
if( g.argc!=5 && g.argc!=6 ){
424
- usage("add ?--raw? ?--propagate? TAGNAME CHECK-IN ?VALUE?");
458
+ usage("add ?options? TAGNAME CHECK-IN ?VALUE?");
425459
}
426460
zValue = g.argc==6 ? g.argv[5] : 0;
427461
db_begin_transaction();
428462
tag_add_artifact(zPrefix, g.argv[3], g.argv[4], zValue,
429
- 1+fPropagate,zDateOvrd,zUserOvrd);
463
+ 1+fPropagate+dryRun,zDateOvrd,zUserOvrd);
430464
db_end_transaction(0);
431465
}else
432466
433467
if( strncmp(g.argv[2],"branch",n)==0 ){
434468
fossil_fatal("the \"fossil tag branch\" command is discontinued\n"
435469
"Use the \"fossil branch new\" command instead.");
436470
}else
437471
438472
if( strncmp(g.argv[2],"cancel",n)==0 ){
473
+ int dryRun = 0;
474
+ if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN;
439475
if( g.argc!=5 ){
440
- usage("cancel ?--raw? TAGNAME CHECK-IN");
476
+ usage("cancel ?options? TAGNAME CHECK-IN");
441477
}
442478
db_begin_transaction();
443
- tag_add_artifact(zPrefix, g.argv[3], g.argv[4], 0, 0, 0, 0);
479
+ tag_add_artifact(zPrefix, g.argv[3], g.argv[4], 0, dryRun, 0, 0);
444480
db_end_transaction(0);
445481
}else
446482
447483
if( strncmp(g.argv[2],"find",n)==0 ){
448484
Stmt q;
@@ -546,10 +582,65 @@
546582
return;
547583
548584
tag_cmd_usage:
549585
usage("add|cancel|find|list ...");
550586
}
587
+
588
+/*
589
+** COMMAND: reparent*
590
+**
591
+** Usage: %fossil reparent [OPTIONS] CHECK-IN PARENT ....
592
+**
593
+** Create a "parent" tag that causes CHECK-IN to be interpreted as a
594
+** child of PARENT. If multiple PARENTs are listed, then the first is
595
+** the primary parent and others are merge ancestors.
596
+**
597
+** This is an experts-only command. It is used to patch up a repository
598
+** that has been damaged by a shun or that has been pieced together from
599
+** two or more separate repositories. You should never need to reparent
600
+** during normal operations.
601
+**
602
+** Reparenting is accomplished by adding a parent tag. So to undo the
603
+** reparenting operation, simply delete the tag.
604
+**
605
+** --test Make database entries but do not add the tag artifact.
606
+** So the reparent operation will be undone by the next
607
+** "fossil rebuild" command.
608
+** --dryrun | -n Print the tag that would have been created but do not
609
+** actually change the database in any way.
610
+*/
611
+void reparent_cmd(void){
612
+ int bTest = find_option("test","",0)!=0;
613
+ int rid;
614
+ int i;
615
+ Blob value;
616
+ char *zUuid;
617
+ int dryRun = 0;
618
+
619
+ if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN;
620
+ db_find_and_open_repository(0, 0);
621
+ verify_all_options();
622
+ if( g.argc<4 ){
623
+ usage("reparent [OPTIONS] PARENT ...");
624
+ }
625
+ rid = name_to_typed_rid(g.argv[2], "ci");
626
+ blob_init(&value, 0, 0);
627
+ for(i=3; i<g.argc; i++){
628
+ int pid = name_to_typed_rid(g.argv[i], "ci");
629
+ if( i>3 ) blob_append(&value, " ", 1);
630
+ zUuid = rid_to_uuid(pid);
631
+ blob_append(&value, zUuid, UUID_SIZE);
632
+ fossil_free(zUuid);
633
+ }
634
+ if( bTest && !dryRun ){
635
+ tag_insert("parent", 1, blob_str(&value), -1, 0.0, rid);
636
+ }else{
637
+ zUuid = rid_to_uuid(rid);
638
+ tag_add_artifact("","parent",zUuid,blob_str(&value),1|dryRun,0,0);
639
+ }
640
+}
641
+
551642
552643
/*
553644
** WEBPAGE: taglist
554645
**
555646
** List all non-propagating symbolic tags.
556647
--- src/tag.c
+++ src/tag.c
@@ -148,10 +148,13 @@
148 return id;
149 }
150
151 /*
152 ** Insert a tag into the database.
 
 
 
153 */
154 int tag_insert(
155 const char *zTag, /* Name of the tag (w/o the "+" or "-" prefix */
156 int tagtype, /* 0:cancel 1:singleton 2:propagated */
157 const char *zValue, /* Value if the tag is really a property */
@@ -228,10 +231,13 @@
228 " SET mtime=julianday(%Q),"
229 " omtime=coalesce(omtime,mtime)"
230 " WHERE objid=%d",
231 zValue, rid);
232 }
 
 
 
233 if( tagtype==1 ) tagtype = 0;
234 tag_propagate(rid, tagid, tagtype, rid, zValue, mtime);
235 return tagid;
236 }
237
@@ -273,13 +279,26 @@
273 db_begin_transaction();
274 tag_insert(zTag, tagtype, zValue, -1, 0.0, rid);
275 db_end_transaction(0);
276 }
277
 
 
 
 
 
 
 
 
 
278 /*
279 ** Add a control record to the repository that either creates
280 ** or cancels a tag.
 
 
 
 
281 */
282 void tag_add_artifact(
283 const char *zPrefix, /* Prefix to prepend to tag name */
284 const char *zTagname, /* The tag to add or cancel */
285 const char *zObjName, /* Name of object attached to */
@@ -293,11 +312,16 @@
293 char *zDate;
294 Blob uuid;
295 Blob ctrl;
296 Blob cksum;
297 static const char zTagtype[] = { '-', '+', '*' };
 
298
 
 
 
 
299 assert( tagtype>=0 && tagtype<=2 );
300 user_select();
301 blob_zero(&uuid);
302 blob_append(&uuid, zObjName, -1);
303 if( name_to_uuid(&uuid, 9, "*") ){
@@ -327,12 +351,17 @@
327 blob_appendf(&ctrl, "\n");
328 }
329 blob_appendf(&ctrl, "U %F\n", zUserOvrd ? zUserOvrd : login_name());
330 md5sum_blob(&ctrl, &cksum);
331 blob_appendf(&ctrl, "Z %b\n", &cksum);
332 nrid = content_put(&ctrl);
333 manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS);
 
 
 
 
 
334 assert( blob_is_reset(&ctrl) );
335 }
336
337 /*
338 ** COMMAND: tag
@@ -347,23 +376,26 @@
347 ** be usable instead of a CHECK-IN in commands such as
348 ** update and merge. If the --propagate flag is present,
349 ** the tag value propagates to all descendants of CHECK-IN
350 **
351 ** Options:
352 ** --raw Raw tag name.
353 ** --propagate Propagating tag.
354 ** --date-override DATETIME Set date and time added.
355 ** --user-override USER Name USER when adding the tag.
 
 
356 **
357 ** The --date-override and --user-override options support
358 ** importing history from other SCM systems. DATETIME has
359 ** the form 'YYYY-MMM-DD HH:MM:SS'.
360 **
361 ** %fossil tag cancel ?--raw? TAGNAME CHECK-IN
362 **
363 ** Remove the tag TAGNAME from CHECK-IN, and also remove
364 ** the propagation of the tag to any descendants.
 
365 **
366 ** %fossil tag find ?OPTIONS? TAGNAME
367 **
368 ** List all objects that use TAGNAME. TYPE can be "ci" for
369 ** check-ins or "e" for events. The limit option limits the number
@@ -416,33 +448,37 @@
416 goto tag_cmd_usage;
417 }
418
419 if( strncmp(g.argv[2],"add",n)==0 ){
420 char *zValue;
 
421 const char *zDateOvrd = find_option("date-override",0,1);
422 const char *zUserOvrd = find_option("user-override",0,1);
 
423 if( g.argc!=5 && g.argc!=6 ){
424 usage("add ?--raw? ?--propagate? TAGNAME CHECK-IN ?VALUE?");
425 }
426 zValue = g.argc==6 ? g.argv[5] : 0;
427 db_begin_transaction();
428 tag_add_artifact(zPrefix, g.argv[3], g.argv[4], zValue,
429 1+fPropagate,zDateOvrd,zUserOvrd);
430 db_end_transaction(0);
431 }else
432
433 if( strncmp(g.argv[2],"branch",n)==0 ){
434 fossil_fatal("the \"fossil tag branch\" command is discontinued\n"
435 "Use the \"fossil branch new\" command instead.");
436 }else
437
438 if( strncmp(g.argv[2],"cancel",n)==0 ){
 
 
439 if( g.argc!=5 ){
440 usage("cancel ?--raw? TAGNAME CHECK-IN");
441 }
442 db_begin_transaction();
443 tag_add_artifact(zPrefix, g.argv[3], g.argv[4], 0, 0, 0, 0);
444 db_end_transaction(0);
445 }else
446
447 if( strncmp(g.argv[2],"find",n)==0 ){
448 Stmt q;
@@ -546,10 +582,65 @@
546 return;
547
548 tag_cmd_usage:
549 usage("add|cancel|find|list ...");
550 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
551
552 /*
553 ** WEBPAGE: taglist
554 **
555 ** List all non-propagating symbolic tags.
556
--- src/tag.c
+++ src/tag.c
@@ -148,10 +148,13 @@
148 return id;
149 }
150
151 /*
152 ** Insert a tag into the database.
153 **
154 ** Also translate zTag into a tagid and return the tagid. (In other words
155 ** if zTag is "bgcolor" then return TAG_BGCOLOR.)
156 */
157 int tag_insert(
158 const char *zTag, /* Name of the tag (w/o the "+" or "-" prefix */
159 int tagtype, /* 0:cancel 1:singleton 2:propagated */
160 const char *zValue, /* Value if the tag is really a property */
@@ -228,10 +231,13 @@
231 " SET mtime=julianday(%Q),"
232 " omtime=coalesce(omtime,mtime)"
233 " WHERE objid=%d",
234 zValue, rid);
235 }
236 if( tagid==TAG_PARENT && tagtype==1 ){
237 manifest_reparent_checkin(rid, zValue);
238 }
239 if( tagtype==1 ) tagtype = 0;
240 tag_propagate(rid, tagid, tagtype, rid, zValue, mtime);
241 return tagid;
242 }
243
@@ -273,13 +279,26 @@
279 db_begin_transaction();
280 tag_insert(zTag, tagtype, zValue, -1, 0.0, rid);
281 db_end_transaction(0);
282 }
283
284 /*
285 ** OR this value into the tagtype argument to tag_add_artifact to
286 ** cause the tag to be displayed on standard output rather than be
287 ** inserted. Used for --dryrun options and debugging.
288 */
289 #if INTERFACE
290 #define TAG_ADD_DRYRUN 0x04
291 #endif
292
293 /*
294 ** Add a control record to the repository that either creates
295 ** or cancels a tag.
296 **
297 ** tagtype should normally be 0, 1, or 2. But if the TAG_ADD_DRYRUN bit
298 ** is also set, then simply print the text of the tag on standard output
299 ** (for testing purposes) rather than create the tag.
300 */
301 void tag_add_artifact(
302 const char *zPrefix, /* Prefix to prepend to tag name */
303 const char *zTagname, /* The tag to add or cancel */
304 const char *zObjName, /* Name of object attached to */
@@ -293,11 +312,16 @@
312 char *zDate;
313 Blob uuid;
314 Blob ctrl;
315 Blob cksum;
316 static const char zTagtype[] = { '-', '+', '*' };
317 int dryRun = 0;
318
319 if( tagtype & TAG_ADD_DRYRUN ){
320 tagtype &= ~TAG_ADD_DRYRUN;
321 dryRun = 1;
322 }
323 assert( tagtype>=0 && tagtype<=2 );
324 user_select();
325 blob_zero(&uuid);
326 blob_append(&uuid, zObjName, -1);
327 if( name_to_uuid(&uuid, 9, "*") ){
@@ -327,12 +351,17 @@
351 blob_appendf(&ctrl, "\n");
352 }
353 blob_appendf(&ctrl, "U %F\n", zUserOvrd ? zUserOvrd : login_name());
354 md5sum_blob(&ctrl, &cksum);
355 blob_appendf(&ctrl, "Z %b\n", &cksum);
356 if( dryRun ){
357 fossil_print("%s", blob_str(&ctrl));
358 blob_reset(&ctrl);
359 }else{
360 nrid = content_put(&ctrl);
361 manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS);
362 }
363 assert( blob_is_reset(&ctrl) );
364 }
365
366 /*
367 ** COMMAND: tag
@@ -347,23 +376,26 @@
376 ** be usable instead of a CHECK-IN in commands such as
377 ** update and merge. If the --propagate flag is present,
378 ** the tag value propagates to all descendants of CHECK-IN
379 **
380 ** Options:
381 ** --raw Raw tag name.
382 ** --propagate Propagating tag.
383 ** --date-override DATETIME Set date and time added.
384 ** --user-override USER Name USER when adding the tag.
385 ** --dryrun|-n Display the tag text, but to not
386 ** actually insert it into the database.
387 **
388 ** The --date-override and --user-override options support
389 ** importing history from other SCM systems. DATETIME has
390 ** the form 'YYYY-MMM-DD HH:MM:SS'.
391 **
392 ** %fossil tag cancel ?--raw? TAGNAME CHECK-IN
393 **
394 ** Remove the tag TAGNAME from CHECK-IN, and also remove
395 ** the propagation of the tag to any descendants. Use the
396 ** the --dryrun or -n options to see what would have happened.
397 **
398 ** %fossil tag find ?OPTIONS? TAGNAME
399 **
400 ** List all objects that use TAGNAME. TYPE can be "ci" for
401 ** check-ins or "e" for events. The limit option limits the number
@@ -416,33 +448,37 @@
448 goto tag_cmd_usage;
449 }
450
451 if( strncmp(g.argv[2],"add",n)==0 ){
452 char *zValue;
453 int dryRun = 0;
454 const char *zDateOvrd = find_option("date-override",0,1);
455 const char *zUserOvrd = find_option("user-override",0,1);
456 if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN;
457 if( g.argc!=5 && g.argc!=6 ){
458 usage("add ?options? TAGNAME CHECK-IN ?VALUE?");
459 }
460 zValue = g.argc==6 ? g.argv[5] : 0;
461 db_begin_transaction();
462 tag_add_artifact(zPrefix, g.argv[3], g.argv[4], zValue,
463 1+fPropagate+dryRun,zDateOvrd,zUserOvrd);
464 db_end_transaction(0);
465 }else
466
467 if( strncmp(g.argv[2],"branch",n)==0 ){
468 fossil_fatal("the \"fossil tag branch\" command is discontinued\n"
469 "Use the \"fossil branch new\" command instead.");
470 }else
471
472 if( strncmp(g.argv[2],"cancel",n)==0 ){
473 int dryRun = 0;
474 if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN;
475 if( g.argc!=5 ){
476 usage("cancel ?options? TAGNAME CHECK-IN");
477 }
478 db_begin_transaction();
479 tag_add_artifact(zPrefix, g.argv[3], g.argv[4], 0, dryRun, 0, 0);
480 db_end_transaction(0);
481 }else
482
483 if( strncmp(g.argv[2],"find",n)==0 ){
484 Stmt q;
@@ -546,10 +582,65 @@
582 return;
583
584 tag_cmd_usage:
585 usage("add|cancel|find|list ...");
586 }
587
588 /*
589 ** COMMAND: reparent*
590 **
591 ** Usage: %fossil reparent [OPTIONS] CHECK-IN PARENT ....
592 **
593 ** Create a "parent" tag that causes CHECK-IN to be interpreted as a
594 ** child of PARENT. If multiple PARENTs are listed, then the first is
595 ** the primary parent and others are merge ancestors.
596 **
597 ** This is an experts-only command. It is used to patch up a repository
598 ** that has been damaged by a shun or that has been pieced together from
599 ** two or more separate repositories. You should never need to reparent
600 ** during normal operations.
601 **
602 ** Reparenting is accomplished by adding a parent tag. So to undo the
603 ** reparenting operation, simply delete the tag.
604 **
605 ** --test Make database entries but do not add the tag artifact.
606 ** So the reparent operation will be undone by the next
607 ** "fossil rebuild" command.
608 ** --dryrun | -n Print the tag that would have been created but do not
609 ** actually change the database in any way.
610 */
611 void reparent_cmd(void){
612 int bTest = find_option("test","",0)!=0;
613 int rid;
614 int i;
615 Blob value;
616 char *zUuid;
617 int dryRun = 0;
618
619 if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN;
620 db_find_and_open_repository(0, 0);
621 verify_all_options();
622 if( g.argc<4 ){
623 usage("reparent [OPTIONS] PARENT ...");
624 }
625 rid = name_to_typed_rid(g.argv[2], "ci");
626 blob_init(&value, 0, 0);
627 for(i=3; i<g.argc; i++){
628 int pid = name_to_typed_rid(g.argv[i], "ci");
629 if( i>3 ) blob_append(&value, " ", 1);
630 zUuid = rid_to_uuid(pid);
631 blob_append(&value, zUuid, UUID_SIZE);
632 fossil_free(zUuid);
633 }
634 if( bTest && !dryRun ){
635 tag_insert("parent", 1, blob_str(&value), -1, 0.0, rid);
636 }else{
637 zUuid = rid_to_uuid(rid);
638 tag_add_artifact("","parent",zUuid,blob_str(&value),1|dryRun,0,0);
639 }
640 }
641
642
643 /*
644 ** WEBPAGE: taglist
645 **
646 ** List all non-propagating symbolic tags.
647

Keyboard Shortcuts

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