| ︙ | | | ︙ | |
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
|
** Local variables for this module
*/
static struct {
PathNode *pCurrent; /* Current generation of nodes */
PathNode *pAll; /* All nodes */
Bag seen; /* Nodes seen before */
int nStep; /* Number of steps from first to last */
PathNode *pStart; /* Earliest node */
PathNode *pEnd; /* Most recent */
} path;
/*
** Return the first (last) element of the computed path.
*/
PathNode *path_first(void){ return path.pStart; }
PathNode *path_last(void){ return path.pEnd; }
/*
** Return the number of steps in the computed path.
*/
int path_length(void){ return path.nStep; }
/*
** Create a new node
*/
static PathNode *path_new_node(int rid, PathNode *pFrom, int isParent){
PathNode *p;
p = fossil_malloc( sizeof(*p) );
|
>
>
>
>
>
>
|
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
|
** Local variables for this module
*/
static struct {
PathNode *pCurrent; /* Current generation of nodes */
PathNode *pAll; /* All nodes */
Bag seen; /* Nodes seen before */
int nStep; /* Number of steps from first to last */
int nNotHidden; /* Number of steps not counting hidden nodes */
PathNode *pStart; /* Earliest node */
PathNode *pEnd; /* Most recent */
} path;
/*
** Return the first (last) element of the computed path.
*/
PathNode *path_first(void){ return path.pStart; }
PathNode *path_last(void){ return path.pEnd; }
/*
** Return the number of steps in the computed path.
*/
int path_length(void){ return path.nStep; }
/*
** Return the number of non-hidden steps in the computed path.
*/
int path_length_not_hidden(void){ return path.nNotHidden; }
/*
** Create a new node
*/
static PathNode *path_new_node(int rid, PathNode *pFrom, int isParent){
PathNode *p;
p = fossil_malloc( sizeof(*p) );
|
| ︙ | | | ︙ | |
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
**
** Return NULL if no path is found.
*/
PathNode *path_shortest(
int iFrom, /* Path starts here */
int iTo, /* Path ends here */
int directOnly, /* No merge links if true */
int oneWayOnly /* Parent->child only if true */
){
Stmt s;
PathNode *pPrev;
PathNode *p;
path_reset();
path.pStart = path_new_node(iFrom, 0, 0);
|
|
>
|
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
**
** Return NULL if no path is found.
*/
PathNode *path_shortest(
int iFrom, /* Path starts here */
int iTo, /* Path ends here */
int directOnly, /* No merge links if true */
int oneWayOnly, /* Parent->child only if true */
Bag *pHidden /* Hidden nodes */
){
Stmt s;
PathNode *pPrev;
PathNode *p;
path_reset();
path.pStart = path_new_node(iFrom, 0, 0);
|
| ︙ | | | ︙ | |
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
214
215
216
217
218
219
220
221
222
223
224
225
226
227
|
while( pPrev ){
db_bind_int(&s, ":pid", pPrev->rid);
while( db_step(&s)==SQLITE_ROW ){
int cid = db_column_int(&s, 0);
int isParent = db_column_int(&s, 1);
if( bag_find(&path.seen, cid) ) continue;
p = path_new_node(cid, pPrev, isParent);
if( cid==iTo ){
db_finalize(&s);
path.pEnd = p;
path_reverse_path();
return path.pStart;
}
}
db_reset(&s);
pPrev = pPrev->u.pPeer;
}
}
db_finalize(&s);
path_reset();
return 0;
}
/*
** Find the mid-point of the path. If the path contains fewer than
** 2 steps, return 0.
*/
PathNode *path_midpoint(void){
PathNode *p;
int i;
if( path.nStep<2 ) return 0;
for(p=path.pEnd, i=0; p && i<path.nStep/2; p=p->pFrom, i++){}
return p;
}
/*
** Return an estimate of the number of comparisons remaining in order
** to bisect path. This is based on the log2() of path.nStep.
*/
int path_search_depth(void){
int i, j;
for(i=0, j=1; j<path.nStep; i++, j+=j){}
return i;
}
/*
** Compute the shortest path between two check-ins and then transfer
** that path into the "ancestor" table. This is a utility used by
** both /annotate and /finfo. See also: compute_direct_ancestors().
*/
void path_shortest_stored_in_ancestor_table(
int origid, /* RID for check-in at start of the path */
int cid /* RID for check-in at the end of the path */
){
PathNode *pPath;
int gen = 0;
Stmt ins;
pPath = path_shortest(cid, origid, 1, 0);
db_multi_exec(
"CREATE TEMP TABLE IF NOT EXISTS ancestor("
" rid INT UNIQUE,"
" generation INTEGER PRIMARY KEY"
");"
"DELETE FROM ancestor;"
);
|
>
>
>
>
|
|
>
>
|
|
|
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
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
|
while( pPrev ){
db_bind_int(&s, ":pid", pPrev->rid);
while( db_step(&s)==SQLITE_ROW ){
int cid = db_column_int(&s, 0);
int isParent = db_column_int(&s, 1);
if( bag_find(&path.seen, cid) ) continue;
p = path_new_node(cid, pPrev, isParent);
if( pHidden && bag_find(pHidden,cid) ) p->isHidden = 1;
if( cid==iTo ){
db_finalize(&s);
path.pEnd = p;
path_reverse_path();
for(p=path.pStart->u.pTo; p; p=p->u.pTo ){
if( !p->isHidden ) path.nNotHidden++;
}
return path.pStart;
}
}
db_reset(&s);
pPrev = pPrev->u.pPeer;
}
}
db_finalize(&s);
path_reset();
return 0;
}
/*
** Find the mid-point of the path. If the path contains fewer than
** 2 steps, return 0.
*/
PathNode *path_midpoint(void){
PathNode *p;
int i;
if( path.nNotHidden<2 ) return 0;
for(p=path.pEnd, i=0; p && (p->isHidden || i<path.nNotHidden/2); p=p->pFrom){
if( !p->isHidden ) i++;
}
return p;
}
/*
** Return an estimate of the number of comparisons remaining in order
** to bisect path. This is based on the log2() of path.nStep.
*/
int path_search_depth(void){
int i, j;
for(i=0, j=1; j<path.nNotHidden; i++, j+=j){}
return i;
}
/*
** Compute the shortest path between two check-ins and then transfer
** that path into the "ancestor" table. This is a utility used by
** both /annotate and /finfo. See also: compute_direct_ancestors().
*/
void path_shortest_stored_in_ancestor_table(
int origid, /* RID for check-in at start of the path */
int cid /* RID for check-in at the end of the path */
){
PathNode *pPath;
int gen = 0;
Stmt ins;
pPath = path_shortest(cid, origid, 1, 0, 0);
db_multi_exec(
"CREATE TEMP TABLE IF NOT EXISTS ancestor("
" rid INT UNIQUE,"
" generation INTEGER PRIMARY KEY"
");"
"DELETE FROM ancestor;"
);
|
| ︙ | | | ︙ | |
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
|
db_find_and_open_repository(0,0);
directOnly = find_option("no-merge",0,0)!=0;
oneWay = find_option("one-way",0,0)!=0;
if( g.argc!=4 ) usage("VERSION1 VERSION2");
iFrom = name_to_rid(g.argv[2]);
iTo = name_to_rid(g.argv[3]);
p = path_shortest(iFrom, iTo, directOnly, oneWay);
if( p==0 ){
fossil_fatal("no path from %s to %s", g.argv[1], g.argv[2]);
}
for(n=1, p=path.pStart; p; p=p->u.pTo, n++){
char *z;
z = db_text(0,
"SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
|
|
|
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
|
db_find_and_open_repository(0,0);
directOnly = find_option("no-merge",0,0)!=0;
oneWay = find_option("one-way",0,0)!=0;
if( g.argc!=4 ) usage("VERSION1 VERSION2");
iFrom = name_to_rid(g.argv[2]);
iTo = name_to_rid(g.argv[3]);
p = path_shortest(iFrom, iTo, directOnly, oneWay, 0);
if( p==0 ){
fossil_fatal("no path from %s to %s", g.argv[1], g.argv[2]);
}
for(n=1, p=path.pStart; p; p=p->u.pTo, n++){
char *z;
z = db_text(0,
"SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
|
| ︙ | | | ︙ | |
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
|
if(0==iFrom){
fossil_fatal("Invalid 'from' RID: 0");
}else if(0==iTo){
fossil_fatal("Invalid 'to' RID: 0");
}
if( iFrom==iTo ) return;
path_reset();
p = path_shortest(iFrom, iTo, 1, revOk==0);
if( p==0 ) return;
path_reverse_path();
db_prepare(&q1,
"SELECT pfnid, fnid FROM mlink"
" WHERE mid=:mid AND (pfnid>0 OR fid==0)"
" ORDER BY pfnid"
);
|
|
|
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
|
if(0==iFrom){
fossil_fatal("Invalid 'from' RID: 0");
}else if(0==iTo){
fossil_fatal("Invalid 'to' RID: 0");
}
if( iFrom==iTo ) return;
path_reset();
p = path_shortest(iFrom, iTo, 1, revOk==0, 0);
if( p==0 ) return;
path_reverse_path();
db_prepare(&q1,
"SELECT pfnid, fnid FROM mlink"
" WHERE mid=:mid AND (pfnid>0 OR fid==0)"
" ORDER BY pfnid"
);
|
| ︙ | | | ︙ | |