Fossil

Diff
Login

Differences From Artifact [a11699aaf4]:

To Artifact [a19ebf91b9]:


28
29
30
31
32
33
34
35
36

























37
38
39
40



41
42
43
44
45
46
47
48
49




50






51
52
53
54
55
56
57
58
59
60
61


62
63


64
65
66


67
68



69
70



















71
72
73
74
75
76
77
#include "descendants.h"
#include <assert.h>


/*
** Create a temporary table named "leaves" if it does not
** already exist.  Load this table with the RID of all
** versions that are leaves which are decended from
** version iBase.

























*/
void compute_leaves(int iBase){
  Bag seen;       /* Descendants seen */
  Bag pending;    /* Unpropagated descendants */




  db_multi_exec(
    "CREATE TEMP TABLE IF NOT EXISTS leaves("
    "  rid INTEGER PRIMARY KEY"
    ");"
    "DELETE FROM leaves;"
  );
  bag_init(&seen);
  bag_init(&pending);




  bag_insert(&pending, iBase);






  while( bag_count(&pending) ){
    int rid = bag_first(&pending);
    int cnt = 0;
    Stmt q;
    bag_remove(&pending, rid);
    db_prepare(&q, "SELECT cid FROM plink WHERE pid=%d", rid);
    while( db_step(&q)==SQLITE_ROW ){
      int cid = db_column_int(&q, 0);
      if( bag_insert(&seen, cid) ){
        bag_insert(&pending, cid);
      }


      cnt++;
    }


    db_finalize(&q);
    if( cnt==0 ){
      db_multi_exec("INSERT INTO leaves VALUES(%d)", rid);


    }
  }



  bag_clear(&pending);
  bag_clear(&seen);



















}

/*
** Load the record ID rid and up to N-1 closest ancestors into
** the "ok" table.
*/
void compute_ancestors(int rid, int N){







|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|


>
>
>









>
>
>
>

>
>
>
>
>
>



<

|





>
>
|
|
>
>
|

|
>
>


>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include "descendants.h"
#include <assert.h>


/*
** Create a temporary table named "leaves" if it does not
** already exist.  Load this table with the RID of all
** check-ins that are leaves which are decended from
** check-in iBase.
**
** A "leaf" is a check-in that has no children.  For the purpose
** of finding leaves, children marked with the "newbranch" tag are
** not counted as children.  For example:
**
**
**    A -> B -> C -> D
**          `-> E
**
** D and E are clearly leaves since they have no children.  If
** D has the "newbranch" tag, then C is also a leaf since its only
** child is marked as a newbranch.
**
** The closeMode flag determines behavior associated with the "closed"
** tag:
**
**    closeMode==0       Show all leaves regardless of the "closed" tag.
**
**    closeMode==1       Show only leaves without the "closed" tag.
**
**    closeMode==2       Show only leaves with the "closed" tag.
**
** The default behavior is to ignore closed leaves (closeMode==0).  To
** 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 q;         /* 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 */

  db_multi_exec(
    "CREATE TEMP TABLE IF NOT EXISTS leaves("
    "  rid INTEGER PRIMARY KEY"
    ");"
    "DELETE FROM leaves;"
  );
  bag_init(&seen);
  bag_init(&pending);
  if( iBase<=0 ){
    iBase = db_int(0, "SELECT objid FROM event WHERE type='ci'"
                      " ORDER BY mtime LIMIT 1");
  }
  bag_insert(&pending, iBase);
  db_prepare(&q, "SELECT cid FROM plink WHERE pid=:rid");
  db_prepare(&isBr, 
     "SELECT 1 FROM tagxref WHERE rid=:rid AND tagid=%d AND tagtype=1",
     TAG_NEWBRANCH
  );
  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);
      if( bag_insert(&seen, cid) ){
        bag_insert(&pending, cid);
      }
      db_bind_int(&isBr, ":rid", cid);
      if( db_step(&isBr)==SQLITE_DONE ){
        cnt++;
      }
      db_reset(&isBr);
    }
    db_reset(&q);
    if( cnt==0 ){
      db_bind_int(&ins, ":rid", rid);
      db_step(&ins);
      db_reset(&ins);
    }
  }
  db_finalize(&ins);
  db_finalize(&isBr);
  db_finalize(&q);
  bag_clear(&pending);
  bag_clear(&seen);
  if( closeMode==1 ){
    db_multi_exec(
      "DELETE FROM leaves WHERE rid IN"
      "  (SELECT leaves.rid FROM leaves, tagxref"
      "    WHERE tagxref.rid=leaves.rid "
      "      AND tagxref.tagid=%d"
      "      AND tagxref.tagtype>0)",
      TAG_CLOSED
    );
  }else if( closeMode==2 ){
    db_multi_exec(
      "DELETE FROM leaves WHERE rid NOT IN"
      "  (SELECT leaves.rid FROM leaves, tagxref"
      "    WHERE tagxref.rid=leaves.rid "
      "      AND tagxref.tagid=%d"
      "      AND tagxref.tagtype>0)",
      TAG_CLOSED
    );
  }
}

