Fossil SCM
Reducing the leak of annotate even more. I wrote a TODO in the file, for a leak still present and relevant for files modified by many versions, but that requires harder work to get right.
Commit
e2ebb1f5cae83e85a03bf4a32a48bb1303e665e8
Parent
fa760a24cd50191…
1 file changed
+21
-10
+21
-10
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -637,22 +637,23 @@ | ||
| 637 | 637 | int nOrig; /* Number of elements in aOrig[] */ |
| 638 | 638 | int nNoSrc; /* Number of entries where aOrig[].zSrc==NULL */ |
| 639 | 639 | int iLevel; /* Current level */ |
| 640 | 640 | int nVers; /* Number of versions analyzed */ |
| 641 | 641 | char **azVers; /* Names of versions analyzed */ |
| 642 | + Blob toAnnotate; | |
| 642 | 643 | }; |
| 643 | 644 | |
| 644 | 645 | /* |
| 645 | 646 | ** Initialize the annotation process by specifying the file that is |
| 646 | 647 | ** to be annotated. The annotator takes control of the input Blob and |
| 647 | 648 | ** will release it when it is finished with it. |
| 648 | 649 | */ |
| 649 | -static int annotation_start(Annotator *p, Blob *pInput){ | |
| 650 | +static int annotation_start(Annotator *p){ | |
| 650 | 651 | int i; |
| 651 | 652 | |
| 652 | - memset(p, 0, sizeof(*p)); | |
| 653 | - p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo,1); | |
| 653 | + p->c.aTo = break_into_lines(blob_str(&p->toAnnotate), | |
| 654 | + blob_size(&p->toAnnotate),&p->c.nTo,1); | |
| 654 | 655 | if( p->c.aTo==0 ){ |
| 655 | 656 | return 1; |
| 656 | 657 | } |
| 657 | 658 | p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); |
| 658 | 659 | for(i=0; i<p->c.nTo; i++){ |
| @@ -679,10 +680,11 @@ | ||
| 679 | 680 | |
| 680 | 681 | /* Prepare the parent file to be diffed */ |
| 681 | 682 | p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent), |
| 682 | 683 | &p->c.nFrom, 1); |
| 683 | 684 | if( p->c.aFrom==0 ){ |
| 685 | + free(p->c.aFrom); | |
| 684 | 686 | return 1; |
| 685 | 687 | } |
| 686 | 688 | |
| 687 | 689 | /* Compute the differences going from pParent to the file being |
| 688 | 690 | ** annotated. */ |
| @@ -696,10 +698,12 @@ | ||
| 696 | 698 | iThisLevel = p->iLevel; |
| 697 | 699 | for(i=lnTo=0; i<p->c.nEdit; i+=3){ |
| 698 | 700 | struct AnnLine *x = &p->aOrig[lnTo]; |
| 699 | 701 | for(j=0; j<p->c.aEdit[i]; j++, lnTo++, x++){ |
| 700 | 702 | if( x->zSrc==0 || x->iLevel==iPrevLevel ){ |
| 703 | + /* TODO: handle zPName so we can free labels | |
| 704 | + * if they get totally unreferenced in the Annotator */ | |
| 701 | 705 | x->zSrc = zPName; |
| 702 | 706 | x->iLevel = iThisLevel; |
| 703 | 707 | } |
| 704 | 708 | } |
| 705 | 709 | lnTo += p->c.aEdit[i+2]; |
| @@ -722,19 +726,20 @@ | ||
| 722 | 726 | |
| 723 | 727 | /* |
| 724 | 728 | ** COMMAND: test-annotate-step |
| 725 | 729 | */ |
| 726 | 730 | void test_annotate_step_cmd(void){ |
| 727 | - Blob orig, b; | |
| 731 | + Blob b = empty_blob; | |
| 728 | 732 | Annotator x; |
| 729 | 733 | int i; |
| 730 | 734 | |
| 731 | 735 | if( g.argc<4 ) usage("RID1 RID2 ..."); |
| 732 | 736 | db_must_be_within_tree(); |
| 733 | - blob_zero(&b); | |
| 734 | - content_get(name_to_rid(g.argv[2]), &orig); | |
| 735 | - if( annotation_start(&x, &orig) ){ | |
| 737 | + memset(&x, 0, sizeof(x)); | |
| 738 | + x.toAnnotate = empty_blob; | |
| 739 | + content_get(name_to_rid(g.argv[2]), &x.toAnnotate); | |
| 740 | + if( annotation_start(&x) ){ | |
| 736 | 741 | fossil_fatal("binary file"); |
| 737 | 742 | } |
| 738 | 743 | for(i=3; i<g.argc; i++){ |
| 739 | 744 | blob_zero(&b); |
| 740 | 745 | content_get(name_to_rid(g.argv[i]), &b); |
| @@ -763,11 +768,10 @@ | ||
| 763 | 768 | int mid, /* Use the version of the file in this check-in */ |
| 764 | 769 | int webLabel, /* Use web-style annotations if true */ |
| 765 | 770 | int iLimit, /* Limit the number of levels if greater than zero */ |
| 766 | 771 | int annFlags /* Flags to alter the annotation */ |
| 767 | 772 | ){ |
| 768 | - Blob toAnnotate = empty_blob; /* Text of the final (mid) version of the file */ | |
| 769 | 773 | Blob step = empty_blob; /* Text of previous revision */ |
| 770 | 774 | int rid; /* Artifact ID of the file being annotated */ |
| 771 | 775 | char *zLabel; /* Label to apply to a line */ |
| 772 | 776 | Stmt q; /* Query returning all ancestor versions */ |
| 773 | 777 | |
| @@ -774,17 +778,19 @@ | ||
| 774 | 778 | /* Initialize the annotation */ |
| 775 | 779 | rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid); |
| 776 | 780 | if( rid==0 ){ |
| 777 | 781 | fossil_panic("file #%d is unchanged in manifest #%d", fnid, mid); |
| 778 | 782 | } |
| 779 | - if( !content_get(rid, &toAnnotate) ){ | |
| 783 | + memset(p, 0, sizeof(*p)); | |
| 784 | + p->toAnnotate = empty_blob; | |
| 785 | + if( !content_get(rid, &p->toAnnotate) ){ | |
| 780 | 786 | fossil_panic("unable to retrieve content of artifact #%d", rid); |
| 781 | 787 | } |
| 782 | 788 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 783 | 789 | if( iLimit<=0 ) iLimit = 1000000000; |
| 784 | 790 | compute_direct_ancestors(mid, iLimit); |
| 785 | - annotation_start(p, &toAnnotate); | |
| 791 | + annotation_start(p); | |
| 786 | 792 | |
| 787 | 793 | db_prepare(&q, |
| 788 | 794 | "SELECT mlink.fid," |
| 789 | 795 | " (SELECT uuid FROM blob WHERE rid=mlink.%s)," |
| 790 | 796 | " date(event.mtime), " |
| @@ -818,10 +824,11 @@ | ||
| 818 | 824 | content_get(pid, &step); |
| 819 | 825 | annotation_step(p, &step, zLabel); |
| 820 | 826 | blob_reset(&step); |
| 821 | 827 | } |
| 822 | 828 | db_finalize(&q); |
| 829 | + free(p->c.aTo); | |
| 823 | 830 | } |
| 824 | 831 | |
| 825 | 832 | /* |
| 826 | 833 | ** WEBPAGE: annotate |
| 827 | 834 | ** |
| @@ -914,10 +921,11 @@ | ||
| 914 | 921 | } |
| 915 | 922 | fid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFilename); |
| 916 | 923 | if( fid==0 ){ |
| 917 | 924 | fossil_fatal("not part of current checkout: %s", zFilename); |
| 918 | 925 | } |
| 926 | + blob_reset(&treename); | |
| 919 | 927 | mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid); |
| 920 | 928 | if( mid==0 ){ |
| 921 | 929 | fossil_panic("unable to find manifest"); |
| 922 | 930 | } |
| 923 | 931 | if( fileVers ) annFlags |= ANN_FILE_VERS; |
| @@ -930,6 +938,9 @@ | ||
| 930 | 938 | } |
| 931 | 939 | for(i=0; i<ann.nOrig; i++){ |
| 932 | 940 | fossil_print("%s: %.*s\n", |
| 933 | 941 | ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z); |
| 934 | 942 | } |
| 943 | + free(ann.azVers); | |
| 944 | + free(ann.aOrig); | |
| 945 | + blob_reset(&ann.toAnnotate); | |
| 935 | 946 | } |
| 936 | 947 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -637,22 +637,23 @@ | |
| 637 | int nOrig; /* Number of elements in aOrig[] */ |
| 638 | int nNoSrc; /* Number of entries where aOrig[].zSrc==NULL */ |
| 639 | int iLevel; /* Current level */ |
| 640 | int nVers; /* Number of versions analyzed */ |
| 641 | char **azVers; /* Names of versions analyzed */ |
| 642 | }; |
| 643 | |
| 644 | /* |
| 645 | ** Initialize the annotation process by specifying the file that is |
| 646 | ** to be annotated. The annotator takes control of the input Blob and |
| 647 | ** will release it when it is finished with it. |
| 648 | */ |
| 649 | static int annotation_start(Annotator *p, Blob *pInput){ |
| 650 | int i; |
| 651 | |
| 652 | memset(p, 0, sizeof(*p)); |
| 653 | p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo,1); |
| 654 | if( p->c.aTo==0 ){ |
| 655 | return 1; |
| 656 | } |
| 657 | p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); |
| 658 | for(i=0; i<p->c.nTo; i++){ |
| @@ -679,10 +680,11 @@ | |
| 679 | |
| 680 | /* Prepare the parent file to be diffed */ |
| 681 | p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent), |
| 682 | &p->c.nFrom, 1); |
| 683 | if( p->c.aFrom==0 ){ |
| 684 | return 1; |
| 685 | } |
| 686 | |
| 687 | /* Compute the differences going from pParent to the file being |
| 688 | ** annotated. */ |
| @@ -696,10 +698,12 @@ | |
| 696 | iThisLevel = p->iLevel; |
| 697 | for(i=lnTo=0; i<p->c.nEdit; i+=3){ |
| 698 | struct AnnLine *x = &p->aOrig[lnTo]; |
| 699 | for(j=0; j<p->c.aEdit[i]; j++, lnTo++, x++){ |
| 700 | if( x->zSrc==0 || x->iLevel==iPrevLevel ){ |
| 701 | x->zSrc = zPName; |
| 702 | x->iLevel = iThisLevel; |
| 703 | } |
| 704 | } |
| 705 | lnTo += p->c.aEdit[i+2]; |
| @@ -722,19 +726,20 @@ | |
| 722 | |
| 723 | /* |
| 724 | ** COMMAND: test-annotate-step |
| 725 | */ |
| 726 | void test_annotate_step_cmd(void){ |
| 727 | Blob orig, b; |
| 728 | Annotator x; |
| 729 | int i; |
| 730 | |
| 731 | if( g.argc<4 ) usage("RID1 RID2 ..."); |
| 732 | db_must_be_within_tree(); |
| 733 | blob_zero(&b); |
| 734 | content_get(name_to_rid(g.argv[2]), &orig); |
| 735 | if( annotation_start(&x, &orig) ){ |
| 736 | fossil_fatal("binary file"); |
| 737 | } |
| 738 | for(i=3; i<g.argc; i++){ |
| 739 | blob_zero(&b); |
| 740 | content_get(name_to_rid(g.argv[i]), &b); |
| @@ -763,11 +768,10 @@ | |
| 763 | int mid, /* Use the version of the file in this check-in */ |
| 764 | int webLabel, /* Use web-style annotations if true */ |
| 765 | int iLimit, /* Limit the number of levels if greater than zero */ |
| 766 | int annFlags /* Flags to alter the annotation */ |
| 767 | ){ |
| 768 | Blob toAnnotate = empty_blob; /* Text of the final (mid) version of the file */ |
| 769 | Blob step = empty_blob; /* Text of previous revision */ |
| 770 | int rid; /* Artifact ID of the file being annotated */ |
| 771 | char *zLabel; /* Label to apply to a line */ |
| 772 | Stmt q; /* Query returning all ancestor versions */ |
| 773 | |
| @@ -774,17 +778,19 @@ | |
| 774 | /* Initialize the annotation */ |
| 775 | rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid); |
| 776 | if( rid==0 ){ |
| 777 | fossil_panic("file #%d is unchanged in manifest #%d", fnid, mid); |
| 778 | } |
| 779 | if( !content_get(rid, &toAnnotate) ){ |
| 780 | fossil_panic("unable to retrieve content of artifact #%d", rid); |
| 781 | } |
| 782 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 783 | if( iLimit<=0 ) iLimit = 1000000000; |
| 784 | compute_direct_ancestors(mid, iLimit); |
| 785 | annotation_start(p, &toAnnotate); |
| 786 | |
| 787 | db_prepare(&q, |
| 788 | "SELECT mlink.fid," |
| 789 | " (SELECT uuid FROM blob WHERE rid=mlink.%s)," |
| 790 | " date(event.mtime), " |
| @@ -818,10 +824,11 @@ | |
| 818 | content_get(pid, &step); |
| 819 | annotation_step(p, &step, zLabel); |
| 820 | blob_reset(&step); |
| 821 | } |
| 822 | db_finalize(&q); |
| 823 | } |
| 824 | |
| 825 | /* |
| 826 | ** WEBPAGE: annotate |
| 827 | ** |
| @@ -914,10 +921,11 @@ | |
| 914 | } |
| 915 | fid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFilename); |
| 916 | if( fid==0 ){ |
| 917 | fossil_fatal("not part of current checkout: %s", zFilename); |
| 918 | } |
| 919 | mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid); |
| 920 | if( mid==0 ){ |
| 921 | fossil_panic("unable to find manifest"); |
| 922 | } |
| 923 | if( fileVers ) annFlags |= ANN_FILE_VERS; |
| @@ -930,6 +938,9 @@ | |
| 930 | } |
| 931 | for(i=0; i<ann.nOrig; i++){ |
| 932 | fossil_print("%s: %.*s\n", |
| 933 | ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z); |
| 934 | } |
| 935 | } |
| 936 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -637,22 +637,23 @@ | |
| 637 | int nOrig; /* Number of elements in aOrig[] */ |
| 638 | int nNoSrc; /* Number of entries where aOrig[].zSrc==NULL */ |
| 639 | int iLevel; /* Current level */ |
| 640 | int nVers; /* Number of versions analyzed */ |
| 641 | char **azVers; /* Names of versions analyzed */ |
| 642 | Blob toAnnotate; |
| 643 | }; |
| 644 | |
| 645 | /* |
| 646 | ** Initialize the annotation process by specifying the file that is |
| 647 | ** to be annotated. The annotator takes control of the input Blob and |
| 648 | ** will release it when it is finished with it. |
| 649 | */ |
| 650 | static int annotation_start(Annotator *p){ |
| 651 | int i; |
| 652 | |
| 653 | p->c.aTo = break_into_lines(blob_str(&p->toAnnotate), |
| 654 | blob_size(&p->toAnnotate),&p->c.nTo,1); |
| 655 | if( p->c.aTo==0 ){ |
| 656 | return 1; |
| 657 | } |
| 658 | p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); |
| 659 | for(i=0; i<p->c.nTo; i++){ |
| @@ -679,10 +680,11 @@ | |
| 680 | |
| 681 | /* Prepare the parent file to be diffed */ |
| 682 | p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent), |
| 683 | &p->c.nFrom, 1); |
| 684 | if( p->c.aFrom==0 ){ |
| 685 | free(p->c.aFrom); |
| 686 | return 1; |
| 687 | } |
| 688 | |
| 689 | /* Compute the differences going from pParent to the file being |
| 690 | ** annotated. */ |
| @@ -696,10 +698,12 @@ | |
| 698 | iThisLevel = p->iLevel; |
| 699 | for(i=lnTo=0; i<p->c.nEdit; i+=3){ |
| 700 | struct AnnLine *x = &p->aOrig[lnTo]; |
| 701 | for(j=0; j<p->c.aEdit[i]; j++, lnTo++, x++){ |
| 702 | if( x->zSrc==0 || x->iLevel==iPrevLevel ){ |
| 703 | /* TODO: handle zPName so we can free labels |
| 704 | * if they get totally unreferenced in the Annotator */ |
| 705 | x->zSrc = zPName; |
| 706 | x->iLevel = iThisLevel; |
| 707 | } |
| 708 | } |
| 709 | lnTo += p->c.aEdit[i+2]; |
| @@ -722,19 +726,20 @@ | |
| 726 | |
| 727 | /* |
| 728 | ** COMMAND: test-annotate-step |
| 729 | */ |
| 730 | void test_annotate_step_cmd(void){ |
| 731 | Blob b = empty_blob; |
| 732 | Annotator x; |
| 733 | int i; |
| 734 | |
| 735 | if( g.argc<4 ) usage("RID1 RID2 ..."); |
| 736 | db_must_be_within_tree(); |
| 737 | memset(&x, 0, sizeof(x)); |
| 738 | x.toAnnotate = empty_blob; |
| 739 | content_get(name_to_rid(g.argv[2]), &x.toAnnotate); |
| 740 | if( annotation_start(&x) ){ |
| 741 | fossil_fatal("binary file"); |
| 742 | } |
| 743 | for(i=3; i<g.argc; i++){ |
| 744 | blob_zero(&b); |
| 745 | content_get(name_to_rid(g.argv[i]), &b); |
| @@ -763,11 +768,10 @@ | |
| 768 | int mid, /* Use the version of the file in this check-in */ |
| 769 | int webLabel, /* Use web-style annotations if true */ |
| 770 | int iLimit, /* Limit the number of levels if greater than zero */ |
| 771 | int annFlags /* Flags to alter the annotation */ |
| 772 | ){ |
| 773 | Blob step = empty_blob; /* Text of previous revision */ |
| 774 | int rid; /* Artifact ID of the file being annotated */ |
| 775 | char *zLabel; /* Label to apply to a line */ |
| 776 | Stmt q; /* Query returning all ancestor versions */ |
| 777 | |
| @@ -774,17 +778,19 @@ | |
| 778 | /* Initialize the annotation */ |
| 779 | rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid); |
| 780 | if( rid==0 ){ |
| 781 | fossil_panic("file #%d is unchanged in manifest #%d", fnid, mid); |
| 782 | } |
| 783 | memset(p, 0, sizeof(*p)); |
| 784 | p->toAnnotate = empty_blob; |
| 785 | if( !content_get(rid, &p->toAnnotate) ){ |
| 786 | fossil_panic("unable to retrieve content of artifact #%d", rid); |
| 787 | } |
| 788 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 789 | if( iLimit<=0 ) iLimit = 1000000000; |
| 790 | compute_direct_ancestors(mid, iLimit); |
| 791 | annotation_start(p); |
| 792 | |
| 793 | db_prepare(&q, |
| 794 | "SELECT mlink.fid," |
| 795 | " (SELECT uuid FROM blob WHERE rid=mlink.%s)," |
| 796 | " date(event.mtime), " |
| @@ -818,10 +824,11 @@ | |
| 824 | content_get(pid, &step); |
| 825 | annotation_step(p, &step, zLabel); |
| 826 | blob_reset(&step); |
| 827 | } |
| 828 | db_finalize(&q); |
| 829 | free(p->c.aTo); |
| 830 | } |
| 831 | |
| 832 | /* |
| 833 | ** WEBPAGE: annotate |
| 834 | ** |
| @@ -914,10 +921,11 @@ | |
| 921 | } |
| 922 | fid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFilename); |
| 923 | if( fid==0 ){ |
| 924 | fossil_fatal("not part of current checkout: %s", zFilename); |
| 925 | } |
| 926 | blob_reset(&treename); |
| 927 | mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid); |
| 928 | if( mid==0 ){ |
| 929 | fossil_panic("unable to find manifest"); |
| 930 | } |
| 931 | if( fileVers ) annFlags |= ANN_FILE_VERS; |
| @@ -930,6 +938,9 @@ | |
| 938 | } |
| 939 | for(i=0; i<ann.nOrig; i++){ |
| 940 | fossil_print("%s: %.*s\n", |
| 941 | ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z); |
| 942 | } |
| 943 | free(ann.azVers); |
| 944 | free(ann.aOrig); |
| 945 | blob_reset(&ann.toAnnotate); |
| 946 | } |
| 947 |