Diff
Not logged in

Differences From:

File src/descendants.c part of check-in [2fa4df1e47] - Add timeline links on the leaves page. Also on the leaves page, do not show Merge labels on check-ins. The second part is the fix for ticket d6bb26f436d8299f95d63f45fa51c92acdc91c5a. by drh on 2009-01-21 18:59:11. [view]

To:

File src/descendants.c part of check-in [042a08b564] - Improved messages in the "tags and properties" section of the vinfo page. Distinguish between a merge between forks and a merge between branches. A merge from forks, closes the fork, but not a merge from a branch. by drh on 2009-01-22 01:10:41. [view]

@@ -62,39 +62,82 @@
 */
 void compute_leaves(int iBase, int closeMode){
   Bag seen;       /* Descendants seen */
   Bag pending;    /* Unpropagated descendants */
-  Stmt q;         /* Query to find children of a check-in */
+  Stmt q1;        /* Query to find children of a check-in */
+  Stmt q2;        /* Query to detect if a merge is across branches */
   Stmt isBr;      /* Query to check to see if a check-in starts a new branch */
   Stmt ins;       /* INSERT statement for a new record */
 
+  /* Create the LEAVES table if it does not already exist.  Make sure
+  ** it is empty.
+  */
   db_multi_exec(
     "CREATE TEMP TABLE IF NOT EXISTS leaves("
     "  rid INTEGER PRIMARY KEY"
     ");"
     "DELETE FROM leaves;"
   );
-  bag_init(&seen);
-  bag_init(&pending);
+
+  /* We are checking all descendants of iBase.  If iBase==0, then
+  ** change iBase to be the root of the entire check-in hierarchy.
+  */
   if( iBase<=0 ){
     iBase = db_int(0, "SELECT objid FROM event WHERE type='ci'"
                       " ORDER BY mtime LIMIT 1");
     if( iBase==0 ) return;
   }
+
+  /* Initialize the bags. */
+  bag_init(&seen);
+  bag_init(&pending);
   bag_insert(&pending, iBase);
-  db_prepare(&q, "SELECT cid FROM plink WHERE pid=:rid");
+
+  /* This query returns all non-merge children of check-in :rid */
+  db_prepare(&q1, "SELECT cid FROM plink WHERE pid=:rid AND isprim");
+
+  /* This query returns all merge children of check-in :rid where
+  ** the child and parent are on same branch.  The child and
+  ** parent are assumed to be on same branch if they have
+  ** the same set of propagated symbolic tags.
+  */
+  db_prepare(&q2,
+     "SELECT cid FROM plink"
+     " WHERE pid=:rid AND NOT isprim"
+     "   AND (SELECT group_concat(x) FROM ("
+     "          SELECT tag.tagid AS x FROM tagxref, tag"
+     "           WHERE tagxref.rid=:rid AND tagxref.tagtype=2"
+     "             AND tag.tagid=tagxref.tagid AND tagxref.srcid=0"
+     "             AND tag.tagname GLOB 'sym-*'"
+     "           ORDER BY 1))"
+     "    == (SELECT group_concat(x) FROM ("
+     "          SELECT tag.tagid AS x FROM tagxref, tag"
+     "           WHERE tagxref.rid=plink.cid AND tagxref.tagtype=2"
+     "             AND tag.tagid=tagxref.tagid AND tagxref.srcid=0"
+     "             AND tag.tagname GLOB 'sym-*'"
+     "           ORDER BY 1))"
+  );
+
+  /* This query returns a single row if check-in :rid is the first
+  ** check-in of a new branch.  In other words, it returns a row if
+  ** check-in :rid has the 'newbranch' tag.
+  */
   db_prepare(&isBr,
      "SELECT 1 FROM tagxref WHERE rid=:rid AND tagid=%d AND tagtype=1",
      TAG_NEWBRANCH
   );
+
+  /* This statement inserts check-in :rid into the LEAVES table.
+  */
   db_prepare(&ins, "INSERT OR IGNORE INTO leaves VALUES(:rid)");
+
   while( bag_count(&pending) ){
     int rid = bag_first(&pending);
     int cnt = 0;
     bag_remove(&pending, rid);
-    db_bind_int(&q, ":rid", rid);
-    while( db_step(&q)==SQLITE_ROW ){
-      int cid = db_column_int(&q, 0);
+    db_bind_int(&q1, ":rid", rid);
+    while( db_step(&q1)==SQLITE_ROW ){
+      int cid = db_column_int(&q1, 0);
       if( bag_insert(&seen, cid) ){
         bag_insert(&pending, cid);
       }
       db_bind_int(&isBr, ":rid", cid);
@@ -102,9 +145,16 @@
         cnt++;
       }
       db_reset(&isBr);
     }
-    db_reset(&q);
+    db_reset(&q1);
+    if( cnt==0 ){
+      db_bind_int(&q2, ":rid", rid);
+      if( db_step(&q2)==SQLITE_ROW ){
+        cnt++;
+      }
+      db_reset(&q2);
+    }
     if( cnt==0 ){
       db_bind_int(&ins, ":rid", rid);
       db_step(&ins);
       db_reset(&ins);
@@ -111,9 +161,10 @@
     }
   }
   db_finalize(&ins);
   db_finalize(&isBr);
-  db_finalize(&q);
+  db_finalize(&q2);
+  db_finalize(&q1);
   bag_clear(&pending);
   bag_clear(&seen);
   if( closeMode==1 ){
     db_multi_exec(