Fossil SCM

Incomplete implementation of the "fossil grep" command.

drh 2018-06-13 02:02 trunk
Commit c5a98aa0ba0692d1df4e9565cfee8ec584543370ba5e53e82bad57b35646a75f
1 file changed +94 -5
+94 -5
--- src/regexp.c
+++ src/regexp.c
@@ -736,24 +736,56 @@
736736
return sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, 0,
737737
re_sql_func, 0, 0);
738738
}
739739
740740
/*
741
-** Run a "grep" over a single file
741
+** Run a "grep" over a single file read from disk.
742742
*/
743
-static void grep(ReCompiled *pRe, const char *zFile, FILE *in){
743
+static void grep_file(ReCompiled *pRe, const char *zFile, FILE *in){
744744
int ln = 0;
745745
int n;
746746
char zLine[2000];
747747
while( fgets(zLine, sizeof(zLine), in) ){
748748
ln++;
749749
n = (int)strlen(zLine);
750750
while( n && (zLine[n-1]=='\n' || zLine[n-1]=='\r') ) n--;
751751
if( re_match(pRe, (const unsigned char*)zLine, n) ){
752
- printf("%s:%d:%.*s\n", zFile, ln, n, zLine);
752
+ fossil_print("%s:%d:%.*s\n", zFile, ln, n, zLine);
753
+ }
754
+ }
755
+}
756
+
757
+/*
758
+** Flags for grep_buffer()
759
+*/
760
+#define GREP_EXISTS 0x001 /* If any match, print only the name and stop */
761
+
762
+/*
763
+** Run a "grep" over a text file
764
+*/
765
+static int grep_buffer(
766
+ ReCompiled *pRe,
767
+ const char *zName,
768
+ const char *z,
769
+ u32 flags
770
+){
771
+ int i, j, n, ln, cnt;
772
+ for(i=j=ln=cnt=0; z[i]; i=j+1){
773
+ for(j=i; z[j] && z[j]!='\n'; j++){}
774
+ n = j - i;
775
+ if( z[j]=='\n' ) j++;
776
+ ln++;
777
+ if( re_match(pRe, (const unsigned char*)(z+i), j-i) ){
778
+ cnt++;
779
+ if( flags & GREP_EXISTS ){
780
+ fossil_print("%s\n", zName);
781
+ break;
782
+ }
783
+ fossil_print("%s:%d:%.*s\n", zName, ln, n, z+i);
753784
}
754785
}
786
+ return cnt;
755787
}
756788
757789
/*
758790
** COMMAND: test-grep
759791
**
@@ -774,20 +806,77 @@
774806
usage("REGEXP [FILE...]");
775807
}
776808
zErr = re_compile(&pRe, g.argv[2], ignoreCase);
777809
if( zErr ) fossil_fatal("%s", zErr);
778810
if( g.argc==3 ){
779
- grep(pRe, "-", stdin);
811
+ grep_file(pRe, "-", stdin);
780812
}else{
781813
int i;
782814
for(i=3; i<g.argc; i++){
783815
FILE *in = fossil_fopen(g.argv[i], "rb");
784816
if( in==0 ){
785817
fossil_warning("cannot open \"%s\"", g.argv[i]);
786818
}else{
787
- grep(pRe, g.argv[i], in);
819
+ grep_file(pRe, g.argv[i], in);
788820
fclose(in);
789821
}
790822
}
791823
}
792824
re_free(pRe);
793825
}
826
+
827
+/*
828
+** COMMAND: grep
829
+**
830
+** Usage: %fossil grep [OPTIONS] PATTERN FILENAME|CHECKIN
831
+**
832
+** Run grep over all historic version of FILENAME or over all files
833
+** in CHECKIN.
834
+**
835
+** Options:
836
+**
837
+** -i|--ignore-case Ignore case
838
+** -l|--files-with-matches Print only filenames that match
839
+** -v|--verbose Show each file as it is analyzed
840
+*/
841
+void re_grep_cmd(void){
842
+ u32 flags = 0;
843
+ int bVerbose = 0;
844
+ ReCompiled *pRe;
845
+ const char *zErr;
846
+ int ignoreCase = 0;
847
+ Blob fullName;
848
+
849
+ if( find_option("ignore-case","i",0)!=0 ) ignoreCase = 1;
850
+ if( find_option("files-with-matches","l",0)!=0 ) flags |= GREP_EXISTS;
851
+ if( find_option("verbose","v",0)!=0 ) bVerbose = 1;
852
+ db_find_and_open_repository(0, 0);
853
+ verify_all_options();
854
+ if( g.argc<3 ){
855
+ usage("REGEXP FILENAME|CHECKIN");
856
+ }
857
+ zErr = re_compile(&pRe, g.argv[2], ignoreCase);
858
+ if( zErr ) fossil_fatal("%s", zErr);
859
+
860
+ if( file_tree_name(g.argv[3], &fullName, 0, 0) ){
861
+ int fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q",
862
+ blob_str(&fullName));
863
+ Stmt q;
864
+ if( fnid==0 ){
865
+ fossil_fatal("no such file: \"%s\"", blob_str(&fullName));
866
+ }
867
+ add_content_sql_commands(g.db);
868
+ db_prepare(&q,
869
+ "SELECT content(uuid), substr(uuid,1,10)"
870
+ " FROM mlink, blob, event"
871
+ " WHERE mlink.mid=event.objid"
872
+ " AND mlink.fid=blob.rid"
873
+ " AND mlink.fnid=%d"
874
+ " ORDER BY event.mtime DESC",
875
+ fnid
876
+ );
877
+ while( db_step(&q)==SQLITE_ROW ){
878
+ grep_buffer(pRe, db_column_text(&q,1), db_column_text(&q,0), flags);
879
+ }
880
+ db_finalize(&q);
881
+ }
882
+}
794883
--- src/regexp.c
+++ src/regexp.c
@@ -736,24 +736,56 @@
736 return sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, 0,
737 re_sql_func, 0, 0);
738 }
739
740 /*
741 ** Run a "grep" over a single file
742 */
743 static void grep(ReCompiled *pRe, const char *zFile, FILE *in){
744 int ln = 0;
745 int n;
746 char zLine[2000];
747 while( fgets(zLine, sizeof(zLine), in) ){
748 ln++;
749 n = (int)strlen(zLine);
750 while( n && (zLine[n-1]=='\n' || zLine[n-1]=='\r') ) n--;
751 if( re_match(pRe, (const unsigned char*)zLine, n) ){
752 printf("%s:%d:%.*s\n", zFile, ln, n, zLine);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
753 }
754 }
 
755 }
756
757 /*
758 ** COMMAND: test-grep
759 **
@@ -774,20 +806,77 @@
774 usage("REGEXP [FILE...]");
775 }
776 zErr = re_compile(&pRe, g.argv[2], ignoreCase);
777 if( zErr ) fossil_fatal("%s", zErr);
778 if( g.argc==3 ){
779 grep(pRe, "-", stdin);
780 }else{
781 int i;
782 for(i=3; i<g.argc; i++){
783 FILE *in = fossil_fopen(g.argv[i], "rb");
784 if( in==0 ){
785 fossil_warning("cannot open \"%s\"", g.argv[i]);
786 }else{
787 grep(pRe, g.argv[i], in);
788 fclose(in);
789 }
790 }
791 }
792 re_free(pRe);
793 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
794
--- src/regexp.c
+++ src/regexp.c
@@ -736,24 +736,56 @@
736 return sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, 0,
737 re_sql_func, 0, 0);
738 }
739
740 /*
741 ** Run a "grep" over a single file read from disk.
742 */
743 static void grep_file(ReCompiled *pRe, const char *zFile, FILE *in){
744 int ln = 0;
745 int n;
746 char zLine[2000];
747 while( fgets(zLine, sizeof(zLine), in) ){
748 ln++;
749 n = (int)strlen(zLine);
750 while( n && (zLine[n-1]=='\n' || zLine[n-1]=='\r') ) n--;
751 if( re_match(pRe, (const unsigned char*)zLine, n) ){
752 fossil_print("%s:%d:%.*s\n", zFile, ln, n, zLine);
753 }
754 }
755 }
756
757 /*
758 ** Flags for grep_buffer()
759 */
760 #define GREP_EXISTS 0x001 /* If any match, print only the name and stop */
761
762 /*
763 ** Run a "grep" over a text file
764 */
765 static int grep_buffer(
766 ReCompiled *pRe,
767 const char *zName,
768 const char *z,
769 u32 flags
770 ){
771 int i, j, n, ln, cnt;
772 for(i=j=ln=cnt=0; z[i]; i=j+1){
773 for(j=i; z[j] && z[j]!='\n'; j++){}
774 n = j - i;
775 if( z[j]=='\n' ) j++;
776 ln++;
777 if( re_match(pRe, (const unsigned char*)(z+i), j-i) ){
778 cnt++;
779 if( flags & GREP_EXISTS ){
780 fossil_print("%s\n", zName);
781 break;
782 }
783 fossil_print("%s:%d:%.*s\n", zName, ln, n, z+i);
784 }
785 }
786 return cnt;
787 }
788
789 /*
790 ** COMMAND: test-grep
791 **
@@ -774,20 +806,77 @@
806 usage("REGEXP [FILE...]");
807 }
808 zErr = re_compile(&pRe, g.argv[2], ignoreCase);
809 if( zErr ) fossil_fatal("%s", zErr);
810 if( g.argc==3 ){
811 grep_file(pRe, "-", stdin);
812 }else{
813 int i;
814 for(i=3; i<g.argc; i++){
815 FILE *in = fossil_fopen(g.argv[i], "rb");
816 if( in==0 ){
817 fossil_warning("cannot open \"%s\"", g.argv[i]);
818 }else{
819 grep_file(pRe, g.argv[i], in);
820 fclose(in);
821 }
822 }
823 }
824 re_free(pRe);
825 }
826
827 /*
828 ** COMMAND: grep
829 **
830 ** Usage: %fossil grep [OPTIONS] PATTERN FILENAME|CHECKIN
831 **
832 ** Run grep over all historic version of FILENAME or over all files
833 ** in CHECKIN.
834 **
835 ** Options:
836 **
837 ** -i|--ignore-case Ignore case
838 ** -l|--files-with-matches Print only filenames that match
839 ** -v|--verbose Show each file as it is analyzed
840 */
841 void re_grep_cmd(void){
842 u32 flags = 0;
843 int bVerbose = 0;
844 ReCompiled *pRe;
845 const char *zErr;
846 int ignoreCase = 0;
847 Blob fullName;
848
849 if( find_option("ignore-case","i",0)!=0 ) ignoreCase = 1;
850 if( find_option("files-with-matches","l",0)!=0 ) flags |= GREP_EXISTS;
851 if( find_option("verbose","v",0)!=0 ) bVerbose = 1;
852 db_find_and_open_repository(0, 0);
853 verify_all_options();
854 if( g.argc<3 ){
855 usage("REGEXP FILENAME|CHECKIN");
856 }
857 zErr = re_compile(&pRe, g.argv[2], ignoreCase);
858 if( zErr ) fossil_fatal("%s", zErr);
859
860 if( file_tree_name(g.argv[3], &fullName, 0, 0) ){
861 int fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q",
862 blob_str(&fullName));
863 Stmt q;
864 if( fnid==0 ){
865 fossil_fatal("no such file: \"%s\"", blob_str(&fullName));
866 }
867 add_content_sql_commands(g.db);
868 db_prepare(&q,
869 "SELECT content(uuid), substr(uuid,1,10)"
870 " FROM mlink, blob, event"
871 " WHERE mlink.mid=event.objid"
872 " AND mlink.fid=blob.rid"
873 " AND mlink.fnid=%d"
874 " ORDER BY event.mtime DESC",
875 fnid
876 );
877 while( db_step(&q)==SQLITE_ROW ){
878 grep_buffer(pRe, db_column_text(&q,1), db_column_text(&q,0), flags);
879 }
880 db_finalize(&q);
881 }
882 }
883

Keyboard Shortcuts

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