| | @@ -1542,14 +1542,126 @@ |
| 1542 | 1542 | if( pmid<=0 ) continue; |
| 1543 | 1543 | add_mlink(pmid, 0, mid, pChild, 0); |
| 1544 | 1544 | } |
| 1545 | 1545 | } |
| 1546 | 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 | +} |
| 1547 | 1655 | |
| 1548 | 1656 | /* |
| 1549 | 1657 | ** 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(). |
| 1551 | 1663 | */ |
| 1552 | 1664 | void manifest_crosslink_begin(void){ |
| 1553 | 1665 | assert( manifest_crosslink_busy==0 ); |
| 1554 | 1666 | manifest_crosslink_busy = 1; |
| 1555 | 1667 | db_begin_transaction(); |
| | @@ -1592,10 +1704,21 @@ |
| 1592 | 1704 | rc = xfer_run_common_script(); |
| 1593 | 1705 | if( rc==TH_OK ){ |
| 1594 | 1706 | zScript = xfer_ticket_code(); |
| 1595 | 1707 | } |
| 1596 | 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); |
| 1597 | 1720 | db_prepare(&q, "SELECT uuid FROM pending_tkt"); |
| 1598 | 1721 | while( db_step(&q)==SQLITE_ROW ){ |
| 1599 | 1722 | const char *zUuid = db_column_text(&q, 0); |
| 1600 | 1723 | ticket_rebuild_entry(zUuid); |
| 1601 | 1724 | if( permitHooks && rc==TH_OK ){ |
| | @@ -1837,54 +1960,11 @@ |
| 1837 | 1960 | zScript = xfer_commit_code(); |
| 1838 | 1961 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1839 | 1962 | } |
| 1840 | 1963 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){ |
| 1841 | 1964 | 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); |
| 1886 | 1966 | search_doc_touch('c', rid, 0); |
| 1887 | 1967 | db_multi_exec( |
| 1888 | 1968 | "REPLACE INTO event(type,mtime,objid,user,comment," |
| 1889 | 1969 | "bgcolor,euser,ecomment,omtime)" |
| 1890 | 1970 | "VALUES('ci'," |
| 1891 | 1971 | |