Fossil SCM

Add the --parse option to test-integrity which causes artifacts to be run through the manifest parser.

drh 2013-08-24 16:11 trunk
Commit 2e83d0dea36f7e2dbf72856a77bacbd90a59413b
2 files changed +1 +61 -2
--- src/allrepo.c
+++ src/allrepo.c
@@ -153,10 +153,11 @@
153153
collect_argument(&extra, "stats",0);
154154
}else if( strncmp(zCmd, "sync", n)==0 ){
155155
zCmd = "sync -autourl -R";
156156
collect_argument(&extra, "verbose","v");
157157
}else if( strncmp(zCmd, "test-integrity", n)==0 ){
158
+ collect_argument(&extra, "parse", 0);
158159
zCmd = "test-integrity";
159160
}else if( strncmp(zCmd, "test-orphans", n)==0 ){
160161
zCmd = "test-orphans -R";
161162
}else if( strncmp(zCmd, "test-missing", n)==0 ){
162163
zCmd = "test-missing -q -R";
163164
--- src/allrepo.c
+++ src/allrepo.c
@@ -153,10 +153,11 @@
153 collect_argument(&extra, "stats",0);
154 }else if( strncmp(zCmd, "sync", n)==0 ){
155 zCmd = "sync -autourl -R";
156 collect_argument(&extra, "verbose","v");
157 }else if( strncmp(zCmd, "test-integrity", n)==0 ){
 
158 zCmd = "test-integrity";
159 }else if( strncmp(zCmd, "test-orphans", n)==0 ){
160 zCmd = "test-orphans -R";
161 }else if( strncmp(zCmd, "test-missing", n)==0 ){
162 zCmd = "test-missing -q -R";
163
--- src/allrepo.c
+++ src/allrepo.c
@@ -153,10 +153,11 @@
153 collect_argument(&extra, "stats",0);
154 }else if( strncmp(zCmd, "sync", n)==0 ){
155 zCmd = "sync -autourl -R";
156 collect_argument(&extra, "verbose","v");
157 }else if( strncmp(zCmd, "test-integrity", n)==0 ){
158 collect_argument(&extra, "parse", 0);
159 zCmd = "test-integrity";
160 }else if( strncmp(zCmd, "test-orphans", n)==0 ){
161 zCmd = "test-orphans -R";
162 }else if( strncmp(zCmd, "test-missing", n)==0 ){
163 zCmd = "test-missing -q -R";
164
+61 -2
--- src/content.c
+++ src/content.c
@@ -825,25 +825,47 @@
825825
db_must_be_within_tree();
826826
content_deltify(atoi(g.argv[2]), atoi(g.argv[3]), atoi(g.argv[4]));
827827
}
828828
829829
/*
830
-** COMMAND: test-integrity
830
+** Return true if Blob p looks like it might be a parsable control artifact.
831
+*/
832
+static int looks_like_control_artifact(Blob *p){
833
+ const char *z = blob_buffer(p);
834
+ int n = blob_size(p);
835
+ if( n<10 ) return 0;
836
+ if( strncmp(z, "-----BEGIN PGP SIGNED MESSAGE-----", 34)==0 ) return 1;
837
+ if( z[0]<'A' || z[0]>'Z' || z[1]!=' ' || z[0]=='I' ) return 0;
838
+ if( z[n-1]!='\n' ) return 0;
839
+ return 1;
840
+}
841
+
842
+/*
843
+** COMMAND: test-integrity ?OPTIONS?
831844
**
832845
** Verify that all content can be extracted from the BLOB table correctly.
833846
** If the BLOB table is correct, then the repository can always be
834847
** successfully reconstructed using "fossil rebuild".
848
+**
849
+** Options:
850
+**
851
+** --parse Parse all manifests, wikis, tickets, events, and
852
+** so forth, reporting any errors found.
835853
*/
836854
void test_integrity(void){
837855
Stmt q;
838856
Blob content;
839857
Blob cksum;
840858
int n1 = 0;
841859
int n2 = 0;
842860
int nErr = 0;
843861
int total;
862
+ int nCA = 0;
863
+ int anCA[10];
864
+ int bParse = find_option("parse",0,0)!=0;
844865
db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
866
+ memset(anCA, 0, sizeof(anCA));
845867
846868
/* Make sure no public artifact is a delta from a private artifact */
847869
db_prepare(&q,
848870
"SELECT "
849871
" rid, (SELECT uuid FROM blob WHERE rid=delta.rid),"
@@ -887,17 +909,54 @@
887909
if( fossil_strcmp(blob_str(&cksum), zUuid)!=0 ){
888910
fossil_print("checksum mismatch on artifact %d: wanted %s but got %s\n",
889911
rid, zUuid, blob_str(&cksum));
890912
nErr++;
891913
}
914
+ if( bParse && looks_like_control_artifact(&content) ){
915
+ Blob err;
916
+ int i, n;
917
+ char *z;
918
+ Manifest *p;
919
+ char zFirstLine[400];
920
+ blob_zero(&err);
921
+
922
+ z = blob_buffer(&content);
923
+ n = blob_size(&content);
924
+ for(i=0; i<n && z[i] && z[i]!='\n' && i<sizeof(zFirstLine)-1; i++){}
925
+ memcpy(zFirstLine, z, i);
926
+ zFirstLine[i] = 0;
927
+ p = manifest_parse(&content, 0, &err);
928
+ if( p==0 ){
929
+ fossil_print("manifest_parse failed for %s:\n%s\n",
930
+ blob_str(&cksum), blob_str(&err));
931
+ if( strncmp(blob_str(&err), "line 1:", 7)==0 ){
932
+ fossil_print("\"%s\"\n", zFirstLine);
933
+ }
934
+ }else{
935
+ anCA[p->type]++;
936
+ manifest_destroy(p);
937
+ nCA++;
938
+ }
939
+ blob_reset(&err);
940
+ }else{
941
+ blob_reset(&content);
942
+ }
892943
blob_reset(&cksum);
893
- blob_reset(&content);
894944
n2++;
895945
}
896946
db_finalize(&q);
897947
fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
898948
n2, n1, nErr);
949
+ if( bParse ){
950
+ const char *azType[] = { 0, "manifest", "cluster", "control", "wiki",
951
+ "ticket", "attachment", "event" };
952
+ int i;
953
+ fossil_print("%d total control artifacts\n", nCA);
954
+ for(i=1; i<count(azType); i++){
955
+ if( anCA[i] ) fossil_print(" %d %ss\n", anCA[i], azType[i]);
956
+ }
957
+ }
899958
}
900959
901960
/*
902961
** COMMAND: test-orphans
903962
**
904963
--- src/content.c
+++ src/content.c
@@ -825,25 +825,47 @@
825 db_must_be_within_tree();
826 content_deltify(atoi(g.argv[2]), atoi(g.argv[3]), atoi(g.argv[4]));
827 }
828
829 /*
830 ** COMMAND: test-integrity
 
 
 
 
 
 
 
 
 
 
 
 
 
831 **
832 ** Verify that all content can be extracted from the BLOB table correctly.
833 ** If the BLOB table is correct, then the repository can always be
834 ** successfully reconstructed using "fossil rebuild".
 
 
 
 
 
835 */
836 void test_integrity(void){
837 Stmt q;
838 Blob content;
839 Blob cksum;
840 int n1 = 0;
841 int n2 = 0;
842 int nErr = 0;
843 int total;
 
 
 
844 db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
 
845
846 /* Make sure no public artifact is a delta from a private artifact */
847 db_prepare(&q,
848 "SELECT "
849 " rid, (SELECT uuid FROM blob WHERE rid=delta.rid),"
@@ -887,17 +909,54 @@
887 if( fossil_strcmp(blob_str(&cksum), zUuid)!=0 ){
888 fossil_print("checksum mismatch on artifact %d: wanted %s but got %s\n",
889 rid, zUuid, blob_str(&cksum));
890 nErr++;
891 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
892 blob_reset(&cksum);
893 blob_reset(&content);
894 n2++;
895 }
896 db_finalize(&q);
897 fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
898 n2, n1, nErr);
 
 
 
 
 
 
 
 
 
899 }
900
901 /*
902 ** COMMAND: test-orphans
903 **
904
--- src/content.c
+++ src/content.c
@@ -825,25 +825,47 @@
825 db_must_be_within_tree();
826 content_deltify(atoi(g.argv[2]), atoi(g.argv[3]), atoi(g.argv[4]));
827 }
828
829 /*
830 ** Return true if Blob p looks like it might be a parsable control artifact.
831 */
832 static int looks_like_control_artifact(Blob *p){
833 const char *z = blob_buffer(p);
834 int n = blob_size(p);
835 if( n<10 ) return 0;
836 if( strncmp(z, "-----BEGIN PGP SIGNED MESSAGE-----", 34)==0 ) return 1;
837 if( z[0]<'A' || z[0]>'Z' || z[1]!=' ' || z[0]=='I' ) return 0;
838 if( z[n-1]!='\n' ) return 0;
839 return 1;
840 }
841
842 /*
843 ** COMMAND: test-integrity ?OPTIONS?
844 **
845 ** Verify that all content can be extracted from the BLOB table correctly.
846 ** If the BLOB table is correct, then the repository can always be
847 ** successfully reconstructed using "fossil rebuild".
848 **
849 ** Options:
850 **
851 ** --parse Parse all manifests, wikis, tickets, events, and
852 ** so forth, reporting any errors found.
853 */
854 void test_integrity(void){
855 Stmt q;
856 Blob content;
857 Blob cksum;
858 int n1 = 0;
859 int n2 = 0;
860 int nErr = 0;
861 int total;
862 int nCA = 0;
863 int anCA[10];
864 int bParse = find_option("parse",0,0)!=0;
865 db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
866 memset(anCA, 0, sizeof(anCA));
867
868 /* Make sure no public artifact is a delta from a private artifact */
869 db_prepare(&q,
870 "SELECT "
871 " rid, (SELECT uuid FROM blob WHERE rid=delta.rid),"
@@ -887,17 +909,54 @@
909 if( fossil_strcmp(blob_str(&cksum), zUuid)!=0 ){
910 fossil_print("checksum mismatch on artifact %d: wanted %s but got %s\n",
911 rid, zUuid, blob_str(&cksum));
912 nErr++;
913 }
914 if( bParse && looks_like_control_artifact(&content) ){
915 Blob err;
916 int i, n;
917 char *z;
918 Manifest *p;
919 char zFirstLine[400];
920 blob_zero(&err);
921
922 z = blob_buffer(&content);
923 n = blob_size(&content);
924 for(i=0; i<n && z[i] && z[i]!='\n' && i<sizeof(zFirstLine)-1; i++){}
925 memcpy(zFirstLine, z, i);
926 zFirstLine[i] = 0;
927 p = manifest_parse(&content, 0, &err);
928 if( p==0 ){
929 fossil_print("manifest_parse failed for %s:\n%s\n",
930 blob_str(&cksum), blob_str(&err));
931 if( strncmp(blob_str(&err), "line 1:", 7)==0 ){
932 fossil_print("\"%s\"\n", zFirstLine);
933 }
934 }else{
935 anCA[p->type]++;
936 manifest_destroy(p);
937 nCA++;
938 }
939 blob_reset(&err);
940 }else{
941 blob_reset(&content);
942 }
943 blob_reset(&cksum);
 
944 n2++;
945 }
946 db_finalize(&q);
947 fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
948 n2, n1, nErr);
949 if( bParse ){
950 const char *azType[] = { 0, "manifest", "cluster", "control", "wiki",
951 "ticket", "attachment", "event" };
952 int i;
953 fossil_print("%d total control artifacts\n", nCA);
954 for(i=1; i<count(azType); i++){
955 if( anCA[i] ) fossil_print(" %d %ss\n", anCA[i], azType[i]);
956 }
957 }
958 }
959
960 /*
961 ** COMMAND: test-orphans
962 **
963

Keyboard Shortcuts

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