Fossil SCM
Support version 3 format (diff dumps)
Commit
eb0bf08733791043207ab064782fe6104fc00c7c
Parent
2889cdc36df4a4a…
1 file changed
+105
-11
+105
-11
| --- src/import.c | ||
| +++ src/import.c | ||
| @@ -728,11 +728,11 @@ | ||
| 728 | 728 | int nHeaders; |
| 729 | 729 | char *pRawProps; |
| 730 | 730 | KeyVal *aProps; |
| 731 | 731 | int nProps; |
| 732 | 732 | Blob content; |
| 733 | - int nContent; | |
| 733 | + int contentFlag; | |
| 734 | 734 | } SvnRecord; |
| 735 | 735 | |
| 736 | 736 | #define svn_find_header(rec, zHeader) \ |
| 737 | 737 | svn_find_keyval((rec).aHeaders, (rec).nHeaders, (zHeader)) |
| 738 | 738 | #define svn_find_prop(rec, zProp) \ |
| @@ -866,17 +866,20 @@ | ||
| 866 | 866 | if( svn_read_headers(pIn, rec)==0 ) return 0; |
| 867 | 867 | svn_read_props(pIn, rec); |
| 868 | 868 | blob_zero(&rec->content); |
| 869 | 869 | zLen = svn_find_header(*rec, "Text-content-length"); |
| 870 | 870 | if( zLen ){ |
| 871 | + rec->contentFlag = 1; | |
| 871 | 872 | 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; | |
| 878 | 881 | } |
| 879 | 882 | return 1; |
| 880 | 883 | } |
| 881 | 884 | |
| 882 | 885 | static void svn_create_manifests(int flatFlag){ |
| @@ -976,10 +979,11 @@ | ||
| 976 | 979 | } |
| 977 | 980 | db_reset(&qTags); |
| 978 | 981 | blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", rev); |
| 979 | 982 | if( zParentBranch ) { |
| 980 | 983 | blob_appendf(&manifest, "T -sym-%s *\n", zParentBranch); |
| 984 | + zParentBranch = 0; | |
| 981 | 985 | } |
| 982 | 986 | if( zUser ){ |
| 983 | 987 | blob_appendf(&manifest, "U %F\n", zUser); |
| 984 | 988 | }else{ |
| 985 | 989 | const char *zUserOvrd = find_option("user-override",0,1); |
| @@ -1000,10 +1004,64 @@ | ||
| 1000 | 1004 | db_finalize(&qParent); |
| 1001 | 1005 | db_finalize(&qFiles); |
| 1002 | 1006 | db_finalize(&qTags); |
| 1003 | 1007 | db_finalize(&setUuid); |
| 1004 | 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 | + | |
| 1005 | 1063 | /* |
| 1006 | 1064 | ** Read the svn-dump format from pIn and insert the corresponding |
| 1007 | 1065 | ** content into the database. |
| 1008 | 1066 | */ |
| 1009 | 1067 | static void svn_dump_import(FILE *pIn, int flatFlag){ |
| @@ -1022,11 +1080,11 @@ | ||
| 1022 | 1080 | |
| 1023 | 1081 | /* version */ |
| 1024 | 1082 | if( svn_read_rec(pIn, &rec) |
| 1025 | 1083 | && (zTemp = svn_find_header(rec, "SVN-fs-dump-format-version")) ){ |
| 1026 | 1084 | ver = atoi(zTemp); |
| 1027 | - if( ver!=2 ){ | |
| 1085 | + if( ver!=2 && ver!=3 ){ | |
| 1028 | 1086 | fossil_fatal("Unknown svn-dump format version: %d", ver); |
| 1029 | 1087 | } |
| 1030 | 1088 | }else{ |
| 1031 | 1089 | fossil_fatal("Input is not an svn-dump!"); |
| 1032 | 1090 | } |
| @@ -1085,19 +1143,25 @@ | ||
| 1085 | 1143 | if( rev>0 ){ |
| 1086 | 1144 | db_multi_exec("INSERT INTO xfiles (trev, tpath, trid, tperm) " |
| 1087 | 1145 | "SELECT %d, tpath, trid, tperm FROM xfiles " |
| 1088 | 1146 | "WHERE trev=%d", rev, rev-1); |
| 1089 | 1147 | } |
| 1148 | +fossil_print("rev: %d\n", rev); | |
| 1090 | 1149 | }else |
| 1091 | 1150 | if( zTemp = svn_find_header(rec, "Node-path") ){ |
| 1092 | 1151 | const char *zPath = zTemp; |
| 1093 | 1152 | const char *zAction = svn_find_header(rec, "Node-action"); |
| 1094 | 1153 | const char *zKind = svn_find_header(rec, "Node-kind"); |
| 1095 | 1154 | const char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path"); |
| 1096 | 1155 | const char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0; |
| 1156 | + int deltaFlag = 0; | |
| 1097 | 1157 | int srcRev = -1; |
| 1098 | 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 | + } | |
| 1099 | 1163 | if( zSrcPath ){ |
| 1100 | 1164 | zTemp = svn_find_header(rec, "Node-copyfrom-rev"); |
| 1101 | 1165 | if( zTemp ){ |
| 1102 | 1166 | srcRev = atoi(zTemp); |
| 1103 | 1167 | }else{ |
| @@ -1156,27 +1220,56 @@ | ||
| 1156 | 1220 | db_reset(&insTag); |
| 1157 | 1221 | } |
| 1158 | 1222 | } |
| 1159 | 1223 | } |
| 1160 | 1224 | }else{ |
| 1161 | - if( blob_size(&rec.content)==0 && zSrcPath ){ | |
| 1225 | + if( zSrcPath ){ | |
| 1162 | 1226 | rid = db_int(0, |
| 1163 | 1227 | "SELECT trid FROM xfiles WHERE trev=%d AND tpath=%Q", |
| 1164 | 1228 | 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)); | |
| 1166 | 1244 | rid = content_put(&rec.content); |
| 1167 | 1245 | } |
| 1246 | +fossil_print("rid: %d ", rid); | |
| 1168 | 1247 | db_bind_int(&insFile, ":rev", rev); |
| 1169 | 1248 | db_bind_int(&insFile, ":rid", rid); |
| 1170 | 1249 | db_bind_text(&insFile, ":path", zPath); |
| 1171 | 1250 | db_bind_text(&insFile, ":perm", zPerm); |
| 1172 | 1251 | db_step(&insFile); |
| 1173 | 1252 | db_reset(&insFile); |
| 1174 | 1253 | } |
| 1175 | 1254 | }else |
| 1176 | 1255 | 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 | + } | |
| 1178 | 1271 | db_bind_int(&insFile, ":rev", rev); |
| 1179 | 1272 | db_bind_int(&insFile, ":rid", rid); |
| 1180 | 1273 | db_bind_text(&insFile, ":path", zPath); |
| 1181 | 1274 | db_bind_text(&insFile, ":perm", zPerm); |
| 1182 | 1275 | db_step(&insFile); |
| @@ -1188,10 +1281,11 @@ | ||
| 1188 | 1281 | } |
| 1189 | 1282 | }else{ |
| 1190 | 1283 | fossil_fatal("Unknown record type"); |
| 1191 | 1284 | } |
| 1192 | 1285 | svn_free_rec(&rec); |
| 1286 | +fossil_print("done\n"); | |
| 1193 | 1287 | } |
| 1194 | 1288 | if( !flatFlag ){ |
| 1195 | 1289 | if( *zBranch ){ |
| 1196 | 1290 | db_bind_text(&setBranch, ":branch", zBranch); |
| 1197 | 1291 | db_bind_int(&setBranch, ":rev", rev); |
| 1198 | 1292 |
| --- 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 |