Fossil SCM

Support version 3 format (diff dumps)

baruch 2014-10-28 10:44 UTC svn-import
Commit eb0bf08733791043207ab064782fe6104fc00c7c
1 file changed +105 -11
+105 -11
--- src/import.c
+++ src/import.c
@@ -728,11 +728,11 @@
728728
int nHeaders;
729729
char *pRawProps;
730730
KeyVal *aProps;
731731
int nProps;
732732
Blob content;
733
- int nContent;
733
+ int contentFlag;
734734
} SvnRecord;
735735
736736
#define svn_find_header(rec, zHeader) \
737737
svn_find_keyval((rec).aHeaders, (rec).nHeaders, (zHeader))
738738
#define svn_find_prop(rec, zProp) \
@@ -866,17 +866,20 @@
866866
if( svn_read_headers(pIn, rec)==0 ) return 0;
867867
svn_read_props(pIn, rec);
868868
blob_zero(&rec->content);
869869
zLen = svn_find_header(*rec, "Text-content-length");
870870
if( zLen ){
871
+ rec->contentFlag = 1;
871872
nLen = atoi(zLen);
872
- }
873
- blob_read_from_channel(&rec->content, pIn, nLen);
874
- if( blob_size(&rec->content)!=nLen ){
875
- fossil_fatal("short read: got %d of %d bytes",
876
- blob_size(&rec->content), nLen
877
- );
873
+ blob_read_from_channel(&rec->content, pIn, nLen);
874
+ if( blob_size(&rec->content)!=nLen ){
875
+ fossil_fatal("short read: got %d of %d bytes",
876
+ blob_size(&rec->content), nLen
877
+ );
878
+ }
879
+ }else{
880
+ rec->contentFlag = 0;
878881
}
879882
return 1;
880883
}
881884
882885
static void svn_create_manifests(int flatFlag){
@@ -976,10 +979,11 @@
976979
}
977980
db_reset(&qTags);
978981
blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", rev);
979982
if( zParentBranch ) {
980983
blob_appendf(&manifest, "T -sym-%s *\n", zParentBranch);
984
+ zParentBranch = 0;
981985
}
982986
if( zUser ){
983987
blob_appendf(&manifest, "U %F\n", zUser);
984988
}else{
985989
const char *zUserOvrd = find_option("user-override",0,1);
@@ -1000,10 +1004,64 @@
10001004
db_finalize(&qParent);
10011005
db_finalize(&qFiles);
10021006
db_finalize(&qTags);
10031007
db_finalize(&setUuid);
10041008
}
1009
+
1010
+static u64 svn_get_varint(const char **pz){
1011
+ unsigned int v = 0;
1012
+ do{
1013
+ v = (v<<7) | ((*pz)[0]&0x7f);
1014
+ }while( (*pz)++[0]&0x80 );
1015
+ return v;
1016
+}
1017
+
1018
+static void svn_apply_svndiff(Blob *pDiff, Blob *pSrc, Blob *pOut){
1019
+ const char *zDiff = blob_buffer(pDiff);
1020
+ char *zOut;
1021
+ if( blob_size(pDiff)<4 || memcmp(zDiff, "SVN", 4)!=0 ){
1022
+ fossil_fatal("Invalid svndiff0 format");
1023
+ }
1024
+ zDiff += 4;
1025
+ blob_zero(pOut);
1026
+ while( zDiff<(blob_buffer(pDiff)+blob_size(pDiff)) ){
1027
+ u64 offSrc = svn_get_varint(&zDiff);
1028
+ u64 lenSrc = svn_get_varint(&zDiff);
1029
+ u64 lenOut = svn_get_varint(&zDiff);
1030
+ u64 lenInst = svn_get_varint(&zDiff);
1031
+ u64 lenData = svn_get_varint(&zDiff);
1032
+ const char *zInst = zDiff;
1033
+ const char *zData = zInst+lenInst;
1034
+ u64 lenOld = blob_size(pOut);
1035
+ blob_resize(pOut, lenOut);
1036
+ zOut = blob_buffer(pOut) + lenOld;
1037
+ while( zDiff<zInst+lenInst ){
1038
+ u64 lenCpy = (*zDiff)&0x3f;
1039
+ const char *zCpy;
1040
+ switch( (*zDiff)&0xC0 ){
1041
+ case 0x00: zCpy = blob_buffer(pSrc)+offSrc; break;
1042
+ case 0x40: zCpy = blob_buffer(pOut); break;
1043
+ case 0x80: zCpy = zData; break;
1044
+ default: fossil_fatal("Invalid svndiff0 instruction");
1045
+ }
1046
+ zDiff++;
1047
+ if( lenCpy==0 ){
1048
+ lenCpy = svn_get_varint(&zDiff);
1049
+ }
1050
+ if( zCpy!=zData ){
1051
+ zCpy += svn_get_varint(&zDiff);
1052
+ }else{
1053
+ zData += lenCpy;
1054
+ }
1055
+ while( lenCpy-- > 0 ){
1056
+ *zOut++ = *zCpy++;
1057
+ }
1058
+ }
1059
+ zDiff += lenData;
1060
+ }
1061
+}
1062
+
10051063
/*
10061064
** Read the svn-dump format from pIn and insert the corresponding
10071065
** content into the database.
10081066
*/
10091067
static void svn_dump_import(FILE *pIn, int flatFlag){
@@ -1022,11 +1080,11 @@
10221080
10231081
/* version */
10241082
if( svn_read_rec(pIn, &rec)
10251083
&& (zTemp = svn_find_header(rec, "SVN-fs-dump-format-version")) ){
10261084
ver = atoi(zTemp);
1027
- if( ver!=2 ){
1085
+ if( ver!=2 && ver!=3 ){
10281086
fossil_fatal("Unknown svn-dump format version: %d", ver);
10291087
}
10301088
}else{
10311089
fossil_fatal("Input is not an svn-dump!");
10321090
}
@@ -1085,19 +1143,25 @@
10851143
if( rev>0 ){
10861144
db_multi_exec("INSERT INTO xfiles (trev, tpath, trid, tperm) "
10871145
"SELECT %d, tpath, trid, tperm FROM xfiles "
10881146
"WHERE trev=%d", rev, rev-1);
10891147
}
1148
+fossil_print("rev: %d\n", rev);
10901149
}else
10911150
if( zTemp = svn_find_header(rec, "Node-path") ){
10921151
const char *zPath = zTemp;
10931152
const char *zAction = svn_find_header(rec, "Node-action");
10941153
const char *zKind = svn_find_header(rec, "Node-kind");
10951154
const char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path");
10961155
const char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0;
1156
+ int deltaFlag = 0;
10971157
int srcRev = -1;
10981158
int rid = 0;
1159
+fossil_print("file: %s ...", zPath);
1160
+ if( zTemp = svn_find_header(rec, "Text-delta") ){
1161
+ deltaFlag = strncmp(zTemp, "true", 4)==0;
1162
+ }
10991163
if( zSrcPath ){
11001164
zTemp = svn_find_header(rec, "Node-copyfrom-rev");
11011165
if( zTemp ){
11021166
srcRev = atoi(zTemp);
11031167
}else{
@@ -1156,27 +1220,56 @@
11561220
db_reset(&insTag);
11571221
}
11581222
}
11591223
}
11601224
}else{
1161
- if( blob_size(&rec.content)==0 && zSrcPath ){
1225
+ if( zSrcPath ){
11621226
rid = db_int(0,
11631227
"SELECT trid FROM xfiles WHERE trev=%d AND tpath=%Q",
11641228
srcRev, zSrcPath);
1165
- }else{
1229
+ }
1230
+ if( deltaFlag ){
1231
+ Blob deltaSrc;
1232
+ Blob target;
1233
+fossil_print("diff-size: %d ", blob_size(&rec.content));
1234
+ if( rid!=0 ){
1235
+ content_get(rid, &deltaSrc);
1236
+ }else{
1237
+ blob_zero(&deltaSrc);
1238
+ }
1239
+ svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1240
+fossil_print("real-size: %d ", blob_size(&target));
1241
+ rid = content_put(&target);
1242
+ }else if( rec.contentFlag ){
1243
+fossil_print("size: %d ", blob_size(&rec.content));
11661244
rid = content_put(&rec.content);
11671245
}
1246
+fossil_print("rid: %d ", rid);
11681247
db_bind_int(&insFile, ":rev", rev);
11691248
db_bind_int(&insFile, ":rid", rid);
11701249
db_bind_text(&insFile, ":path", zPath);
11711250
db_bind_text(&insFile, ":perm", zPerm);
11721251
db_step(&insFile);
11731252
db_reset(&insFile);
11741253
}
11751254
}else
11761255
if( strncmp(zAction, "change", 6)==0 ){
1177
- rid = content_put(&rec.content);
1256
+ if( zKind==0 ){
1257
+ fossil_fatal("Missing Node-kind");
1258
+ }
1259
+ if( strncmp(zKind, "dir", 3)==0 ) continue;
1260
+ if( deltaFlag ){
1261
+ Blob deltaSrc;
1262
+ Blob target;
1263
+ rid = db_int(0, "SELECT trid FROM xfiles WHERE tpath=%Q AND trev=%d",
1264
+ zPath, rev-1);
1265
+ content_get(rid, &deltaSrc);
1266
+ svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1267
+ rid = content_put(&target);
1268
+ }else{
1269
+ rid = content_put(&rec.content);
1270
+ }
11781271
db_bind_int(&insFile, ":rev", rev);
11791272
db_bind_int(&insFile, ":rid", rid);
11801273
db_bind_text(&insFile, ":path", zPath);
11811274
db_bind_text(&insFile, ":perm", zPerm);
11821275
db_step(&insFile);
@@ -1188,10 +1281,11 @@
11881281
}
11891282
}else{
11901283
fossil_fatal("Unknown record type");
11911284
}
11921285
svn_free_rec(&rec);
1286
+fossil_print("done\n");
11931287
}
11941288
if( !flatFlag ){
11951289
if( *zBranch ){
11961290
db_bind_text(&setBranch, ":branch", zBranch);
11971291
db_bind_int(&setBranch, ":rev", rev);
11981292
--- src/import.c
+++ src/import.c
@@ -728,11 +728,11 @@
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) \
@@ -866,17 +866,20 @@
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 blob_read_from_channel(&rec->content, pIn, nLen);
874 if( blob_size(&rec->content)!=nLen ){
875 fossil_fatal("short read: got %d of %d bytes",
876 blob_size(&rec->content), nLen
877 );
 
 
878 }
879 return 1;
880 }
881
882 static void svn_create_manifests(int flatFlag){
@@ -976,10 +979,11 @@
976 }
977 db_reset(&qTags);
978 blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", rev);
979 if( zParentBranch ) {
980 blob_appendf(&manifest, "T -sym-%s *\n", zParentBranch);
 
981 }
982 if( zUser ){
983 blob_appendf(&manifest, "U %F\n", zUser);
984 }else{
985 const char *zUserOvrd = find_option("user-override",0,1);
@@ -1000,10 +1004,64 @@
1000 db_finalize(&qParent);
1001 db_finalize(&qFiles);
1002 db_finalize(&qTags);
1003 db_finalize(&setUuid);
1004 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1005 /*
1006 ** Read the svn-dump format from pIn and insert the corresponding
1007 ** content into the database.
1008 */
1009 static void svn_dump_import(FILE *pIn, int flatFlag){
@@ -1022,11 +1080,11 @@
1022
1023 /* version */
1024 if( svn_read_rec(pIn, &rec)
1025 && (zTemp = svn_find_header(rec, "SVN-fs-dump-format-version")) ){
1026 ver = atoi(zTemp);
1027 if( ver!=2 ){
1028 fossil_fatal("Unknown svn-dump format version: %d", ver);
1029 }
1030 }else{
1031 fossil_fatal("Input is not an svn-dump!");
1032 }
@@ -1085,19 +1143,25 @@
1085 if( rev>0 ){
1086 db_multi_exec("INSERT INTO xfiles (trev, tpath, trid, tperm) "
1087 "SELECT %d, tpath, trid, tperm FROM xfiles "
1088 "WHERE trev=%d", rev, rev-1);
1089 }
 
1090 }else
1091 if( zTemp = svn_find_header(rec, "Node-path") ){
1092 const char *zPath = zTemp;
1093 const char *zAction = svn_find_header(rec, "Node-action");
1094 const char *zKind = svn_find_header(rec, "Node-kind");
1095 const char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path");
1096 const char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0;
 
1097 int srcRev = -1;
1098 int rid = 0;
 
 
 
 
1099 if( zSrcPath ){
1100 zTemp = svn_find_header(rec, "Node-copyfrom-rev");
1101 if( zTemp ){
1102 srcRev = atoi(zTemp);
1103 }else{
@@ -1156,27 +1220,56 @@
1156 db_reset(&insTag);
1157 }
1158 }
1159 }
1160 }else{
1161 if( blob_size(&rec.content)==0 && zSrcPath ){
1162 rid = db_int(0,
1163 "SELECT trid FROM xfiles WHERE trev=%d AND tpath=%Q",
1164 srcRev, zSrcPath);
1165 }else{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1166 rid = content_put(&rec.content);
1167 }
 
1168 db_bind_int(&insFile, ":rev", rev);
1169 db_bind_int(&insFile, ":rid", rid);
1170 db_bind_text(&insFile, ":path", zPath);
1171 db_bind_text(&insFile, ":perm", zPerm);
1172 db_step(&insFile);
1173 db_reset(&insFile);
1174 }
1175 }else
1176 if( strncmp(zAction, "change", 6)==0 ){
1177 rid = content_put(&rec.content);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1178 db_bind_int(&insFile, ":rev", rev);
1179 db_bind_int(&insFile, ":rid", rid);
1180 db_bind_text(&insFile, ":path", zPath);
1181 db_bind_text(&insFile, ":perm", zPerm);
1182 db_step(&insFile);
@@ -1188,10 +1281,11 @@
1188 }
1189 }else{
1190 fossil_fatal("Unknown record type");
1191 }
1192 svn_free_rec(&rec);
 
