Fossil SCM
Add the -r|--revision option to the annotate command.
Commit
5a6b194bc900eb001d7574dc086cb8d957c80e3f1286d57b2fb7736ce8de3fd5
Parent
02403f0647b16c0…
2 files changed
+52
-19
+1
+52
-19
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -2477,20 +2477,22 @@ | ||
| 2477 | 2477 | /* |
| 2478 | 2478 | ** COMMAND: annotate |
| 2479 | 2479 | ** COMMAND: blame |
| 2480 | 2480 | ** COMMAND: praise |
| 2481 | 2481 | ** |
| 2482 | -** Usage: %fossil (annotate|blame|praise) ?OPTIONS? FILENAME | |
| 2482 | +** Usage: %fossil annotate|blame|praise ?OPTIONS? FILENAME | |
| 2483 | 2483 | ** |
| 2484 | -** Output the text of a file with markings to show when each line of | |
| 2485 | -** the file was last modified. The "annotate" command shows line numbers | |
| 2486 | -** and omits the username. The "blame" and "praise" commands show the user | |
| 2487 | -** who made each check-in and omits the line number. | |
| 2484 | +** Output the text of a file with markings to show when each line of the file | |
| 2485 | +** was last modified. The version currently checked out is shown by default. | |
| 2486 | +** Other versions may be specified using the -r option. The "annotate" command | |
| 2487 | +** shows line numbers and omits the username. The "blame" and "praise" commands | |
| 2488 | +** show the user who made each check-in and omits the line numbers. | |
| 2488 | 2489 | ** |
| 2489 | 2490 | ** Options: |
| 2490 | 2491 | ** --filevers Show file version numbers rather than |
| 2491 | 2492 | ** check-in versions |
| 2493 | +** -r|--revision VERSION The specific check-in containing the file | |
| 2492 | 2494 | ** -l|--log List all versions analyzed |
| 2493 | 2495 | ** -n|--limit N Only look backwards in time by N versions |
| 2494 | 2496 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 2495 | 2497 | ** -Z|--ignore-trailing-space Ignore whitespace at line end |
| 2496 | 2498 | ** |
| @@ -2498,23 +2500,26 @@ | ||
| 2498 | 2500 | */ |
| 2499 | 2501 | void annotate_cmd(void){ |
| 2500 | 2502 | int fnid; /* Filename ID */ |
| 2501 | 2503 | int fid; /* File instance ID */ |
| 2502 | 2504 | int mid; /* Manifest where file was checked in */ |
| 2503 | - int cid; /* Checkout ID */ | |
| 2504 | 2505 | Blob treename; /* FILENAME translated to canonical form */ |
| 2506 | + const char *zRev; /* Revision name, or NULL for current check-in */ | |
| 2505 | 2507 | char *zFilename; /* Canonical filename */ |
| 2506 | 2508 | Annotator ann; /* The annotation of the file */ |
| 2507 | 2509 | int i; /* Loop counter */ |
| 2508 | 2510 | const char *zLimit; /* The value to the -n|--limit option */ |
| 2509 | 2511 | int iLimit; /* How far back in time to look */ |
| 2510 | 2512 | int showLog; /* True to show the log */ |
| 2511 | 2513 | int fileVers; /* Show file version instead of check-in versions */ |
| 2512 | 2514 | u64 annFlags = 0; /* Flags to control annotation properties */ |
| 2513 | 2515 | int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */ |
| 2516 | + Manifest *pManifest; /* Manifest structure */ | |
| 2517 | + ManifestFile *pFile; /* Manifest file pointer */ | |
| 2514 | 2518 | |
| 2515 | 2519 | bBlame = g.argv[1][0]!='a'; |
| 2520 | + zRev = find_option("r","revision",1); | |
| 2516 | 2521 | zLimit = find_option("limit","n",1); |
| 2517 | 2522 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 2518 | 2523 | iLimit = atoi(zLimit); |
| 2519 | 2524 | showLog = find_option("log","l",0)!=0; |
| 2520 | 2525 | if( find_option("ignore-trailing-space","Z",0)!=0 ){ |
| @@ -2530,33 +2535,61 @@ | ||
| 2530 | 2535 | verify_all_options(); |
| 2531 | 2536 | |
| 2532 | 2537 | if( g.argc<3 ) { |
| 2533 | 2538 | usage("FILENAME"); |
| 2534 | 2539 | } |
| 2540 | + | |
| 2541 | + /* Get filename ID */ | |
| 2535 | 2542 | file_tree_name(g.argv[2], &treename, 0, 1); |
| 2536 | 2543 | zFilename = blob_str(&treename); |
| 2537 | 2544 | fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); |
| 2538 | 2545 | if( fnid==0 ){ |
| 2539 | 2546 | fossil_fatal("no such file: %s", zFilename); |
| 2540 | 2547 | } |
| 2541 | - fid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFilename); | |
| 2542 | - if( fid==0 ){ | |
| 2543 | - fossil_fatal("not part of current checkout: %s", zFilename); | |
| 2544 | - } | |
| 2545 | - cid = db_lget_int("checkout", 0); | |
| 2546 | - if( cid == 0 ){ | |
| 2547 | - fossil_fatal("Not in a checkout"); | |
| 2548 | - } | |
| 2549 | - if( iLimit<=0 ) iLimit = 1000000000; | |
| 2550 | - compute_direct_ancestors(cid); | |
| 2548 | + | |
| 2549 | + /* Get artifact IDs of selected check-in and file */ | |
| 2550 | + if( zRev ){ | |
| 2551 | + /* Get artifact ID of selected check-in manifest */ | |
| 2552 | + mid = name_to_typed_rid(zRev, "ci"); | |
| 2553 | + | |
| 2554 | + /* Get manifest structure for selected check-in */ | |
| 2555 | + pManifest = manifest_get(mid, CFTYPE_MANIFEST, 0); | |
| 2556 | + if( !pManifest ){ | |
| 2557 | + fossil_fatal("could not parse manifest for check-in: %s", zRev); | |
| 2558 | + } | |
| 2559 | + | |
| 2560 | + /* Get selected file in manifest */ | |
| 2561 | + pFile = manifest_file_find(pManifest, zFilename); | |
| 2562 | + if( !pFile ){ | |
| 2563 | + fossil_fatal("file %s does not exist in check-in %s", zFilename, zRev); | |
| 2564 | + } | |
| 2565 | + manifest_destroy(pManifest); | |
| 2566 | + | |
| 2567 | + /* Get file instance ID from manifest file record */ | |
| 2568 | + fid = fast_uuid_to_rid(pFile->zUuid); | |
| 2569 | + }else{ | |
| 2570 | + /* Get artifact ID of current checkout manifest */ | |
| 2571 | + mid = db_lget_int("checkout", 0); | |
| 2572 | + if( mid == 0 ){ | |
| 2573 | + fossil_fatal("not in a checkout"); | |
| 2574 | + } | |
| 2575 | + | |
| 2576 | + /* Get file instance ID from current checkout file table */ | |
| 2577 | + fid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFilename); | |
| 2578 | + if( fid==0 ){ | |
| 2579 | + fossil_fatal("not part of current checkout: %s", zFilename); | |
| 2580 | + } | |
| 2581 | + } | |
| 2582 | + | |
| 2583 | + /* Get ID of most recent manifest containing a change to the selected file */ | |
| 2584 | + compute_direct_ancestors(mid); | |
| 2551 | 2585 | mid = db_int(0, "SELECT mlink.mid FROM mlink, ancestor " |
| 2552 | 2586 | " WHERE mlink.fid=%d AND mlink.fnid=%d AND mlink.mid=ancestor.rid" |
| 2553 | 2587 | " ORDER BY ancestor.generation ASC LIMIT 1", |
| 2554 | 2588 | fid, fnid); |
| 2555 | - if( mid==0 ){ | |
| 2556 | - fossil_fatal("unable to find manifest"); | |
| 2557 | - } | |
| 2589 | + | |
| 2590 | + if( iLimit<=0 ) iLimit = 1000000000; | |
| 2558 | 2591 | annFlags |= (ANN_FILE_ANCEST|DIFF_STRIP_EOLCR); |
| 2559 | 2592 | annotate_file(&ann, fnid, mid, iLimit, annFlags); |
| 2560 | 2593 | if( showLog ){ |
| 2561 | 2594 | struct AnnVers *p; |
| 2562 | 2595 | for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){ |
| 2563 | 2596 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -2477,20 +2477,22 @@ | |
| 2477 | /* |
| 2478 | ** COMMAND: annotate |
| 2479 | ** COMMAND: blame |
| 2480 | ** COMMAND: praise |
| 2481 | ** |
| 2482 | ** Usage: %fossil (annotate|blame|praise) ?OPTIONS? FILENAME |
| 2483 | ** |
| 2484 | ** Output the text of a file with markings to show when each line of |
| 2485 | ** the file was last modified. The "annotate" command shows line numbers |
| 2486 | ** and omits the username. The "blame" and "praise" commands show the user |
| 2487 | ** who made each check-in and omits the line number. |
| 2488 | ** |
| 2489 | ** Options: |
| 2490 | ** --filevers Show file version numbers rather than |
| 2491 | ** check-in versions |
| 2492 | ** -l|--log List all versions analyzed |
| 2493 | ** -n|--limit N Only look backwards in time by N versions |
| 2494 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 2495 | ** -Z|--ignore-trailing-space Ignore whitespace at line end |
| 2496 | ** |
| @@ -2498,23 +2500,26 @@ | |
| 2498 | */ |
| 2499 | void annotate_cmd(void){ |
| 2500 | int fnid; /* Filename ID */ |
| 2501 | int fid; /* File instance ID */ |
| 2502 | int mid; /* Manifest where file was checked in */ |
| 2503 | int cid; /* Checkout ID */ |
| 2504 | Blob treename; /* FILENAME translated to canonical form */ |
| 2505 | char *zFilename; /* Canonical filename */ |
| 2506 | Annotator ann; /* The annotation of the file */ |
| 2507 | int i; /* Loop counter */ |
| 2508 | const char *zLimit; /* The value to the -n|--limit option */ |
| 2509 | int iLimit; /* How far back in time to look */ |
| 2510 | int showLog; /* True to show the log */ |
| 2511 | int fileVers; /* Show file version instead of check-in versions */ |
| 2512 | u64 annFlags = 0; /* Flags to control annotation properties */ |
| 2513 | int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */ |
| 2514 | |
| 2515 | bBlame = g.argv[1][0]!='a'; |
| 2516 | zLimit = find_option("limit","n",1); |
| 2517 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 2518 | iLimit = atoi(zLimit); |
| 2519 | showLog = find_option("log","l",0)!=0; |
| 2520 | if( find_option("ignore-trailing-space","Z",0)!=0 ){ |
| @@ -2530,33 +2535,61 @@ | |
| 2530 | verify_all_options(); |
| 2531 | |
| 2532 | if( g.argc<3 ) { |
| 2533 | usage("FILENAME"); |
| 2534 | } |
| 2535 | file_tree_name(g.argv[2], &treename, 0, 1); |
| 2536 | zFilename = blob_str(&treename); |
| 2537 | fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); |
| 2538 | if( fnid==0 ){ |
| 2539 | fossil_fatal("no such file: %s", zFilename); |
| 2540 | } |
| 2541 | fid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFilename); |
| 2542 | if( fid==0 ){ |
| 2543 | fossil_fatal("not part of current checkout: %s", zFilename); |
| 2544 | } |
| 2545 | cid = db_lget_int("checkout", 0); |
| 2546 | if( cid == 0 ){ |
| 2547 | fossil_fatal("Not in a checkout"); |
| 2548 | } |
| 2549 | if( iLimit<=0 ) iLimit = 1000000000; |
| 2550 | compute_direct_ancestors(cid); |
| 2551 | mid = db_int(0, "SELECT mlink.mid FROM mlink, ancestor " |
| 2552 | " WHERE mlink.fid=%d AND mlink.fnid=%d AND mlink.mid=ancestor.rid" |
| 2553 | " ORDER BY ancestor.generation ASC LIMIT 1", |
| 2554 | fid, fnid); |
| 2555 | if( mid==0 ){ |
| 2556 | fossil_fatal("unable to find manifest"); |
| 2557 | } |
| 2558 | annFlags |= (ANN_FILE_ANCEST|DIFF_STRIP_EOLCR); |
| 2559 | annotate_file(&ann, fnid, mid, iLimit, annFlags); |
| 2560 | if( showLog ){ |
| 2561 | struct AnnVers *p; |
| 2562 | for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){ |
| 2563 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -2477,20 +2477,22 @@ | |
| 2477 | /* |
| 2478 | ** COMMAND: annotate |
| 2479 | ** COMMAND: blame |
| 2480 | ** COMMAND: praise |
| 2481 | ** |
| 2482 | ** Usage: %fossil annotate|blame|praise ?OPTIONS? FILENAME |
| 2483 | ** |
| 2484 | ** Output the text of a file with markings to show when each line of the file |
| 2485 | ** was last modified. The version currently checked out is shown by default. |
| 2486 | ** Other versions may be specified using the -r option. The "annotate" command |
| 2487 | ** shows line numbers and omits the username. The "blame" and "praise" commands |
| 2488 | ** show the user who made each check-in and omits the line numbers. |
| 2489 | ** |
| 2490 | ** Options: |
| 2491 | ** --filevers Show file version numbers rather than |
| 2492 | ** check-in versions |
| 2493 | ** -r|--revision VERSION The specific check-in containing the file |
| 2494 | ** -l|--log List all versions analyzed |
| 2495 | ** -n|--limit N Only look backwards in time by N versions |
| 2496 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 2497 | ** -Z|--ignore-trailing-space Ignore whitespace at line end |
| 2498 | ** |
| @@ -2498,23 +2500,26 @@ | |
| 2500 | */ |
| 2501 | void annotate_cmd(void){ |
| 2502 | int fnid; /* Filename ID */ |
| 2503 | int fid; /* File instance ID */ |
| 2504 | int mid; /* Manifest where file was checked in */ |
| 2505 | Blob treename; /* FILENAME translated to canonical form */ |
| 2506 | const char *zRev; /* Revision name, or NULL for current check-in */ |
| 2507 | char *zFilename; /* Canonical filename */ |
| 2508 | Annotator ann; /* The annotation of the file */ |
| 2509 | int i; /* Loop counter */ |
| 2510 | const char *zLimit; /* The value to the -n|--limit option */ |
| 2511 | int iLimit; /* How far back in time to look */ |
| 2512 | int showLog; /* True to show the log */ |
| 2513 | int fileVers; /* Show file version instead of check-in versions */ |
| 2514 | u64 annFlags = 0; /* Flags to control annotation properties */ |
| 2515 | int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */ |
| 2516 | Manifest *pManifest; /* Manifest structure */ |
| 2517 | ManifestFile *pFile; /* Manifest file pointer */ |
| 2518 | |
| 2519 | bBlame = g.argv[1][0]!='a'; |
| 2520 | zRev = find_option("r","revision",1); |
| 2521 | zLimit = find_option("limit","n",1); |
| 2522 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 2523 | iLimit = atoi(zLimit); |
| 2524 | showLog = find_option("log","l",0)!=0; |
| 2525 | if( find_option("ignore-trailing-space","Z",0)!=0 ){ |
| @@ -2530,33 +2535,61 @@ | |
| 2535 | verify_all_options(); |
| 2536 | |
| 2537 | if( g.argc<3 ) { |
| 2538 | usage("FILENAME"); |
| 2539 | } |
| 2540 | |
| 2541 | /* Get filename ID */ |
| 2542 | file_tree_name(g.argv[2], &treename, 0, 1); |
| 2543 | zFilename = blob_str(&treename); |
| 2544 | fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); |
| 2545 | if( fnid==0 ){ |
| 2546 | fossil_fatal("no such file: %s", zFilename); |
| 2547 | } |
| 2548 | |
| 2549 | /* Get artifact IDs of selected check-in and file */ |
| 2550 | if( zRev ){ |
| 2551 | /* Get artifact ID of selected check-in manifest */ |
| 2552 | mid = name_to_typed_rid(zRev, "ci"); |
| 2553 | |
| 2554 | /* Get manifest structure for selected check-in */ |
| 2555 | pManifest = manifest_get(mid, CFTYPE_MANIFEST, 0); |
| 2556 | if( !pManifest ){ |
| 2557 | fossil_fatal("could not parse manifest for check-in: %s", zRev); |
| 2558 | } |
| 2559 | |
| 2560 | /* Get selected file in manifest */ |
| 2561 | pFile = manifest_file_find(pManifest, zFilename); |
| 2562 | if( !pFile ){ |
| 2563 | fossil_fatal("file %s does not exist in check-in %s", zFilename, zRev); |
| 2564 | } |
| 2565 | manifest_destroy(pManifest); |
| 2566 | |
| 2567 | /* Get file instance ID from manifest file record */ |
| 2568 | fid = fast_uuid_to_rid(pFile->zUuid); |
| 2569 | }else{ |
| 2570 | /* Get artifact ID of current checkout manifest */ |
| 2571 | mid = db_lget_int("checkout", 0); |
| 2572 | if( mid == 0 ){ |
| 2573 | fossil_fatal("not in a checkout"); |
| 2574 | } |
| 2575 | |
| 2576 | /* Get file instance ID from current checkout file table */ |
| 2577 | fid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFilename); |
| 2578 | if( fid==0 ){ |
| 2579 | fossil_fatal("not part of current checkout: %s", zFilename); |
| 2580 | } |
| 2581 | } |
| 2582 | |
| 2583 | /* Get ID of most recent manifest containing a change to the selected file */ |
| 2584 | compute_direct_ancestors(mid); |
| 2585 | mid = db_int(0, "SELECT mlink.mid FROM mlink, ancestor " |
| 2586 | " WHERE mlink.fid=%d AND mlink.fnid=%d AND mlink.mid=ancestor.rid" |
| 2587 | " ORDER BY ancestor.generation ASC LIMIT 1", |
| 2588 | fid, fnid); |
| 2589 | |
| 2590 | if( iLimit<=0 ) iLimit = 1000000000; |
| 2591 | annFlags |= (ANN_FILE_ANCEST|DIFF_STRIP_EOLCR); |
| 2592 | annotate_file(&ann, fnid, mid, iLimit, annFlags); |
| 2593 | if( showLog ){ |
| 2594 | struct AnnVers *p; |
| 2595 | for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){ |
| 2596 |
+1
| --- www/changes.wiki | ||
| +++ www/changes.wiki | ||
| @@ -1,10 +1,11 @@ | ||
| 1 | 1 | <title>Change Log</title> |
| 2 | 2 | |
| 3 | 3 | <a name='v2_4'></a> |
| 4 | 4 | <h2>Changes for Version 2.4 (TBD)</h2> |
| 5 | 5 | |
| 6 | + * Add the -r|--revision option to the annotate command. | |
| 6 | 7 | * Support for URL Aliases added. URL Aliases allow an administrator |
| 7 | 8 | to define their own URLs on the web interface that are rewritten to |
| 8 | 9 | built-in URLs with specific parameters. |
| 9 | 10 | * Provide separate on-line help screens for each setting. |
| 10 | 11 | * Back out support for the --no-dir-symlinks option |
| 11 | 12 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,10 +1,11 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <a name='v2_4'></a> |
| 4 | <h2>Changes for Version 2.4 (TBD)</h2> |
| 5 | |
| 6 | * Support for URL Aliases added. URL Aliases allow an administrator |
| 7 | to define their own URLs on the web interface that are rewritten to |
| 8 | built-in URLs with specific parameters. |
| 9 | * Provide separate on-line help screens for each setting. |
| 10 | * Back out support for the --no-dir-symlinks option |
| 11 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,10 +1,11 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <a name='v2_4'></a> |
| 4 | <h2>Changes for Version 2.4 (TBD)</h2> |
| 5 | |
| 6 | * Add the -r|--revision option to the annotate command. |
| 7 | * Support for URL Aliases added. URL Aliases allow an administrator |
| 8 | to define their own URLs on the web interface that are rewritten to |
| 9 | built-in URLs with specific parameters. |
| 10 | * Provide separate on-line help screens for each setting. |
| 11 | * Back out support for the --no-dir-symlinks option |
| 12 |