Fossil

Check-in [faf09dc7]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Define a "leaf" as a check-in with no children in the same branch. The is_a_leaf() function does some complicated SQL to figure this out.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:faf09dc7ae5417fd4a8b09cc67c7c6ef9c9793a9
User & Date: drh 2009-01-22 01:53:04
Context
2009-01-22
12:03
Change the way branches are tagged: The value of the "branch" property is used to identify the branch name. Repository rebuild required. Also, branches must be retagged. check-in: 42c2a18e user: drh tags: trunk
01:53
Define a "leaf" as a check-in with no children in the same branch. The is_a_leaf() function does some complicated SQL to figure this out. check-in: faf09dc7 user: drh tags: trunk
01:10
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. check-in: 042a08b5 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/checkin.c.

344
345
346
347
348
349
350
351
352
353


354
355
356



357
358
359
360


361
362






363
364
365
366













367
368
369
370
371
372
373
      blob_reset(&b);
    }
    g.aCommitFile[ii-2] = 0;
  }
}

/*
** Return true if the check-in with RID=rid has no child
** check-ins which are not tagged with "newbranch".  In other words,
** return true if the check-in is a leaf.


*/
int is_a_leaf(int rid){
  return !db_exists(



    "SELECT 1 FROM plink"
    " WHERE pid=%d"
      " AND NOT EXISTS("
                     "SELECT 1 FROM tagxref"


                     " WHERE tagxref.rid=plink.cid"
                     "   AND tagxref.tagid=%d"






                     "   AND tagxref.tagtype=1"
               ")",
    rid, TAG_NEWBRANCH
  );













}

/*
** COMMAND: ci
** COMMAND: commit
**
** Usage: %fossil commit ?-m COMMENT? ?--nosign? ?FILE...?







|
|
|
>
>


<
>
>
>
|
|
<
<
>
>
|
<
>
>
>
>
>
>
|
<
<
<
>
>
>
>
>
>
>
>
>
>
>
>
>







344
345
346
347
348
349
350
351
352
353
354
355
356
357

358
359
360
361
362


363
364
365

366
367
368
369
370
371
372



373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
      blob_reset(&b);
    }
    g.aCommitFile[ii-2] = 0;
  }
}

/*
** Return true if the check-in with RID=rid is a leaf.
**
** A leaf has no children in the same branch.  For the purposes of
** this definition, a two check-ins are in same branch they have the
** same set of propagated symbolic tags.
*/
int is_a_leaf(int rid){


  /* This query selects all children in the same branch as rid */
  static const char zSql[] = 
    @ SELECT cid FROM plink
    @  WHERE pid=:rid


    @    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 tag.tagname GLOB 'sym-*'
    @            ORDER BY 1)
    @        )
  ;
  Stmt q;    /* The prepared statement */
  int rc;    /* Return code from stepping the prepared statement */

  db_prepare(&q, zSql);
  db_bind_int(&q, ":rid", rid);
  rc = db_step(&q);
  db_finalize(&q);
  return rc==SQLITE_DONE;
}

/*
** COMMAND: ci
** COMMAND: commit
**
** Usage: %fossil commit ?-m COMMENT? ?--nosign? ?FILE...?

Changes to src/descendants.c.

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
..
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
** Show all leaves, use closeMode==1.  To show only closed leaves, use
** closeMode==2.
*/
void compute_leaves(int iBase, int closeMode){
  Bag seen;       /* Descendants seen */
  Bag pending;    /* Unpropagated descendants */
  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(
................................................................................
  bag_init(&seen);
  bag_init(&pending);
  bag_insert(&pending, iBase);

  /* 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
................................................................................
      db_bind_int(&isBr, ":rid", cid);
      if( db_step(&isBr)==SQLITE_DONE ){
        cnt++;
      }
      db_reset(&isBr);
    }
    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);
    }
  }
  db_finalize(&ins);
  db_finalize(&isBr);
  db_finalize(&q2);
  db_finalize(&q1);
  bag_clear(&pending);
  bag_clear(&seen);
  if( closeMode==1 ){
    db_multi_exec(
      "DELETE FROM leaves WHERE rid IN"
      "  (SELECT leaves.rid FROM leaves, tagxref"







<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|
<
<
|
<
<









<







60
61
62
63
64
65
66

67
68
69
70
71
72
73
..
90
91
92
93
94
95
96






















97
98
99
100
101
102
103
...
120
121
122
123
124
125
126
127


128


129
130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
** Show all leaves, use closeMode==1.  To show only closed leaves, use
** closeMode==2.
*/
void compute_leaves(int iBase, int closeMode){
  Bag seen;       /* Descendants seen */
  Bag pending;    /* Unpropagated descendants */
  Stmt q1;        /* Query to find children of a check-in */

  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(
................................................................................
  bag_init(&seen);
  bag_init(&pending);
  bag_insert(&pending, iBase);

  /* 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 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
................................................................................
      db_bind_int(&isBr, ":rid", cid);
      if( db_step(&isBr)==SQLITE_DONE ){
        cnt++;
      }
      db_reset(&isBr);
    }
    db_reset(&q1);
    if( cnt==0 && !is_a_leaf(rid) ){


      cnt++;


    }
    if( cnt==0 ){
      db_bind_int(&ins, ":rid", rid);
      db_step(&ins);
      db_reset(&ins);
    }
  }
  db_finalize(&ins);
  db_finalize(&isBr);

  db_finalize(&q1);
  bag_clear(&pending);
  bag_clear(&seen);
  if( closeMode==1 ){
    db_multi_exec(
      "DELETE FROM leaves WHERE rid IN"
      "  (SELECT leaves.rid FROM leaves, tagxref"