1193 }
1194 if( !flatFlag ){
1195 if( *zBranch ){
1196 db_bind_text(&setBranch, ":branch", zBranch);
1197 db_bind_int(&setBranch, ":rev", rev);
1198
--- src/import.c
+++ src/import.c
@@ -728,11 +728,11 @@
728 int nHeaders;
729 char *pRawProps;
730 KeyVal *aProps;
731 int nProps;
732 Blob content;
733 int contentFlag;
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) \
@@ -866,17 +866,20 @@
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 rec->contentFlag = 1;
872 nLen = atoi(zLen);
873 blob_read_from_channel(&rec->content, pIn, nLen);
874 if( blob_size(&rec->content)!=nLen ){
875 fossil_fatal("short read: got %d of %d bytes",
876 blob_size(&rec->content), nLen
877 );
878 }
879 }else{
880 rec->contentFlag = 0;
881 }
882 return 1;
883 }
884
885 static void svn_create_manifests(int flatFlag){
@@ -976,10 +979,11 @@
979 }
980 db_reset(&qTags);
981 blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", rev);
982 if( zParentBranch ) {
983 blob_appendf(&manifest, "T -sym-%s *\n", zParentBranch);
984 zParentBranch = 0;
985 }
986 if( zUser ){
987 blob_appendf(&manifest, "U %F\n", zUser);
988 }else{
989 const char *zUserOvrd = find_option("user-override",0,1);
@@ -1000,10 +1004,64 @@
1004 db_finalize(&qParent);
1005 db_finalize(&qFiles);
1006 db_finalize(&qTags);
1007 db_finalize(&setUuid);
1008 }
1009
1010 static u64 svn_get_varint(const char **pz){
1011 unsigned int v = 0;
1012 do{
1013 v = (v<<7) | ((*pz)[0]&0x7f);
1014 }while( (*pz)++[0]&0x80 );
1015 return v;
1016 }
1017
1018 static void svn_apply_svndiff(Blob *pDiff, Blob *pSrc, Blob *pOut){
1019 const char *zDiff = blob_buffer(pDiff);
1020 char *zOut;
1021 if( blob_size(pDiff)<4 || memcmp(zDiff, "SVN", 4)!=0 ){
1022 fossil_fatal("Invalid svndiff0 format");
1023 }
1024 zDiff += 4;
1025 blob_zero(pOut);
1026 while( zDiff<(blob_buffer(pDiff)+blob_size(pDiff)) ){
1027 u64 offSrc = svn_get_varint(&zDiff);
1028 u64 lenSrc = svn_get_varint(&zDiff);
1029 u64 lenOut = svn_get_varint(&zDiff);
1030 u64 lenInst = svn_get_varint(&zDiff);
1031 u64 lenData = svn_get_varint(&zDiff);
1032 const char *zInst = zDiff;
1033 const char *zData = zInst+lenInst;
1034 u64 lenOld = blob_size(pOut);
1035 blob_resize(pOut, lenOut);
1036 zOut = blob_buffer(pOut) + lenOld;
1037 while( zDiff<zInst+lenInst ){
1038 u64 lenCpy = (*zDiff)&0x3f;
1039 const char *zCpy;
1040 switch( (*zDiff)&0xC0 ){
1041 case 0x00: zCpy = blob_buffer(pSrc)+offSrc; break;
1042 case 0x40: zCpy = blob_buffer(pOut); break;
1043 case 0x80: zCpy = zData; break;
1044 default: fossil_fatal("Invalid svndiff0 instruction");
1045 }
1046 zDiff++;
1047 if( lenCpy==0 ){
1048 lenCpy = svn_get_varint(&zDiff);
1049 }
1050 if( zCpy!=zData ){
1051 zCpy += svn_get_varint(&zDiff);
1052 }else{
1053 zData += lenCpy;
1054 }
1055 while( lenCpy-- > 0 ){
1056 *zOut++ = *zCpy++;
1057 }
1058 }
1059 zDiff += lenData;
1060 }
1061 }
1062
1063 /*
1064 ** Read the svn-dump format from pIn and insert the corresponding
1065 ** content into the database.
1066 */
1067 static void svn_dump_import(FILE *pIn, int flatFlag){
@@ -1022,11 +1080,11 @@
1080
1081 /* version */
1082 if( svn_read_rec(pIn, &rec)
1083 && (zTemp = svn_find_header(rec, "SVN-fs-dump-format-version")) ){
1084 ver = atoi(zTemp);
1085 if( ver!=2 && ver!=3 ){
1086 fossil_fatal("Unknown svn-dump format version: %d", ver);
1087 }
1088 }else{
1089 fossil_fatal("Input is not an svn-dump!");
1090 }
@@ -1085,19 +1143,25 @@
1143 if( rev>0 ){
1144 db_multi_exec("INSERT INTO xfiles (trev, tpath, trid, tperm) "
1145 "SELECT %d, tpath, trid, tperm FROM xfiles "
1146 "WHERE trev=%d", rev, rev-1);
1147 }
1148 fossil_print("rev: %d\n", rev);
1149 }else
1150 if( zTemp = svn_find_header(rec, "Node-path") ){
1151 const char *zPath = zTemp;
1152 const char *zAction = svn_find_header(rec, "Node-action");
1153 const char *zKind = svn_find_header(rec, "Node-kind");
1154 const char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path");
1155 const char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0;
1156 int deltaFlag = 0;
1157 int srcRev = -1;
1158 int rid = 0;
1159 fossil_print("file: %s ...", zPath);
1160 if( zTemp = svn_find_header(rec, "Text-delta") ){
1161 deltaFlag = strncmp(zTemp, "true", 4)==0;
1162 }
1163 if( zSrcPath ){
1164 zTemp = svn_find_header(rec, "Node-copyfrom-rev");
1165 if( zTemp ){
1166 srcRev = atoi(zTemp);
1167 }else{
@@ -1156,27 +1220,56 @@
1220 db_reset(&insTag);
1221 }
1222 }
1223 }
1224 }else{
1225 if( zSrcPath ){
1226 rid = db_int(0,
1227 "SELECT trid FROM xfiles WHERE trev=%d AND tpath=%Q",
1228 srcRev, zSrcPath);
1229 }
1230 if( deltaFlag ){
1231 Blob deltaSrc;
1232 Blob target;
1233 fossil_print("diff-size: %d ", blob_size(&rec.content));
1234 if( rid!=0 ){
1235 content_get(rid, &deltaSrc);
1236 }else{
1237 blob_zero(&deltaSrc);
1238 }
1239 svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1240 fossil_print("real-size: %d ", blob_size(&target));
1241 rid = content_put(&target);
1242 }else if( rec.contentFlag ){
1243 fossil_print("size: %d ", blob_size(&rec.content));
1244 rid = content_put(&rec.content);
1245 }
1246 fossil_print("rid: %d ", rid);
1247 db_bind_int(&insFile, ":rev", rev);
1248 db_bind_int(&insFile, ":rid", rid);
1249 db_bind_text(&insFile, ":path", zPath);
1250 db_bind_text(&insFile, ":perm", zPerm);
1251 db_step(&insFile);
1252 db_reset(&insFile);
1253 }
1254 }else
1255 if( strncmp(zAction, "change", 6)==0 ){
1256 if( zKind==0 ){
1257 fossil_fatal("Missing Node-kind");
1258 }
1259 if( strncmp(zKind, "dir", 3)==0 ) continue;
1260 if( deltaFlag ){
1261 Blob deltaSrc;
1262 Blob target;
1263 rid = db_int(0, "SELECT trid FROM xfiles WHERE tpath=%Q AND trev=%d",
1264 zPath, rev-1);
1265 content_get(rid, &deltaSrc);
1266 svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1267 rid = content_put(&target);
1268 }else{
1269 rid = content_put(&rec.content);
1270 }
1271 db_bind_int(&insFile, ":rev", rev);
1272 db_bind_int(&insFile, ":rid", rid);
1273 db_bind_text(&insFile, ":path", zPath);
1274 db_bind_text(&insFile, ":perm", zPerm);
1275 db_step(&insFile);
@@ -1188,10 +1281,11 @@
1281 }
1282 }else{
1283 fossil_fatal("Unknown record type");
1284 }
1285 svn_free_rec(&rec);
1286 fossil_print("done\n");
1287 }
1288 if( !flatFlag ){
1289 if( *zBranch ){
1290 db_bind_text(&setBranch, ":branch", zBranch);
1291 db_bind_int(&setBranch, ":rev", rev);
1292

Keyboard Shortcuts

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