Fossil SCM

Very very basic svn-dump import. Can not handle anything realistic yet

baruch 2014-10-21 09:22 svn-import
Commit 287cd78e27d00501c0cffd841583199c6b24e027
+1 -1
--- src/checkin.c
+++ src/checkin.c
@@ -1176,11 +1176,11 @@
11761176
}
11771177
}
11781178
db_finalize(&q);
11791179
blob_appendf(pOut, "\n");
11801180
}
1181
- free(zDate);
1181
+ fossil_free(zDate);
11821182
11831183
db_prepare(&q,
11841184
"SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
11851185
" FROM vmerge, blob"
11861186
" WHERE (vmerge.id=-1 OR vmerge.id=-2)"
11871187
--- src/checkin.c
+++ src/checkin.c
@@ -1176,11 +1176,11 @@
1176 }
1177 }
1178 db_finalize(&q);
1179 blob_appendf(pOut, "\n");
1180 }
1181 free(zDate);
1182
1183 db_prepare(&q,
1184 "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
1185 " FROM vmerge, blob"
1186 " WHERE (vmerge.id=-1 OR vmerge.id=-2)"
1187
--- src/checkin.c
+++ src/checkin.c
@@ -1176,11 +1176,11 @@
1176 }
1177 }
1178 db_finalize(&q);
1179 blob_appendf(pOut, "\n");
1180 }
1181 fossil_free(zDate);
1182
1183 db_prepare(&q,
1184 "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
1185 " FROM vmerge, blob"
1186 " WHERE (vmerge.id=-1 OR vmerge.id=-2)"
1187
+330 -1
--- src/import.c
+++ src/import.c
@@ -716,10 +716,328 @@
716716
malformed_line:
717717
trim_newline(zLine);
718718
fossil_fatal("bad fast-import line: [%s]", zLine);
719719
return;
720720
}
721
+
722
+typedef struct {
723
+ const char *zKey;
724
+ const char *zVal;
725
+} KeyVal;
726
+typedef struct {
727
+ KeyVal *aHeaders;
728
+ int nHeaders;
729
+ char *pRawProps;
730
+ KeyVal *aProps;
731
+ int nProps;
732
+ Blob content;
733
+ int nContent;
734
+} SvnRecord;
735
+
736
+#define svn_find_header(rec, zHeader) \
737
+ svn_find_keyval((rec).aHeaders, (rec).nHeaders, (zHeader))
738
+#define svn_find_prop(rec, zProp) \
739
+ svn_find_keyval((rec).aProps, (rec).nProps, (zProp))
740
+static const char *svn_find_keyval(
741
+ KeyVal *aKeyVal,
742
+ int nKeyVal,
743
+ const char *zKey
744
+){
745
+ int i;
746
+ for(i=0; i<nKeyVal; i++){
747
+ if( fossil_strcmp(aKeyVal[i].zKey, zKey)==0 ){
748
+ return aKeyVal[i].zVal;
749
+ }
750
+ }
751
+ return 0;
752
+}
753
+
754
+static void svn_free_rec(SvnRecord *rec){
755
+ int i;
756
+ for(i=0; i<rec->nHeaders; i++){
757
+ fossil_free(rec->aHeaders[i].zKey);
758
+ }
759
+ fossil_free(rec->aHeaders);
760
+ fossil_free(rec->aProps);
761
+ fossil_free(rec->pRawProps);
762
+ blob_reset(&rec->content);
763
+}
764
+
765
+static int svn_read_headers(FILE *pIn, SvnRecord *rec){
766
+ char zLine[1000];
767
+
768
+ rec->aHeaders = 0;
769
+ rec->nHeaders = 0;
770
+ while( fgets(zLine, sizeof(zLine), pIn) ){
771
+ if( zLine[0]!='\n' ) break;
772
+ }
773
+ if( feof(pIn) ) return 0;
774
+ do{
775
+ char *sep;
776
+ if( zLine[0]=='\n' ) break;
777
+ rec->nHeaders += 1;
778
+ rec->aHeaders = fossil_realloc(rec->aHeaders,
779
+ sizeof(rec->aHeaders[0])*rec->nHeaders);
780
+ rec->aHeaders[rec->nHeaders-1].zKey = mprintf("%s", zLine);
781
+ sep = strchr(rec->aHeaders[rec->nHeaders-1].zKey, ':');
782
+ if( !sep ){
783
+ trim_newline(zLine);
784
+ fossil_fatal("bad header line: [%s]", zLine);
785
+ }
786
+ *sep = 0;
787
+ rec->aHeaders[rec->nHeaders-1].zVal = sep+1;
788
+ sep = strchr(rec->aHeaders[rec->nHeaders-1].zVal, '\n');
789
+ *sep = 0;
790
+ while(rec->aHeaders[rec->nHeaders-1].zVal
791
+ && fossil_isspace(*(rec->aHeaders[rec->nHeaders-1].zVal)) )
792
+ {
793
+ rec->aHeaders[rec->nHeaders-1].zVal++;
794
+ }
795
+ }while( fgets(zLine, sizeof(zLine), pIn) );
796
+ if( zLine[0]!='\n' ){
797
+ trim_newline(zLine);
798
+ fossil_fatal("svn-dump data ended unexpectedly");
799
+ }
800
+ return 1;
801
+}
802
+
803
+static void svn_read_props(FILE *pIn, SvnRecord *rec){
804
+ int nRawProps = 0;
805
+ char *pRawProps;
806
+ const char *zLen;
807
+
808
+ rec->pRawProps = 0;
809
+ rec->aProps = 0;
810
+ rec->nProps = 0;
811
+ zLen = svn_find_header(*rec, "Prop-content-length");
812
+ if( zLen ){
813
+ nRawProps = atoi(zLen);
814
+ }
815
+ if( nRawProps ){
816
+ int got;
817
+ char *zLine;
818
+ rec->pRawProps = pRawProps = fossil_malloc( nRawProps );
819
+ got = fread(rec->pRawProps, 1, nRawProps, pIn);
820
+ if( got!=nRawProps ){
821
+ fossil_fatal("short read: got %d of %d bytes", got, nRawProps);
822
+ }
823
+ if( memcmp(&pRawProps[got-10], "PROPS-END\n", 10)!=0 ){
824
+ fossil_fatal("svn-dump data ended unexpectedly");
825
+ }
826
+ zLine = pRawProps;
827
+ while( zLine<(pRawProps+nRawProps-10) ){
828
+ char *eol;
829
+ int propLen;
830
+ if( zLine[0]!='K' ){
831
+ fossil_fatal("svn-dump data format broken");
832
+ }
833
+ propLen = atoi(&zLine[2]);
834
+ eol = strchr(zLine, '\n');
835
+ zLine = eol+1;
836
+ eol = zLine+propLen;
837
+ if( *eol!='\n' ){
838
+ fossil_fatal("svn-dump data format broken");
839
+ }
840
+ *eol = 0;
841
+ rec->nProps += 1;
842
+ rec->aProps = fossil_realloc(rec->aProps,
843
+ sizeof(rec->aProps[0])*rec->nProps);
844
+ rec->aProps[rec->nProps-1].zKey = zLine;
845
+ zLine = eol+1;
846
+ if( zLine[0]!='V' ){
847
+ fossil_fatal("svn-dump data format broken");
848
+ }
849
+ propLen = atoi(&zLine[2]);
850
+ eol = strchr(zLine, '\n');
851
+ zLine = eol+1;
852
+ eol = zLine+propLen;
853
+ if( *eol!='\n' ){
854
+ fossil_fatal("svn-dump data format broken");
855
+ }
856
+ *eol = 0;
857
+ rec->aProps[rec->nProps-1].zVal = zLine;
858
+ zLine = eol+1;
859
+ }
860
+ }
861
+}
862
+
863
+static int svn_read_rec(FILE *pIn, SvnRecord *rec){
864
+ const char *zLen;
865
+ int nLen = 0;
866
+ if( svn_read_headers(pIn, rec)==0 ) return 0;
867
+ svn_read_props(pIn, rec);
868
+ blob_zero(&rec->content);
869
+ zLen = svn_find_header(*rec, "Text-content-length");
870
+ if( zLen ){
871
+ nLen = atoi(zLen);
872
+ }
873
+ if( nLen>=0 ){
874
+ blob_read_from_channel(&rec->content, pIn, nLen);
875
+ if( blob_size(&rec->content)!=nLen ){
876
+ fossil_fatal("short read: got %d of %d bytes",
877
+ blob_size(&rec->content), nLen
878
+ );
879
+ }
880
+ }
881
+ return 1;
882
+}
883
+
884
+static void svn_create_manifests(){
885
+ Blob manifest;
886
+ Stmt qRev;
887
+ Stmt qFiles;
888
+
889
+ blob_zero(&manifest);
890
+ db_prepare(&qRev, "SELECT trev, tuser, tmsg, ttime FROM xrevisions"
891
+ " ORDER BY trev");
892
+ db_prepare(&qFiles, "SELECT tpath, uuid, tperm"
893
+ " FROM xfiles JOIN blob ON xfiles.trid=blob.rid"
894
+ " WHERE trev=:rev ORDER BY tpath");
895
+ while( db_step(&qRev)==SQLITE_ROW ){
896
+ int rev = db_column_int(&qRev, 0);
897
+ const char *zUser = db_column_text(&qRev, 1);
898
+ const char *zMsg = db_column_text(&qRev, 2);
899
+ const char *zTime = db_column_text(&qRev, 3);
900
+ int parentRid = 0;
901
+ Blob mcksum;
902
+ blob_reset(&manifest);
903
+ if( zMsg ){
904
+ blob_appendf(&manifest, "C %F\n", zMsg);
905
+ }else{
906
+ blob_append(&manifest, "C (no\\scomment)\n", 16);
907
+ }
908
+ blob_appendf(&manifest, "D %s\n", zTime);
909
+ db_bind_int(&qFiles, ":rev", rev);
910
+ while( db_step(&qFiles)==SQLITE_ROW ){
911
+ const char *zFile = db_column_text(&qFiles, 0);
912
+ const char *zUuid = db_column_text(&qFiles, 1);
913
+ const char *zPerm = db_column_text(&qFiles, 2);
914
+ blob_appendf(&manifest, "F %F %s %s\n", zFile, zUuid, zPerm);
915
+ }
916
+ db_reset(&qFiles);
917
+ if( parentRid>0 ){
918
+ const char *zParent;
919
+ zParent = db_text(0, "SELECT uuid FROM blob WEHRE rid=%d", parentRid);
920
+ blob_appendf(&manifest, "P %s", zParent);
921
+ fossil_free(zParent);
922
+ }
923
+ if( zUser ){
924
+ blob_appendf(&manifest, "U %F\n", zUser);
925
+ }else{
926
+ const char *zUserOvrd = find_option("user-override",0,1);
927
+ blob_appendf(&manifest, "U %F\n",
928
+ zUserOvrd ? zUserOvrd : login_name());
929
+ }
930
+ md5sum_blob(&manifest, &mcksum);
931
+ blob_appendf(&manifest, "Z %b\n", &mcksum);
932
+ blob_reset(&mcksum);
933
+
934
+ parentRid = content_put(&manifest);
935
+ }
936
+ db_finalize(&qRev);
937
+ db_finalize(&qFiles);
938
+}
939
+/*
940
+** Read the svn-dump format from pIn and insert the corresponding
941
+** content into the database.
942
+*/
943
+static void svn_dump_import(FILE *pIn){
944
+ SvnRecord rec;
945
+ int ver;
946
+ const char *zTemp;
947
+ const char *zUuid;
948
+ Stmt insRev;
949
+ Stmt insFile;
950
+ int rev = 0;
951
+
952
+ /* version */
953
+ if( svn_read_rec(pIn, &rec)
954
+ && (zTemp = svn_find_header(rec, "SVN-fs-dump-format-version")) ){
955
+ ver = atoi(zTemp);
956
+ if( ver!=2 ){
957
+ fossil_fatal("Unknown svn-dump format version: %d", ver);
958
+ }
959
+ }else{
960
+ fossil_fatal("Input is not an svn-dump!");
961
+ }
962
+ svn_free_rec(&rec);
963
+ /* UUID */
964
+ if( !svn_read_rec(pIn, &rec) || !(zUuid = svn_find_header(rec, "UUID")) ){
965
+ fossil_fatal("Missing UUID!");
966
+ }
967
+ svn_free_rec(&rec);
968
+ /* content */
969
+ db_prepare(&insRev,
970
+ "INSERT INTO xrevisions (trev, tuser, tmsg, ttime)"
971
+ "VALUES(:rev, :user, :msg, :time)"
972
+ );
973
+ db_prepare(&insFile,
974
+ "INSERT INTO xfiles (trev, tpath, trid, tperm)"
975
+ "VALUES(:rev, :path, :rid, :perm)"
976
+ );
977
+ while( svn_read_rec(pIn, &rec) ){
978
+ if( zTemp = svn_find_header(rec, "Revision-number") ){
979
+ const char *zUser = svn_find_prop(rec, "svn:author");
980
+ const char *zLog = svn_find_prop(rec, "svn:log");
981
+ const char *zDate = svn_find_prop(rec, "svn:date");
982
+ zDate = date_in_standard_format(zDate);
983
+ rev = atoi(zTemp);
984
+ db_bind_int(&insRev, ":rev", rev);
985
+ db_bind_text(&insRev, ":user", zUser);
986
+ db_bind_text(&insRev, ":msg", zLog);
987
+ db_bind_text(&insRev, ":time", zDate);
988
+ db_step(&insRev);
989
+ db_reset(&insRev);
990
+ fossil_free(zDate);
991
+ }else
992
+ if( zTemp = svn_find_header(rec, "Node-path") ){
993
+ const char *zPath = zTemp;
994
+ const char *zAction = svn_find_header(rec, "Node-action");
995
+ const char *zKind = svn_find_header(rec, "Node-kind");
996
+ const char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path");
997
+ const char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0;
998
+ int srcRev = -1;
999
+ int rid = 0;
1000
+ if( zKind && strncmp(zKind, "dir", 3)==0 ){
1001
+ svn_free_rec(&rec);
1002
+ continue;
1003
+ }
1004
+ zTemp = svn_find_header(rec, "Node-copyfrom-rev");
1005
+ if( zTemp ){
1006
+ srcRev = atoi(zTemp);
1007
+ }
1008
+ rid = content_put(&rec.content);
1009
+ if( strncmp(zAction, "add", 3)==0 ){
1010
+ db_bind_int(&insFile, ":rev", rev);
1011
+ db_bind_int(&insFile, ":rid", rid);
1012
+ db_bind_text(&insFile, ":path", zPath);
1013
+ db_bind_text(&insFile, ":perm", zPerm);
1014
+ db_step(&insFile);
1015
+ db_reset(&insFile);
1016
+ }else
1017
+ if( strncmp(zAction, "change", 6)==0 ){
1018
+ db_bind_int(&insFile, ":rev", rev);
1019
+ db_bind_int(&insFile, ":rid", rid);
1020
+ db_bind_text(&insFile, ":path", zPath);
1021
+ db_bind_text(&insFile, ":perm", zPerm);
1022
+ db_step(&insFile);
1023
+ db_reset(&insFile);
1024
+ }else
1025
+ if( strncmp(zAction, "delete", 6)==0 ){
1026
+ }else
1027
+ if( strncmp(zAction, "replace", 7)==0 ){
1028
+ }else{
1029
+ }
1030
+ }else{
1031
+ fossil_fatal("Unknown record type");
1032
+ }
1033
+ svn_free_rec(&rec);
1034
+ }
1035
+ svn_create_manifests();
1036
+ db_finalize(&insRev);
1037
+ db_finalize(&insFile);
1038
+}
7211039
7221040
/*
7231041
** COMMAND: import
7241042
**
7251043
** Usage: %fossil import FORMAT ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?
@@ -804,11 +1122,22 @@
8041122
db_ephemeral_blob(&q, 0, &record);
8051123
fast_insert_content(&record, 0, 0);
8061124
import_reset(0);
8071125
}
8081126
db_finalize(&q);
809
- }else if( svnFlag ){
1127
+ }else
1128
+ if( svnFlag ){
1129
+ db_multi_exec(
1130
+ "CREATE TEMP TABLE xrevisions("
1131
+ " trev INT, tuser TEXT, tmsg TEXT, ttime DATETIME"
1132
+ ");"
1133
+ "CREATE TEMP TABLE xfiles("
1134
+ " trev INT, tpath TEXT, trid TEXT, tperm TEXT"
1135
+ ");"
1136
+ );
1137
+
1138
+ svn_dump_import(pIn);
8101139
}
8111140
8121141
db_end_transaction(0);
8131142
db_begin_transaction();
8141143
fossil_print("Rebuilding repository meta-data...\n");
8151144
--- src/import.c
+++ src/import.c
@@ -716,10 +716,328 @@
716 malformed_line:
717 trim_newline(zLine);
718 fossil_fatal("bad fast-import line: [%s]", zLine);
719 return;
720 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
721
722 /*
723 ** COMMAND: import
724 **
725 ** Usage: %fossil import FORMAT ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?
@@ -804,11 +1122,22 @@
804 db_ephemeral_blob(&q, 0, &record);
805 fast_insert_content(&record, 0, 0);
806 import_reset(0);
807 }
808 db_finalize(&q);
809 }else if( svnFlag ){
 
 
 
 
 
 
 
 
 
 
 
810 }
811
812 db_end_transaction(0);
813 db_begin_transaction();
814 fossil_print("Rebuilding repository meta-data...\n");
815
--- src/import.c
+++ src/import.c
@@ -716,10 +716,328 @@
716 malformed_line:
717 trim_newline(zLine);
718 fossil_fatal("bad fast-import line: [%s]", zLine);
719 return;
720 }
721
722 typedef struct {
723 const char *zKey;
724 const char *zVal;
725 } KeyVal;
726 typedef struct {
727 KeyVal *aHeaders;
728 int nHeaders;
729 char *pRawProps;
730 KeyVal *aProps;
731 int nProps;
732 Blob content;
733 int nContent;
734 } SvnRecord;
735
736 #define svn_find_header(rec, zHeader) \
737 svn_find_keyval((rec).aHeaders, (rec).nHeaders, (zHeader))
738 #define svn_find_prop(rec, zProp) \
739 svn_find_keyval((rec).aProps, (rec).nProps, (zProp))
740 static const char *svn_find_keyval(
741 KeyVal *aKeyVal,
742 int nKeyVal,
743 const char *zKey
744 ){
745 int i;
746 for(i=0; i<nKeyVal; i++){
747 if( fossil_strcmp(aKeyVal[i].zKey, zKey)==0 ){
748 return aKeyVal[i].zVal;
749 }
750 }
751 return 0;
752 }
753
754 static void svn_free_rec(SvnRecord *rec){
755 int i;
756 for(i=0; i<rec->nHeaders; i++){
757 fossil_free(rec->aHeaders[i].zKey);
758 }
759 fossil_free(rec->aHeaders);
760 fossil_free(rec->aProps);
761 fossil_free(rec->pRawProps);
762 blob_reset(&rec->content);
763 }
764
765 static int svn_read_headers(FILE *pIn, SvnRecord *rec){
766 char zLine[1000];
767
768 rec->aHeaders = 0;
769 rec->nHeaders = 0;
770 while( fgets(zLine, sizeof(zLine), pIn) ){
771 if( zLine[0]!='\n' ) break;
772 }
773 if( feof(pIn) ) return 0;
774 do{
775 char *sep;
776 if( zLine[0]=='\n' ) break;
777 rec->nHeaders += 1;
778 rec->aHeaders = fossil_realloc(rec->aHeaders,
779 sizeof(rec->aHeaders[0])*rec->nHeaders);
780 rec->aHeaders[rec->nHeaders-1].zKey = mprintf("%s", zLine);
781 sep = strchr(rec->aHeaders[rec->nHeaders-1].zKey, ':');
782 if( !sep ){
783 trim_newline(zLine);
784 fossil_fatal("bad header line: [%s]", zLine);
785 }
786 *sep = 0;
787 rec->aHeaders[rec->nHeaders-1].zVal = sep+1;
788 sep = strchr(rec->aHeaders[rec->nHeaders-1].zVal, '\n');
789 *sep = 0;
790 while(rec->aHeaders[rec->nHeaders-1].zVal
791 && fossil_isspace(*(rec->aHeaders[rec->nHeaders-1].zVal)) )
792 {
793 rec->aHeaders[rec->nHeaders-1].zVal++;
794 }
795 }while( fgets(zLine, sizeof(zLine), pIn) );
796 if( zLine[0]!='\n' ){
797 trim_newline(zLine);
798 fossil_fatal("svn-dump data ended unexpectedly");
799 }
800 return 1;
801 }
802
803 static void svn_read_props(FILE *pIn, SvnRecord *rec){
804 int nRawProps = 0;
805 char *pRawProps;
806 const char *zLen;
807
808 rec->pRawProps = 0;
809 rec->aProps = 0;
810 rec->nProps = 0;
811 zLen = svn_find_header(*rec, "Prop-content-length");
812 if( zLen ){
813 nRawProps = atoi(zLen);
814 }
815 if( nRawProps ){
816 int got;
817 char *zLine;
818 rec->pRawProps = pRawProps = fossil_malloc( nRawProps );
819 got = fread(rec->pRawProps, 1, nRawProps, pIn);
820 if( got!=nRawProps ){
821 fossil_fatal("short read: got %d of %d bytes", got, nRawProps);
822 }
823 if( memcmp(&pRawProps[got-10], "PROPS-END\n", 10)!=0 ){
824 fossil_fatal("svn-dump data ended unexpectedly");
825 }
826 zLine = pRawProps;
827 while( zLine<(pRawProps+nRawProps-10) ){
828 char *eol;
829 int propLen;
830 if( zLine[0]!='K' ){
831 fossil_fatal("svn-dump data format broken");
832 }
833 propLen = atoi(&zLine[2]);
834 eol = strchr(zLine, '\n');
835 zLine = eol+1;
836 eol = zLine+propLen;
837 if( *eol!='\n' ){
838 fossil_fatal("svn-dump data format broken");
839 }
840 *eol = 0;
841 rec->nProps += 1;
842 rec->aProps = fossil_realloc(rec->aProps,
843 sizeof(rec->aProps[0])*rec->nProps);
844 rec->aProps[rec->nProps-1].zKey = zLine;
845 zLine = eol+1;
846 if( zLine[0]!='V' ){
847 fossil_fatal("svn-dump data format broken");
848 }
849 propLen = atoi(&zLine[2]);
850 eol = strchr(zLine, '\n');
851 zLine = eol+1;
852 eol = zLine+propLen;
853 if( *eol!='\n' ){
854 fossil_fatal("svn-dump data format broken");
855 }
856 *eol = 0;
857 rec->aProps[rec->nProps-1].zVal = zLine;
858 zLine = eol+1;
859 }
860 }
861 }
862
863 static int svn_read_rec(FILE *pIn, SvnRecord *rec){
864 const char *zLen;
865 int nLen = 0;
866 if( svn_read_headers(pIn, rec)==0 ) return 0;
867 svn_read_props(pIn, rec);
868 blob_zero(&rec->content);
869 zLen = svn_find_header(*rec, "Text-content-length");
870 if( zLen ){
871 nLen = atoi(zLen);
872 }
873 if( nLen>=0 ){
874 blob_read_from_channel(&rec->content, pIn, nLen);
875 if( blob_size(&rec->content)!=nLen ){
876 fossil_fatal("short read: got %d of %d bytes",
877 blob_size(&rec->content), nLen
878 );
879 }
880 }
881 return 1;
882 }
883
884 static void svn_create_manifests(){
885 Blob manifest;
886 Stmt qRev;
887 Stmt qFiles;
888
889 blob_zero(&manifest);
890 db_prepare(&qRev, "SELECT trev, tuser, tmsg, ttime FROM xrevisions"
891 " ORDER BY trev");
892 db_prepare(&qFiles, "SELECT tpath, uuid, tperm"
893 " FROM xfiles JOIN blob ON xfiles.trid=blob.rid"
894 " WHERE trev=:rev ORDER BY tpath");
895 while( db_step(&qRev)==SQLITE_ROW ){
896 int rev = db_column_int(&qRev, 0);
897 const char *zUser = db_column_text(&qRev, 1);
898 const char *zMsg = db_column_text(&qRev, 2);
899 const char *zTime = db_column_text(&qRev, 3);
900 int parentRid = 0;
901 Blob mcksum;
902 blob_reset(&manifest);
903 if( zMsg ){
904 blob_appendf(&manifest, "C %F\n", zMsg);
905 }else{
906 blob_append(&manifest, "C (no\\scomment)\n", 16);
907 }
908 blob_appendf(&manifest, "D %s\n", zTime);
909 db_bind_int(&qFiles, ":rev", rev);
910 while( db_step(&qFiles)==SQLITE_ROW ){
911 const char *zFile = db_column_text(&qFiles, 0);
912 const char *zUuid = db_column_text(&qFiles, 1);
913 const char *zPerm = db_column_text(&qFiles, 2);
914 blob_appendf(&manifest, "F %F %s %s\n", zFile, zUuid, zPerm);
915 }
916 db_reset(&qFiles);
917 if( parentRid>0 ){
918 const char *zParent;
919 zParent = db_text(0, "SELECT uuid FROM blob WEHRE rid=%d", parentRid);
920 blob_appendf(&manifest, "P %s", zParent);
921 fossil_free(zParent);
922 }
923 if( zUser ){
924 blob_appendf(&manifest, "U %F\n", zUser);
925 }else{
926 const char *zUserOvrd = find_option("user-override",0,1);
927 blob_appendf(&manifest, "U %F\n",
928 zUserOvrd ? zUserOvrd : login_name());
929 }
930 md5sum_blob(&manifest, &mcksum);
931 blob_appendf(&manifest, "Z %b\n", &mcksum);
932 blob_reset(&mcksum);
933
934 parentRid = content_put(&manifest);
935 }
936 db_finalize(&qRev);
937 db_finalize(&qFiles);
938 }
939 /*
940 ** Read the svn-dump format from pIn and insert the corresponding
941 ** content into the database.
942 */
943 static void svn_dump_import(FILE *pIn){
944 SvnRecord rec;
945 int ver;
946 const char *zTemp;
947 const char *zUuid;
948 Stmt insRev;
949 Stmt insFile;
950 int rev = 0;
951
952 /* version */
953 if( svn_read_rec(pIn, &rec)
954 && (zTemp = svn_find_header(rec, "SVN-fs-dump-format-version")) ){
955 ver = atoi(zTemp);
956 if( ver!=2 ){
957 fossil_fatal("Unknown svn-dump format version: %d", ver);
958 }
959 }else{
960 fossil_fatal("Input is not an svn-dump!");
961 }
962 svn_free_rec(&rec);
963 /* UUID */
964 if( !svn_read_rec(pIn, &rec) || !(zUuid = svn_find_header(rec, "UUID")) ){
965 fossil_fatal("Missing UUID!");
966 }
967 svn_free_rec(&rec);
968 /* content */
969 db_prepare(&insRev,
970 "INSERT INTO xrevisions (trev, tuser, tmsg, ttime)"
971 "VALUES(:rev, :user, :msg, :time)"
972 );
973 db_prepare(&insFile,
974 "INSERT INTO xfiles (trev, tpath, trid, tperm)"
975 "VALUES(:rev, :path, :rid, :perm)"
976 );
977 while( svn_read_rec(pIn, &rec) ){
978 if( zTemp = svn_find_header(rec, "Revision-number") ){
979 const char *zUser = svn_find_prop(rec, "svn:author");
980 const char *zLog = svn_find_prop(rec, "svn:log");
981 const char *zDate = svn_find_prop(rec, "svn:date");
982 zDate = date_in_standard_format(zDate);
983 rev = atoi(zTemp);
984 db_bind_int(&insRev, ":rev", rev);
985 db_bind_text(&insRev, ":user", zUser);
986 db_bind_text(&insRev, ":msg", zLog);
987 db_bind_text(&insRev, ":time", zDate);
988 db_step(&insRev);
989 db_reset(&insRev);
990 fossil_free(zDate);
991 }else
992 if( zTemp = svn_find_header(rec, "Node-path") ){
993 const char *zPath = zTemp;
994 const char *zAction = svn_find_header(rec, "Node-action");
995 const char *zKind = svn_find_header(rec, "Node-kind");
996 const char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path");
997 const char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0;
998 int srcRev = -1;
999 int rid = 0;
1000 if( zKind && strncmp(zKind, "dir", 3)==0 ){
1001 svn_free_rec(&rec);
1002 continue;
1003 }
1004 zTemp = svn_find_header(rec, "Node-copyfrom-rev");
1005 if( zTemp ){
1006 srcRev = atoi(zTemp);
1007 }
1008 rid = content_put(&rec.content);
1009 if( strncmp(zAction, "add", 3)==0 ){
1010 db_bind_int(&insFile, ":rev", rev);
1011 db_bind_int(&insFile, ":rid", rid);
1012 db_bind_text(&insFile, ":path", zPath);
1013 db_bind_text(&insFile, ":perm", zPerm);
1014 db_step(&insFile);
1015 db_reset(&insFile);
1016 }else
1017 if( strncmp(zAction, "change", 6)==0 ){
1018 db_bind_int(&insFile, ":rev", rev);
1019 db_bind_int(&insFile, ":rid", rid);
1020 db_bind_text(&insFile, ":path", zPath);
1021 db_bind_text(&insFile, ":perm", zPerm);
1022 db_step(&insFile);
1023 db_reset(&insFile);
1024 }else
1025 if( strncmp(zAction, "delete", 6)==0 ){
1026 }else
1027 if( strncmp(zAction, "replace", 7)==0 ){
1028 }else{
1029 }
1030 }else{
1031 fossil_fatal("Unknown record type");
1032 }
1033 svn_free_rec(&rec);
1034 }
1035 svn_create_manifests();
1036 db_finalize(&insRev);
1037 db_finalize(&insFile);
1038 }
1039
1040 /*
1041 ** COMMAND: import
1042 **
1043 ** Usage: %fossil import FORMAT ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?
@@ -804,11 +1122,22 @@
1122 db_ephemeral_blob(&q, 0, &record);
1123 fast_insert_content(&record, 0, 0);
1124 import_reset(0);
1125 }
1126 db_finalize(&q);
1127 }else
1128 if( svnFlag ){
1129 db_multi_exec(
1130 "CREATE TEMP TABLE xrevisions("
1131 " trev INT, tuser TEXT, tmsg TEXT, ttime DATETIME"
1132 ");"
1133 "CREATE TEMP TABLE xfiles("
1134 " trev INT, tpath TEXT, trid TEXT, tperm TEXT"
1135 ");"
1136 );
1137
1138 svn_dump_import(pIn);
1139 }
1140
1141 db_end_transaction(0);
1142 db_begin_transaction();
1143 fossil_print("Rebuilding repository meta-data...\n");
1144
+5 -5
--- src/schema.c
+++ src/schema.c
@@ -125,11 +125,11 @@
125125
@ info TEXT, -- contact information
126126
@ mtime DATE, -- last change. seconds since 1970
127127
@ photo BLOB -- JPEG image of this user
128128
@ );
129129
@
130
-@ -- The VAR table holds miscellanous information about the repository.
130
+@ -- The config table holds miscellanous information about the repository.
131131
@ -- in the form of name-value pairs.
132132
@ --
133133
@ CREATE TABLE config(
134134
@ name TEXT PRIMARY KEY NOT NULL, -- Primary name of the entry
135135
@ value CLOB, -- Content of the named parameter
@@ -447,12 +447,12 @@
447447
#if EXPORT_INTERFACE
448448
# define MAX_INT_TAG 16 /* The largest pre-assigned tag id */
449449
#endif
450450
451451
/*
452
-** The schema for the locate FOSSIL database file found at the root
453
-** of very check-out. This database contains the complete state of
452
+** The schema for the local FOSSIL database file found at the root
453
+** of every check-out. This database contains the complete state of
454454
** the checkout.
455455
*/
456456
const char zLocalSchema[] =
457457
@ -- The VVAR table holds miscellanous information about the local database
458458
@ -- in the form of name-value pairs. This is similar to the VAR table
@@ -479,12 +479,12 @@
479479
@ -- Vfile.chnged is 0 for unmodified files, 1 for files that have
480480
@ -- been edited or which have been subjected to a 3-way merge.
481481
@ -- Vfile.chnged is 2 if the file has been replaced from a different
482482
@ -- version by the merge and 3 if the file has been added by a merge.
483483
@ -- Vfile.chnged is 4|5 is the same as 2|3, but the operation has been
484
-@ -- done by an --integrate merge. The difference between vfile.chnged==2|4
485
-@ -- and a regular add is that with vfile.chnged==2|4 we know that the
484
+@ -- done by an --integrate merge. The difference between vfile.chnged==3|5
485
+@ -- and a regular add is that with vfile.chnged==3|5 we know that the
486486
@ -- current version of the file is already in the repository.
487487
@ --
488488
@ CREATE TABLE vfile(
489489
@ id INTEGER PRIMARY KEY, -- ID of the checked out file
490490
@ vid INTEGER REFERENCES blob, -- The baseline this file is part of.
491491
--- src/schema.c
+++ src/schema.c
@@ -125,11 +125,11 @@
125 @ info TEXT, -- contact information
126 @ mtime DATE, -- last change. seconds since 1970
127 @ photo BLOB -- JPEG image of this user
128 @ );
129 @
130 @ -- The VAR table holds miscellanous information about the repository.
131 @ -- in the form of name-value pairs.
132 @ --
133 @ CREATE TABLE config(
134 @ name TEXT PRIMARY KEY NOT NULL, -- Primary name of the entry
135 @ value CLOB, -- Content of the named parameter
@@ -447,12 +447,12 @@
447 #if EXPORT_INTERFACE
448 # define MAX_INT_TAG 16 /* The largest pre-assigned tag id */
449 #endif
450
451 /*
452 ** The schema for the locate FOSSIL database file found at the root
453 ** of very check-out. This database contains the complete state of
454 ** the checkout.
455 */
456 const char zLocalSchema[] =
457 @ -- The VVAR table holds miscellanous information about the local database
458 @ -- in the form of name-value pairs. This is similar to the VAR table
@@ -479,12 +479,12 @@
479 @ -- Vfile.chnged is 0 for unmodified files, 1 for files that have
480 @ -- been edited or which have been subjected to a 3-way merge.
481 @ -- Vfile.chnged is 2 if the file has been replaced from a different
482 @ -- version by the merge and 3 if the file has been added by a merge.
483 @ -- Vfile.chnged is 4|5 is the same as 2|3, but the operation has been
484 @ -- done by an --integrate merge. The difference between vfile.chnged==2|4
485 @ -- and a regular add is that with vfile.chnged==2|4 we know that the
486 @ -- current version of the file is already in the repository.
487 @ --
488 @ CREATE TABLE vfile(
489 @ id INTEGER PRIMARY KEY, -- ID of the checked out file
490 @ vid INTEGER REFERENCES blob, -- The baseline this file is part of.
491
--- src/schema.c
+++ src/schema.c
@@ -125,11 +125,11 @@
125 @ info TEXT, -- contact information
126 @ mtime DATE, -- last change. seconds since 1970
127 @ photo BLOB -- JPEG image of this user
128 @ );
129 @
130 @ -- The config table holds miscellanous information about the repository.
131 @ -- in the form of name-value pairs.
132 @ --
133 @ CREATE TABLE config(
134 @ name TEXT PRIMARY KEY NOT NULL, -- Primary name of the entry
135 @ value CLOB, -- Content of the named parameter
@@ -447,12 +447,12 @@
447 #if EXPORT_INTERFACE
448 # define MAX_INT_TAG 16 /* The largest pre-assigned tag id */
449 #endif
450
451 /*
452 ** The schema for the local FOSSIL database file found at the root
453 ** of every check-out. This database contains the complete state of
454 ** the checkout.
455 */
456 const char zLocalSchema[] =
457 @ -- The VVAR table holds miscellanous information about the local database
458 @ -- in the form of name-value pairs. This is similar to the VAR table
@@ -479,12 +479,12 @@
479 @ -- Vfile.chnged is 0 for unmodified files, 1 for files that have
480 @ -- been edited or which have been subjected to a 3-way merge.
481 @ -- Vfile.chnged is 2 if the file has been replaced from a different
482 @ -- version by the merge and 3 if the file has been added by a merge.
483 @ -- Vfile.chnged is 4|5 is the same as 2|3, but the operation has been
484 @ -- done by an --integrate merge. The difference between vfile.chnged==3|5
485 @ -- and a regular add is that with vfile.chnged==3|5 we know that the
486 @ -- current version of the file is already in the repository.
487 @ --
488 @ CREATE TABLE vfile(
489 @ id INTEGER PRIMARY KEY, -- ID of the checked out file
490 @ vid INTEGER REFERENCES blob, -- The baseline this file is part of.
491
+2 -2
--- src/util.c
+++ src/util.c
@@ -48,12 +48,12 @@
4848
void *fossil_malloc(size_t n){
4949
void *p = malloc(n==0 ? 1 : n);
5050
if( p==0 ) fossil_panic("out of memory");
5151
return p;
5252
}
53
-void fossil_free(void *p){
54
- free(p);
53
+void fossil_free(const void *p){
54
+ free((void*)p);
5555
}
5656
void *fossil_realloc(void *p, size_t n){
5757
p = realloc(p, n);
5858
if( p==0 ) fossil_panic("out of memory");
5959
return p;
6060
--- src/util.c
+++ src/util.c
@@ -48,12 +48,12 @@
48 void *fossil_malloc(size_t n){
49 void *p = malloc(n==0 ? 1 : n);
50 if( p==0 ) fossil_panic("out of memory");
51 return p;
52 }
53 void fossil_free(void *p){
54 free(p);
55 }
56 void *fossil_realloc(void *p, size_t n){
57 p = realloc(p, n);
58 if( p==0 ) fossil_panic("out of memory");
59 return p;
60
--- src/util.c
+++ src/util.c
@@ -48,12 +48,12 @@
48 void *fossil_malloc(size_t n){
49 void *p = malloc(n==0 ? 1 : n);
50 if( p==0 ) fossil_panic("out of memory");
51 return p;
52 }
53 void fossil_free(const void *p){
54 free((void*)p);
55 }
56 void *fossil_realloc(void *p, size_t n){
57 p = realloc(p, n);
58 if( p==0 ) fossil_panic("out of memory");
59 return p;
60

Keyboard Shortcuts

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