/*
** Load the record ID rid and up to N-1 closest ancestors into
** the "ok" table.
*/
void compute_ancestors(int rid, int N){
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

173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190


191
192
193
194









195
196








197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
  db_must_be_within_tree();
  if( g.argc==2 ){
    base = db_lget_int("checkout", 0);
  }else{
    base = name_to_rid(g.argv[2]);
  }
  if( base==0 ) return;
  compute_leaves(base);
  db_prepare(&q,
    "%s"
    "   AND event.objid IN (SELECT rid FROM leaves)"
    " ORDER BY event.mtime DESC",
    timeline_query_for_tty()
  );
  print_timeline(&q, 20);
  db_finalize(&q);
}

/*
** COMMAND:  leaves
**
** Usage: %fossil leaves
**
** Find leaves of all branches.


*/
void branches_cmd(void){
  Stmt q;



  db_must_be_within_tree();

  db_prepare(&q,
    "%s"
    "   AND blob.rid IN"
    "       (SELECT cid FROM plink EXCEPT SELECT pid FROM plink)"
    " ORDER BY event.mtime DESC",
    timeline_query_for_tty()
  );
  print_timeline(&q, 2000);
  db_finalize(&q);
}

/*
** WEBPAGE:  leaves
**
** Find leaves of all branches.
*/
void leaves_page(void){
  Stmt q;



  login_check_credentials();
  if( !g.okRead ){ login_needed(); return; }










  style_header("Leaves");
  login_anonymous_available();








  db_prepare(&q,
    "%s"
    "   AND blob.rid IN"
    "       (SELECT cid FROM plink EXCEPT SELECT pid FROM plink)"
    " ORDER BY event.mtime DESC",
    timeline_query_for_www()
  );
  www_print_timeline(&q);
  db_finalize(&q);
  @ <script>
  @ function xin(id){
  @ }
  @ function xout(id){
  @ }
  @ </script>
  style_footer();
}







|













|

|
>
>

|

>
>


>


|
<














>
>




>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>
>


|
<













209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245

246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287

288
289
290
291
292
293
294
295
296
297
298
299
300
  db_must_be_within_tree();
  if( g.argc==2 ){
    base = db_lget_int("checkout", 0);
  }else{
    base = name_to_rid(g.argv[2]);
  }
  if( base==0 ) return;
  compute_leaves(base, 0);
  db_prepare(&q,
    "%s"
    "   AND event.objid IN (SELECT rid FROM leaves)"
    " ORDER BY event.mtime DESC",
    timeline_query_for_tty()
  );
  print_timeline(&q, 20);
  db_finalize(&q);
}

/*
** COMMAND:  leaves
**
** Usage: %fossil leaves ?--all? ?--closed?
**
** Find leaves of all branches.  By default show only open leaves.
** The --all flag causes all leaves (closed and open) to be shown.
** The --closed flag shows only closed leaves.
*/
void leaves_cmd(void){
  Stmt q;
  int showAll = find_option("all", 0, 0)!=0;
  int showClosed = find_option("closed", 0, 0)!=0;

  db_must_be_within_tree();
  compute_leaves(0, showAll ? 0 : showClosed ? 2 : 1);
  db_prepare(&q,
    "%s"
    "   AND blob.rid IN leaves"

    " ORDER BY event.mtime DESC",
    timeline_query_for_tty()
  );
  print_timeline(&q, 2000);
  db_finalize(&q);
}

/*
** WEBPAGE:  leaves
**
** Find leaves of all branches.
*/
void leaves_page(void){
  Stmt q;
  int showAll = P("all")!=0;
  int showClosed = P("closed")!=0;

  login_check_credentials();
  if( !g.okRead ){ login_needed(); return; }

  if( !showAll ){
    style_submenu_element("All", "All", "leaves?all");
  }
  if( !showClosed ){
    style_submenu_element("Closed", "Closed", "leaves?closed");
  }
  if( showClosed || showAll ){
    style_submenu_element("Open", "Open", "leaves");
  }
  style_header("Leaves");
  login_anonymous_available();
  compute_leaves(0, showAll ? 0 : showClosed ? 2 : 1);
  if( showAll ){
    @ <h1>All leaves, both open and closed</h1>
  }else if( showClosed ){
    @ <h1>Closed leaves only</h1>
  }else{
    @ <h1>All open leaves</h1>
  }
  db_prepare(&q,
    "%s"
    "   AND blob.rid IN leaves"

    " ORDER BY event.mtime DESC",
    timeline_query_for_www()
  );
  www_print_timeline(&q);
  db_finalize(&q);
  @ <script>
  @ function xin(id){
  @ }
  @ function xout(id){
  @ }
  @ </script>
  style_footer();
}