Fossil SCM

Add the origin= query parameter to /annotate and the --origin option to the annotation command, to enable reverse annotations.

drh 2017-09-25 18:32 trunk
Commit c91b810620ad1a804a963ab4b2ba81348a609552f40445d9754f87669bce7c92
1 file changed +44 -5
+44 -5
--- src/diff.c
+++ src/diff.c
@@ -2200,16 +2200,18 @@
22002200
static void annotate_file(
22012201
Annotator *p, /* The annotator */
22022202
const char *zFilename, /* The name of the file to be annotated */
22032203
const char *zRevision, /* Use the version of the file in this check-in */
22042204
const char *zLimit, /* Limit the number of versions analyzed */
2205
+ const char *zOrigin, /* The origin check-in, or NULL for root-of-tree */
22052206
u64 annFlags /* Flags to alter the annotation */
22062207
){
22072208
Blob toAnnotate; /* Text of the final (mid) version of the file */
22082209
Blob step; /* Text of previous revision */
22092210
Blob treename; /* FILENAME translated to canonical form */
22102211
int cid; /* Selected check-in ID */
2212
+ int origid = 0; /* The origin ID or zero */
22112213
int rid; /* Artifact ID of the file being annotated */
22122214
int fnid; /* Filename ID */
22132215
Stmt q; /* Query returning all ancestor versions */
22142216
int cnt = 0; /* Number of versions analyzed */
22152217
int iLimit; /* Maximum number of versions to analyze */
@@ -2239,14 +2241,39 @@
22392241
cid = name_to_typed_rid(zRevision, "ci");
22402242
}else{
22412243
db_must_be_within_tree();
22422244
cid = db_lget_int("checkout", 0);
22432245
}
2246
+ origid = zOrigin ? name_to_typed_rid(zOrigin, "ci") : 0;
22442247
22452248
/* Compute all direct ancestors of the check-in being analyzed into
22462249
** the "ancestor" table. */
2247
- compute_direct_ancestors(cid);
2250
+ if( origid ){
2251
+ PathNode *p;
2252
+ Blob sql;
2253
+ int gen = 0;
2254
+ char *zSep = "VALUES";
2255
+ p = path_shortest(cid, origid, 1, 0);
2256
+ db_multi_exec(
2257
+ "CREATE TEMP TABLE IF NOT EXISTS ancestor("
2258
+ " rid INT UNIQUE,"
2259
+ " generation INTEGER PRIMARY KEY"
2260
+ ");"
2261
+ "DELETE FROM ancestor;"
2262
+ );
2263
+ blob_init(&sql, "INSERT INTO ancestor(rid, generation)", -1);
2264
+ while( p ){
2265
+ blob_append_sql(&sql, "%s(%d,%d)", zSep/*safe-for-%s*/, p->rid, ++gen);
2266
+ zSep = ",";
2267
+ p = p->u.pTo;
2268
+ }
2269
+ path_reset();
2270
+ db_multi_exec("%s", blob_sql_text(&sql));
2271
+ blob_reset(&sql);
2272
+ }else{
2273
+ compute_direct_ancestors(cid);
2274
+ }
22482275
22492276
/* Get filename ID */
22502277
file_tree_name(zFilename, &treename, 0, 1);
22512278
zFilename = blob_str(&treename);
22522279
fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
@@ -2281,11 +2308,11 @@
22812308
if( !content_get(rid, &toAnnotate) ){
22822309
fossil_fatal("unable to retrieve content of artifact #%d", rid);
22832310
}
22842311
blob_to_utf8_no_bom(&toAnnotate, 0);
22852312
annotation_start(p, &toAnnotate, annFlags);
2286
- p->bMoreToDo = 0;
2313
+ p->bMoreToDo = origid!=0;
22872314
}
22882315
p->aVers = fossil_realloc(p->aVers, (p->nVers+1)*sizeof(p->aVers[0]));
22892316
p->aVers[p->nVers].zFUuid = fossil_strdup(db_column_text(&q, 0));
22902317
p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1));
22912318
p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2));
@@ -2336,18 +2363,22 @@
23362363
** the date of the changes and the check-in hash (with a link to the
23372364
** check-in). /blame and /praise also show the user who made the check-in.
23382365
**
23392366
** Query parameters:
23402367
**
2341
-** checkin=ID The manifest ID at which to start the annotation
2368
+** checkin=ID The check-in at which to start the annotation
23422369
** filename=FILENAME The filename.
23432370
** filevers=BOOLEAN Show file versions rather than check-in versions
23442371
** limit=LIMIT Limit the amount of analysis:
23452372
** "none" No limit
23462373
** "Xs" As much as can be computed in X seconds
23472374
** "N" N versions
23482375
** log=BOOLEAN Show a log of versions analyzed
2376
+** origin=ID The origin checkin. If unspecified, the root
2377
+** check-in over the entire repository is used.
2378
+** Specify "origin=trunk" or similar for a reverse
2379
+** annotation
23492380
** w=BOOLEAN Ignore whitespace
23502381
**
23512382
*/
23522383
void annotation_page(void){
23532384
int i;
@@ -2357,10 +2388,11 @@
23572388
int fileVers; /* Show file version instead of check-in versions */
23582389
int ignoreWs; /* Ignore whitespace */
23592390
const char *zFilename; /* Name of file to annotate */
23602391
const char *zRevision; /* Name of check-in from which to start annotation */
23612392
const char *zCI; /* The check-in containing zFilename */
2393
+ const char *zOrigin; /* The origin of the analysis */
23622394
int szHash; /* Number of characters in %S display */
23632395
char *zLink;
23642396
Annotator ann;
23652397
HQuery url;
23662398
struct AnnVers *p;
@@ -2372,18 +2404,19 @@
23722404
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
23732405
if( exclude_spiders() ) return;
23742406
load_control();
23752407
zFilename = P("filename");
23762408
zRevision = PD("checkin",0);
2409
+ zOrigin = P("origin");
23772410
zLimit = P("limit");
23782411
showLog = PB("log");
23792412
fileVers = PB("filevers");
23802413
ignoreWs = PB("w");
23812414
if( ignoreWs ) annFlags |= DIFF_IGNORE_ALLWS;
23822415
23832416
/* compute the annotation */
2384
- annotate_file(&ann, zFilename, zRevision, zLimit, annFlags);
2417
+ annotate_file(&ann, zFilename, zRevision, zLimit, zOrigin, annFlags);
23852418
zCI = ann.aVers[0].zMUuid;
23862419
23872420
/* generate the web page */
23882421
style_header("Annotation For %h", zFilename);
23892422
if( bBlame ){
@@ -2512,10 +2545,14 @@
25122545
** -l|--log List all versions analyzed
25132546
** -n|--limit LIMIT Limit the amount of analysis:
25142547
** N Up to N versions
25152548
** Xs As much as possible in X seconds
25162549
** none No limit
2550
+** -o|--origin VERSION The origin check-in. By default this is the
2551
+** root of the repository which is normally
2552
+** what you want. Set to "trunk" or similar for
2553
+** a reverse annotation.
25172554
** -w|--ignore-all-space Ignore white space when comparing lines
25182555
** -Z|--ignore-trailing-space Ignore whitespace at line end
25192556
**
25202557
** See also: info, finfo, timeline
25212558
*/
@@ -2522,19 +2559,21 @@
25222559
void annotate_cmd(void){
25232560
const char *zRevision; /* Revision name, or NULL for current check-in */
25242561
Annotator ann; /* The annotation of the file */
25252562
int i; /* Loop counter */
25262563
const char *zLimit; /* The value to the -n|--limit option */
2564
+ const char *zOrig; /* The value for -o|--origin */
25272565
int showLog; /* True to show the log */
25282566
int fileVers; /* Show file version instead of check-in versions */
25292567
u64 annFlags = 0; /* Flags to control annotation properties */
25302568
int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */
25312569
int szHash; /* Display size of a version hash */
25322570
25332571
bBlame = g.argv[1][0]!='a';
25342572
zRevision = find_option("r","revision",1);
25352573
zLimit = find_option("limit","n",1);
2574
+ zOrig = find_option("origin","o",1);
25362575
showLog = find_option("log","l",0)!=0;
25372576
if( find_option("ignore-trailing-space","Z",0)!=0 ){
25382577
annFlags = DIFF_IGNORE_EOLWS;
25392578
}
25402579
if( find_option("ignore-all-space","w",0)!=0 ){
@@ -2549,11 +2588,11 @@
25492588
if( g.argc<3 ) {
25502589
usage("FILENAME");
25512590
}
25522591
25532592
annFlags |= DIFF_STRIP_EOLCR;
2554
- annotate_file(&ann, g.argv[2], zRevision, zLimit, annFlags);
2593
+ annotate_file(&ann, g.argv[2], zRevision, zLimit, zOrig, annFlags);
25552594
if( showLog ){
25562595
struct AnnVers *p;
25572596
for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
25582597
fossil_print("version %3d: %s %S file %S\n",
25592598
i+1, p->zDate, p->zMUuid, p->zFUuid);
25602599
--- src/diff.c
+++ src/diff.c
@@ -2200,16 +2200,18 @@
2200 static void annotate_file(
2201 Annotator *p, /* The annotator */
2202 const char *zFilename, /* The name of the file to be annotated */
2203 const char *zRevision, /* Use the version of the file in this check-in */
2204 const char *zLimit, /* Limit the number of versions analyzed */
 
2205 u64 annFlags /* Flags to alter the annotation */
2206 ){
2207 Blob toAnnotate; /* Text of the final (mid) version of the file */
2208 Blob step; /* Text of previous revision */
2209 Blob treename; /* FILENAME translated to canonical form */
2210 int cid; /* Selected check-in ID */
 
2211 int rid; /* Artifact ID of the file being annotated */
2212 int fnid; /* Filename ID */
2213 Stmt q; /* Query returning all ancestor versions */
2214 int cnt = 0; /* Number of versions analyzed */
2215 int iLimit; /* Maximum number of versions to analyze */
@@ -2239,14 +2241,39 @@
2239 cid = name_to_typed_rid(zRevision, "ci");
2240 }else{
2241 db_must_be_within_tree();
2242 cid = db_lget_int("checkout", 0);
2243 }
 
2244
2245 /* Compute all direct ancestors of the check-in being analyzed into
2246 ** the "ancestor" table. */
2247 compute_direct_ancestors(cid);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2248
2249 /* Get filename ID */
2250 file_tree_name(zFilename, &treename, 0, 1);
2251 zFilename = blob_str(&treename);
2252 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
@@ -2281,11 +2308,11 @@
2281 if( !content_get(rid, &toAnnotate) ){
2282 fossil_fatal("unable to retrieve content of artifact #%d", rid);
2283 }
2284 blob_to_utf8_no_bom(&toAnnotate, 0);
2285 annotation_start(p, &toAnnotate, annFlags);
2286 p->bMoreToDo = 0;
2287 }
2288 p->aVers = fossil_realloc(p->aVers, (p->nVers+1)*sizeof(p->aVers[0]));
2289 p->aVers[p->nVers].zFUuid = fossil_strdup(db_column_text(&q, 0));
2290 p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1));
2291 p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2));
@@ -2336,18 +2363,22 @@
2336 ** the date of the changes and the check-in hash (with a link to the
2337 ** check-in). /blame and /praise also show the user who made the check-in.
2338 **
2339 ** Query parameters:
2340 **
2341 ** checkin=ID The manifest ID at which to start the annotation
2342 ** filename=FILENAME The filename.
2343 ** filevers=BOOLEAN Show file versions rather than check-in versions
2344 ** limit=LIMIT Limit the amount of analysis:
2345 ** "none" No limit
2346 ** "Xs" As much as can be computed in X seconds
2347 ** "N" N versions
2348 ** log=BOOLEAN Show a log of versions analyzed
 
 
 
 
2349 ** w=BOOLEAN Ignore whitespace
2350 **
2351 */
2352 void annotation_page(void){
2353 int i;
@@ -2357,10 +2388,11 @@
2357 int fileVers; /* Show file version instead of check-in versions */
2358 int ignoreWs; /* Ignore whitespace */
2359 const char *zFilename; /* Name of file to annotate */
2360 const char *zRevision; /* Name of check-in from which to start annotation */
2361 const char *zCI; /* The check-in containing zFilename */
 
2362 int szHash; /* Number of characters in %S display */
2363 char *zLink;
2364 Annotator ann;
2365 HQuery url;
2366 struct AnnVers *p;
@@ -2372,18 +2404,19 @@
2372 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2373 if( exclude_spiders() ) return;
2374 load_control();
2375 zFilename = P("filename");
2376 zRevision = PD("checkin",0);
 
2377 zLimit = P("limit");
2378 showLog = PB("log");
2379 fileVers = PB("filevers");
2380 ignoreWs = PB("w");
2381 if( ignoreWs ) annFlags |= DIFF_IGNORE_ALLWS;
2382
2383 /* compute the annotation */
2384 annotate_file(&ann, zFilename, zRevision, zLimit, annFlags);
2385 zCI = ann.aVers[0].zMUuid;
2386
2387 /* generate the web page */
2388 style_header("Annotation For %h", zFilename);
2389 if( bBlame ){
@@ -2512,10 +2545,14 @@
2512 ** -l|--log List all versions analyzed
2513 ** -n|--limit LIMIT Limit the amount of analysis:
2514 ** N Up to N versions
2515 ** Xs As much as possible in X seconds
2516 ** none No limit
 
 
 
 
2517 ** -w|--ignore-all-space Ignore white space when comparing lines
2518 ** -Z|--ignore-trailing-space Ignore whitespace at line end
2519 **
2520 ** See also: info, finfo, timeline
2521 */
@@ -2522,19 +2559,21 @@
2522 void annotate_cmd(void){
2523 const char *zRevision; /* Revision name, or NULL for current check-in */
2524 Annotator ann; /* The annotation of the file */
2525 int i; /* Loop counter */
2526 const char *zLimit; /* The value to the -n|--limit option */
 
2527 int showLog; /* True to show the log */
2528 int fileVers; /* Show file version instead of check-in versions */
2529 u64 annFlags = 0; /* Flags to control annotation properties */
2530 int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */
2531 int szHash; /* Display size of a version hash */
2532
2533 bBlame = g.argv[1][0]!='a';
2534 zRevision = find_option("r","revision",1);
2535 zLimit = find_option("limit","n",1);
 
2536 showLog = find_option("log","l",0)!=0;
2537 if( find_option("ignore-trailing-space","Z",0)!=0 ){
2538 annFlags = DIFF_IGNORE_EOLWS;
2539 }
2540 if( find_option("ignore-all-space","w",0)!=0 ){
@@ -2549,11 +2588,11 @@
2549 if( g.argc<3 ) {
2550 usage("FILENAME");
2551 }
2552
2553 annFlags |= DIFF_STRIP_EOLCR;
2554 annotate_file(&ann, g.argv[2], zRevision, zLimit, annFlags);
2555 if( showLog ){
2556 struct AnnVers *p;
2557 for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
2558 fossil_print("version %3d: %s %S file %S\n",
2559 i+1, p->zDate, p->zMUuid, p->zFUuid);
2560
--- src/diff.c
+++ src/diff.c
@@ -2200,16 +2200,18 @@
2200 static void annotate_file(
2201 Annotator *p, /* The annotator */
2202 const char *zFilename, /* The name of the file to be annotated */
2203 const char *zRevision, /* Use the version of the file in this check-in */
2204 const char *zLimit, /* Limit the number of versions analyzed */
2205 const char *zOrigin, /* The origin check-in, or NULL for root-of-tree */
2206 u64 annFlags /* Flags to alter the annotation */
2207 ){
2208 Blob toAnnotate; /* Text of the final (mid) version of the file */
2209 Blob step; /* Text of previous revision */
2210 Blob treename; /* FILENAME translated to canonical form */
2211 int cid; /* Selected check-in ID */
2212 int origid = 0; /* The origin ID or zero */
2213 int rid; /* Artifact ID of the file being annotated */
2214 int fnid; /* Filename ID */
2215 Stmt q; /* Query returning all ancestor versions */
2216 int cnt = 0; /* Number of versions analyzed */
2217 int iLimit; /* Maximum number of versions to analyze */
@@ -2239,14 +2241,39 @@
2241 cid = name_to_typed_rid(zRevision, "ci");
2242 }else{
2243 db_must_be_within_tree();
2244 cid = db_lget_int("checkout", 0);
2245 }
2246 origid = zOrigin ? name_to_typed_rid(zOrigin, "ci") : 0;
2247
2248 /* Compute all direct ancestors of the check-in being analyzed into
2249 ** the "ancestor" table. */
2250 if( origid ){
2251 PathNode *p;
2252 Blob sql;
2253 int gen = 0;
2254 char *zSep = "VALUES";
2255 p = path_shortest(cid, origid, 1, 0);
2256 db_multi_exec(
2257 "CREATE TEMP TABLE IF NOT EXISTS ancestor("
2258 " rid INT UNIQUE,"
2259 " generation INTEGER PRIMARY KEY"
2260 ");"
2261 "DELETE FROM ancestor;"
2262 );
2263 blob_init(&sql, "INSERT INTO ancestor(rid, generation)", -1);
2264 while( p ){
2265 blob_append_sql(&sql, "%s(%d,%d)", zSep/*safe-for-%s*/, p->rid, ++gen);
2266 zSep = ",";
2267 p = p->u.pTo;
2268 }
2269 path_reset();
2270 db_multi_exec("%s", blob_sql_text(&sql));
2271 blob_reset(&sql);
2272 }else{
2273 compute_direct_ancestors(cid);
2274 }
2275
2276 /* Get filename ID */
2277 file_tree_name(zFilename, &treename, 0, 1);
2278 zFilename = blob_str(&treename);
2279 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
@@ -2281,11 +2308,11 @@
2308 if( !content_get(rid, &toAnnotate) ){
2309 fossil_fatal("unable to retrieve content of artifact #%d", rid);
2310 }
2311 blob_to_utf8_no_bom(&toAnnotate, 0);
2312 annotation_start(p, &toAnnotate, annFlags);
2313 p->bMoreToDo = origid!=0;
2314 }
2315 p->aVers = fossil_realloc(p->aVers, (p->nVers+1)*sizeof(p->aVers[0]));
2316 p->aVers[p->nVers].zFUuid = fossil_strdup(db_column_text(&q, 0));
2317 p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1));
2318 p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2));
@@ -2336,18 +2363,22 @@
2363 ** the date of the changes and the check-in hash (with a link to the
2364 ** check-in). /blame and /praise also show the user who made the check-in.
2365 **
2366 ** Query parameters:
2367 **
2368 ** checkin=ID The check-in at which to start the annotation
2369 ** filename=FILENAME The filename.
2370 ** filevers=BOOLEAN Show file versions rather than check-in versions
2371 ** limit=LIMIT Limit the amount of analysis:
2372 ** "none" No limit
2373 ** "Xs" As much as can be computed in X seconds
2374 ** "N" N versions
2375 ** log=BOOLEAN Show a log of versions analyzed
2376 ** origin=ID The origin checkin. If unspecified, the root
2377 ** check-in over the entire repository is used.
2378 ** Specify "origin=trunk" or similar for a reverse
2379 ** annotation
2380 ** w=BOOLEAN Ignore whitespace
2381 **
2382 */
2383 void annotation_page(void){
2384 int i;
@@ -2357,10 +2388,11 @@
2388 int fileVers; /* Show file version instead of check-in versions */
2389 int ignoreWs; /* Ignore whitespace */
2390 const char *zFilename; /* Name of file to annotate */
2391 const char *zRevision; /* Name of check-in from which to start annotation */
2392 const char *zCI; /* The check-in containing zFilename */
2393 const char *zOrigin; /* The origin of the analysis */
2394 int szHash; /* Number of characters in %S display */
2395 char *zLink;
2396 Annotator ann;
2397 HQuery url;
2398 struct AnnVers *p;
@@ -2372,18 +2404,19 @@
2404 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2405 if( exclude_spiders() ) return;
2406 load_control();
2407 zFilename = P("filename");
2408 zRevision = PD("checkin",0);
2409 zOrigin = P("origin");
2410 zLimit = P("limit");
2411 showLog = PB("log");
2412 fileVers = PB("filevers");
2413 ignoreWs = PB("w");
2414 if( ignoreWs ) annFlags |= DIFF_IGNORE_ALLWS;
2415
2416 /* compute the annotation */
2417 annotate_file(&ann, zFilename, zRevision, zLimit, zOrigin, annFlags);
2418 zCI = ann.aVers[0].zMUuid;
2419
2420 /* generate the web page */
2421 style_header("Annotation For %h", zFilename);
2422 if( bBlame ){
@@ -2512,10 +2545,14 @@
2545 ** -l|--log List all versions analyzed
2546 ** -n|--limit LIMIT Limit the amount of analysis:
2547 ** N Up to N versions
2548 ** Xs As much as possible in X seconds
2549 ** none No limit
2550 ** -o|--origin VERSION The origin check-in. By default this is the
2551 ** root of the repository which is normally
2552 ** what you want. Set to "trunk" or similar for
2553 ** a reverse annotation.
2554 ** -w|--ignore-all-space Ignore white space when comparing lines
2555 ** -Z|--ignore-trailing-space Ignore whitespace at line end
2556 **
2557 ** See also: info, finfo, timeline
2558 */
@@ -2522,19 +2559,21 @@
2559 void annotate_cmd(void){
2560 const char *zRevision; /* Revision name, or NULL for current check-in */
2561 Annotator ann; /* The annotation of the file */
2562 int i; /* Loop counter */
2563 const char *zLimit; /* The value to the -n|--limit option */
2564 const char *zOrig; /* The value for -o|--origin */
2565 int showLog; /* True to show the log */
2566 int fileVers; /* Show file version instead of check-in versions */
2567 u64 annFlags = 0; /* Flags to control annotation properties */
2568 int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */
2569 int szHash; /* Display size of a version hash */
2570
2571 bBlame = g.argv[1][0]!='a';
2572 zRevision = find_option("r","revision",1);
2573 zLimit = find_option("limit","n",1);
2574 zOrig = find_option("origin","o",1);
2575 showLog = find_option("log","l",0)!=0;
2576 if( find_option("ignore-trailing-space","Z",0)!=0 ){
2577 annFlags = DIFF_IGNORE_EOLWS;
2578 }
2579 if( find_option("ignore-all-space","w",0)!=0 ){
@@ -2549,11 +2588,11 @@
2588 if( g.argc<3 ) {
2589 usage("FILENAME");
2590 }
2591
2592 annFlags |= DIFF_STRIP_EOLCR;
2593 annotate_file(&ann, g.argv[2], zRevision, zLimit, zOrig, annFlags);
2594 if( showLog ){
2595 struct AnnVers *p;
2596 for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
2597 fossil_print("version %3d: %s %S file %S\n",
2598 i+1, p->zDate, p->zMUuid, p->zFUuid);
2599

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button