Fossil SCM
More work. Still not usable
Commit
2ea79975b60e7af92ccb2262edce51fb66efd6a5
Parent
9604c28207d0aea…
1 file changed
+67
-187
+67
-187
| --- src/import.c | ||
| +++ src/import.c | ||
| @@ -718,129 +718,24 @@ | ||
| 718 | 718 | fossil_fatal("bad fast-import line: [%s]", zLine); |
| 719 | 719 | return; |
| 720 | 720 | } |
| 721 | 721 | |
| 722 | 722 | static struct{ |
| 723 | - char *zBranch; /* Name of a branch for a commit */ | |
| 724 | - char *zDate; /* Date/time stamp */ | |
| 725 | - char *zUser; /* User name */ | |
| 726 | - char *zComment; /* Comment of a commit */ | |
| 727 | - char *zFrom; /* from value as a UUID */ | |
| 728 | - int nMerge; /* Number of merge values */ | |
| 729 | - int nMergeAlloc; /* Number of slots in azMerge[] */ | |
| 730 | - char **azMerge; /* Merge values */ | |
| 731 | - int nFile; /* Number of aFile values */ | |
| 732 | - int nFileAlloc; /* Number of slots in aFile[] */ | |
| 733 | - ImportFile *aFile; /* Information about files in a commit */ | |
| 734 | - int fromLoaded; /* True zFrom content loaded into aFile[] */ | |
| 735 | -} gsvn; | |
| 736 | - | |
| 737 | -/* | |
| 738 | -** Create a new entry in the gsvn.aFile[] array | |
| 739 | -*/ | |
| 740 | -static ImportFile *svn_import_add_file(){ | |
| 741 | - ImportFile *pFile; | |
| 742 | - if( gsvn.nFile>=gsvn.nFileAlloc ){ | |
| 743 | - gsvn.nFileAlloc = gsvn.nFileAlloc*2 + 100; | |
| 744 | - gsvn.aFile = fossil_realloc(gsvn.aFile, gsvn.nFileAlloc*sizeof(gsvn.aFile[0])); | |
| 745 | - } | |
| 746 | - pFile = &gsvn.aFile[gsvn.nFile++]; | |
| 747 | - memset(pFile, 0, sizeof(*pFile)); | |
| 748 | - return pFile; | |
| 749 | -} | |
| 750 | - | |
| 751 | -/* | |
| 752 | -** Load all file information out of the gsvn.zFrom check-in | |
| 753 | -*/ | |
| 754 | -static void svn_import_prior_files(void){ | |
| 755 | - Manifest *p; | |
| 756 | - int rid; | |
| 757 | - ManifestFile *pOld; | |
| 758 | - ImportFile *pNew; | |
| 759 | - if( gsvn.fromLoaded ) return; | |
| 760 | - gsvn.fromLoaded = 1; | |
| 761 | - if( gsvn.zFrom==0 && gsvn.zPrevCheckin!=0 | |
| 762 | - && fossil_strcmp(gsvn.zBranch, gsvn.zPrevBranch)==0 | |
| 763 | - ){ | |
| 764 | - gsvn.zFrom = gsvn.zPrevCheckin; | |
| 765 | - gsvn.zPrevCheckin = 0; | |
| 766 | - } | |
| 767 | - if( gsvn.zFrom==0 ) return; | |
| 768 | - rid = fast_uuid_to_rid(gsvn.zFrom); | |
| 769 | - if( rid==0 ) return; | |
| 770 | - p = manifest_get(rid, CFTYPE_MANIFEST, 0); | |
| 771 | - if( p==0 ) return; | |
| 772 | - manifest_file_rewind(p); | |
| 773 | - while( (pOld = manifest_file_next(p, 0))!=0 ){ | |
| 774 | - pNew = import_add_file(); | |
| 775 | - pNew->zName = fossil_strdup(pOld->zName); | |
| 776 | - pNew->isExe = pOld->zPerm && strstr(pOld->zPerm, "x")!=0; | |
| 777 | - pNew->isLink = pOld->zPerm && strstr(pOld->zPerm, "l")!=0; | |
| 778 | - pNew->zUuid = fossil_strdup(pOld->zUuid); | |
| 779 | - pNew->isFrom = 1; | |
| 780 | - } | |
| 781 | - manifest_destroy(p); | |
| 782 | -} | |
| 783 | - | |
| 784 | -/* | |
| 785 | -** Deallocate the state information. | |
| 786 | -** | |
| 787 | -** The azMerge[] and aFile[] arrays are zeroed but allocated space is | |
| 788 | -** retained unless the freeAll flag is set. | |
| 789 | -*/ | |
| 790 | -static void svn_import_reset(int freeAll){ | |
| 791 | - int i; | |
| 792 | -// gsvn.xFinish = 0; | |
| 793 | -// fossil_free(gsvn.zTag); gsvn.zTag = 0; | |
| 794 | - fossil_free(gsvn.zBranch); gsvn.zBranch = 0; | |
| 795 | -// fossil_free(gsvn.aData); gsvn.aData = 0; | |
| 796 | -// fossil_free(gsvn.zMark); gsvn.zMark = 0; | |
| 797 | - fossil_free(gsvn.zDate); gsvn.zDate = 0; | |
| 798 | - fossil_free(gsvn.zUser); gsvn.zUser = 0; | |
| 799 | - fossil_free(gsvn.zComment); gsvn.zComment = 0; | |
| 800 | - fossil_free(gsvn.zFrom); gsvn.zFrom = 0; | |
| 801 | -// fossil_free(gsvn.zFromMark); gsvn.zFromMark = 0; | |
| 802 | - for(i=0; i<gsvn.nMerge; i++){ | |
| 803 | - fossil_free(gsvn.azMerge[i]); gsvn.azMerge[i] = 0; | |
| 804 | - } | |
| 805 | - gsvn.nMerge = 0; | |
| 806 | - for(i=0; i<gsvn.nFile; i++){ | |
| 807 | - fossil_free(gsvn.aFile[i].zName); | |
| 808 | - fossil_free(gsvn.aFile[i].zUuid); | |
| 809 | - fossil_free(gsvn.aFile[i].zPrior); | |
| 810 | - } | |
| 811 | - memset(gsvn.aFile, 0, gsvn.nFile*sizeof(gsvn.aFile[0])); | |
| 812 | - gsvn.nFile = 0; | |
| 813 | - if( freeAll ){ | |
| 814 | -// fossil_free(gsvn.zPrevBranch); | |
| 815 | -// fossil_free(gsvn.zPrevCheckin); | |
| 816 | - fossil_free(gsvn.azMerge); | |
| 817 | - fossil_free(gsvn.aFile); | |
| 818 | - memset(&gsvn, 0, sizeof(gsvn)); | |
| 819 | - } | |
| 820 | -// gsvn.xFinish = finish_noop; | |
| 821 | -} | |
| 822 | - | |
| 823 | -static struct{ | |
| 824 | - int rev; /* SVN revision number */ | |
| 825 | -// int parentRev; /* SVN revision number of parent check-in */ | |
| 826 | -// char *zParentBranch; /* Name of branch of parent check-in */ | |
| 827 | -// char *zBranch; /* Name of a branch for a commit */ | |
| 828 | - char *zDate; /* Date/time stamp */ | |
| 829 | - char *zUser; /* User name */ | |
| 830 | - char *zComment; /* Comment of a commit */ | |
| 831 | -// int flatFlag; /* True if whole repo is a single file tree */ | |
| 723 | + int rev; /* SVN revision number */ | |
| 724 | + char *zDate; /* Date/time stamp */ | |
| 725 | + char *zUser; /* User name */ | |
| 726 | + char *zComment; /* Comment of a commit */ | |
| 832 | 727 | const char *zTrunk; /* Name of trunk folder in repo root */ |
| 833 | 728 | int lenTrunk; /* String length of zTrunk */ |
| 834 | 729 | const char *zBranches; /* Name of branches folder in repo root */ |
| 835 | 730 | int lenBranches; /* String length of zBranches */ |
| 836 | 731 | const char *zTags; /* Name of tags folder in repo root */ |
| 837 | 732 | int lenTags; /* String length of zTags */ |
| 838 | 733 | } gsvn; |
| 839 | 734 | typedef struct { |
| 840 | 735 | char *zKey; |
| 841 | - const char *zVal; | |
| 736 | + char *zVal; | |
| 842 | 737 | } KeyVal; |
| 843 | 738 | typedef struct { |
| 844 | 739 | KeyVal *aHeaders; |
| 845 | 740 | int nHeaders; |
| 846 | 741 | char *pRawProps; |
| @@ -852,11 +747,11 @@ | ||
| 852 | 747 | |
| 853 | 748 | #define svn_find_header(rec, zHeader) \ |
| 854 | 749 | svn_find_keyval((rec).aHeaders, (rec).nHeaders, (zHeader)) |
| 855 | 750 | #define svn_find_prop(rec, zProp) \ |
| 856 | 751 | svn_find_keyval((rec).aProps, (rec).nProps, (zProp)) |
| 857 | -static const char *svn_find_keyval( | |
| 752 | +static char *svn_find_keyval( | |
| 858 | 753 | KeyVal *aKeyVal, |
| 859 | 754 | int nKeyVal, |
| 860 | 755 | const char *zKey |
| 861 | 756 | ){ |
| 862 | 757 | int i; |
| @@ -1003,51 +898,24 @@ | ||
| 1003 | 898 | rec->contentFlag = 0; |
| 1004 | 899 | } |
| 1005 | 900 | return 1; |
| 1006 | 901 | } |
| 1007 | 902 | |
| 1008 | -static void svn_finish_revision( | |
| 1009 | -){ | |
| 903 | +static void svn_finish_revision(){ | |
| 1010 | 904 | Blob manifest; |
| 1011 | 905 | static Stmt insRev; |
| 1012 | - static Stmt qParent; | |
| 1013 | - static Stmt qParent2; | |
| 1014 | - static Stmt qFiles; | |
| 1015 | - static Stmt qTags; | |
| 1016 | - int nBaseFilter; | |
| 1017 | - int nFilter; | |
| 1018 | - int rid; | |
| 1019 | - char *zParentBranch = 0; | |
| 1020 | 906 | Blob mcksum; |
| 1021 | 907 | |
| 1022 | 908 | blob_zero(&manifest); |
| 1023 | - nBaseFilter = blob_size(&gsvn.filter); | |
| 1024 | - if( !gsvn.flatFlag ){ | |
| 1025 | - if( gsvn.zBranch==0 ){ return; } | |
| 1026 | - if( strncmp(gsvn.zBranch, gsvn.zTrunk, gsvn.lenTrunk-1)==0 ){ | |
| 1027 | - blob_appendf(&gsvn.filter, "%s*", gsvn.zTrunk); | |
| 1028 | - }else{ | |
| 1029 | - blob_appendf(&gsvn.filter, "%s%s/*", gsvn.zBranches, gsvn.zBranch); | |
| 1030 | - } | |
| 1031 | - }else{ | |
| 1032 | - blob_append(&gsvn.filter, "*", 1); | |
| 1033 | - } | |
| 1034 | - if( db_int(0, "SELECT 1 FROM xhist WHERE trev=%d AND tpath GLOB %Q LIMIT 1", | |
| 1035 | - gsvn.rev, blob_str(&gsvn.filter))==0 | |
| 1036 | - ){ | |
| 1037 | - goto skip_revision; | |
| 1038 | - } | |
| 1039 | - db_static_prepare(&insRev, "REPLACE INTO xrevisions (trev, tbranch, tuuid) " | |
| 1040 | - "VALUES(:rev, :branch, " | |
| 1041 | - " (SELECT uuid FROM blob WHERE rid=:rid))"); | |
| 1042 | - db_static_prepare(&qParent, "SELECT tuuid, max(trev) FROM xrevisions " | |
| 1043 | - "WHERE trev<=:rev AND tbranch=:branch"); | |
| 1044 | - db_static_prepare(&qParent2, "SELECT tuuid, min(trev) " | |
| 1045 | - "FROM xrevisions WHERE tbranch=:branch"); | |
| 1046 | - db_static_prepare(&qFiles, "SELECT tpath, trid, tperm FROM xfiles " | |
| 1047 | - "WHERE tpath GLOB :filter ORDER BY tpath"); | |
| 1048 | - db_static_prepare(&qTags, "SELECT ttag FROM xtags WHERE trev=:rev"); | |
| 909 | + db_static_prepare(&getChanges, "SELECT tbranch, ttype FROM xchanged"); | |
| 910 | + db_static_prepare(&getFiles, "SELECT tpath, tuuid, tperm," | |
| 911 | + " tsrc, tsrcbranch, trev tsrcrev" | |
| 912 | + " FROM xfiles, xsrc" | |
| 913 | + " ON tpath, tbranch)" | |
| 914 | + " WHERE tbranch=:branch ORDER BY tpath"); | |
| 915 | + db_static_prepare(&setRid, "REPLACE INTO xrevisions(trev, tbranch, trid)" | |
| 916 | + " VALUES (%d, :branch, :rid)", gsvn.rev); | |
| 1049 | 917 | if( !gsvn.flatFlag ){ |
| 1050 | 918 | if( gsvn.parentRev<0 ){ |
| 1051 | 919 | gsvn.parentRev = db_int(-1, "SELECT ifnull(max(trev),-1) FROM xrevisions " |
| 1052 | 920 | "WHERE tbranch=%Q", gsvn.zBranch); |
| 1053 | 921 | if( gsvn.parentRev<0 ){ |
| @@ -1216,14 +1084,26 @@ | ||
| 1216 | 1084 | ** Returns: 1 - It is on the trunk |
| 1217 | 1085 | ** 2 - It is on a branch |
| 1218 | 1086 | ** 3 - It is a tag |
| 1219 | 1087 | ** 0 - It is none of the above |
| 1220 | 1088 | */ |
| 1221 | -static int *svn_parse_path(char *zPath, char **zBranch, char **zFile){ | |
| 1222 | - if( strncmp(zPath, gsvn.zTrunk, gsvn.lenTrunk)==0 ){ | |
| 1089 | +static int svn_parse_path(char *zPath, char **zBranch, char **zFile){ | |
| 1090 | + if( gsvn.lenTrunk==0 ){ | |
| 1091 | + *zBranch = "trunk"; | |
| 1092 | + *zFile = zPath; | |
| 1093 | + return 1; | |
| 1094 | + }else | |
| 1095 | + if( strncmp(zPath, gsvn.zTrunk, gsvn.lenTrunk-1)==0 ){ | |
| 1223 | 1096 | *zBranch = "trunk"; |
| 1224 | - *zFile = zPath+gsvn.lenTrunk; | |
| 1097 | + if( zPath[gsvn.lenTrunk-1]=='/' ){ | |
| 1098 | + *zFile = zPath+gsvn.lenTrunk;; | |
| 1099 | + }else if( zPath[gsvn.lenTrunk-1]==0 ){ | |
| 1100 | + *zFile = 0; | |
| 1101 | + }else{ | |
| 1102 | + *zFile = *zBranch = 0; | |
| 1103 | + return 0; | |
| 1104 | + } | |
| 1225 | 1105 | return 1; |
| 1226 | 1106 | }else |
| 1227 | 1107 | if( strncmp(zPath, gsvn.zBranches, gsvn.lenBranches)==0 ){ |
| 1228 | 1108 | *zFile = *zBranch = zPath+gsvn.lenBranches; |
| 1229 | 1109 | while( **zFile && **zFile!='/' ){ (*zFile)++; } |
| @@ -1283,11 +1163,11 @@ | ||
| 1283 | 1163 | svn_free_rec(&rec); |
| 1284 | 1164 | |
| 1285 | 1165 | /* content */ |
| 1286 | 1166 | db_prepare(&addFile, |
| 1287 | 1167 | "INSERT INTO xfiles (tpath, tbranch, tuuid, tperm)" |
| 1288 | - " VALUES(:path, :branch, :uuid, :perm)" | |
| 1168 | + " VALUES(:path, :branch, (SELECT uuid FROM blob WHERE rid=:rid), :perm)" | |
| 1289 | 1169 | ); |
| 1290 | 1170 | db_prepare(&delPath, |
| 1291 | 1171 | "DELETE FROM xfiles" |
| 1292 | 1172 | " WHERE (tpath=:path OR (tpath>:path||'/' AND tpath<:path||'0'))" |
| 1293 | 1173 | " AND tbranch=:branch" |
| @@ -1307,11 +1187,11 @@ | ||
| 1307 | 1187 | ); |
| 1308 | 1188 | gsvn.rev = -1; |
| 1309 | 1189 | while( svn_read_rec(pIn, &rec) ){ |
| 1310 | 1190 | if( (zTemp = svn_find_header(rec, "Revision-number")) ){ /* revision node */ |
| 1311 | 1191 | /* finish previous revision */ |
| 1312 | - const char *zDate = NULL; | |
| 1192 | + char *zDate = NULL; | |
| 1313 | 1193 | if( gsvn.rev>=0 ){ |
| 1314 | 1194 | svn_finish_revision(); |
| 1315 | 1195 | fossil_free(gsvn.zUser); |
| 1316 | 1196 | fossil_free(gsvn.zComment); |
| 1317 | 1197 | fossil_free(gsvn.zDate); |
| @@ -1326,14 +1206,14 @@ | ||
| 1326 | 1206 | } |
| 1327 | 1207 | gsvn.zDate = zDate; |
| 1328 | 1208 | fossil_print("\rImporting SVN revision: %d", gsvn.rev); |
| 1329 | 1209 | }else |
| 1330 | 1210 | if( (zTemp = svn_find_header(rec, "Node-path")) ){ /* file/dir node */ |
| 1331 | - const char *zAction = svn_find_header(rec, "Node-action"); | |
| 1332 | - const char *zKind = svn_find_header(rec, "Node-kind"); | |
| 1333 | - const char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path"); | |
| 1334 | - const char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0; | |
| 1211 | + char *zAction = svn_find_header(rec, "Node-action"); | |
| 1212 | + char *zKind = svn_find_header(rec, "Node-kind"); | |
| 1213 | + char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path"); | |
| 1214 | + char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0; | |
| 1335 | 1215 | char *zBranch; |
| 1336 | 1216 | char *zFile; |
| 1337 | 1217 | char *zSrcBranch; |
| 1338 | 1218 | char *zSrcFile; |
| 1339 | 1219 | int deltaFlag = 0; |
| @@ -1355,11 +1235,11 @@ | ||
| 1355 | 1235 | if( zTemp ){ |
| 1356 | 1236 | srcRev = atoi(zTemp); |
| 1357 | 1237 | }else{ |
| 1358 | 1238 | fossil_fatal("Missing copyfrom-rev"); |
| 1359 | 1239 | } |
| 1360 | - if( svn_extract_branch(zSrcPath, &zSrcBranch, &zSrcFile)==0 ){ | |
| 1240 | + if( svn_parse_path(zSrcPath, &zSrcBranch, &zSrcFile)==0 ){ | |
| 1361 | 1241 | fossil_fatal("Copy from path outside the import paths"); |
| 1362 | 1242 | } |
| 1363 | 1243 | db_bind_text(&addSrc, ":path", zFile); |
| 1364 | 1244 | db_bind_text(&addSrc, ":branch", zBranch); |
| 1365 | 1245 | db_bind_text(&addSrc, ":srcpath", zSrcFile); |
| @@ -1397,13 +1277,15 @@ | ||
| 1397 | 1277 | int rid = 0; |
| 1398 | 1278 | if( zSrcPath ){ |
| 1399 | 1279 | int srcRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions" |
| 1400 | 1280 | " WHERE trev<=%d AND tbranch=%Q", |
| 1401 | 1281 | srcRev, zSrcBranch); |
| 1402 | - rid = db_int(0, "SELECT rid FROM xfoci" | |
| 1403 | - " WHERE chekinID=%d AND filename=%Q", | |
| 1404 | - srcRid, zSrcFile) | |
| 1282 | + rid = db_int(0, "SELECT rid FROM blob WHERE uuid=(" | |
| 1283 | + " SELECT uuid FROM xfoci" | |
| 1284 | + " WHERE chekinID=%d AND filename=%Q" | |
| 1285 | + ")", | |
| 1286 | + srcRid, zSrcFile); | |
| 1405 | 1287 | } |
| 1406 | 1288 | if( deltaFlag ){ |
| 1407 | 1289 | Blob deltaSrc; |
| 1408 | 1290 | Blob target; |
| 1409 | 1291 | if( rid!=0 ){ |
| @@ -1414,16 +1296,16 @@ | ||
| 1414 | 1296 | svn_apply_svndiff(&rec.content, &deltaSrc, &target); |
| 1415 | 1297 | rid = content_put(&target); |
| 1416 | 1298 | }else if( rec.contentFlag ){ |
| 1417 | 1299 | rid = content_put(&rec.content); |
| 1418 | 1300 | } |
| 1419 | - db_bind_int(&addHist, ":rid", rid); | |
| 1420 | - db_bind_text(&addHist, ":path", zPath); | |
| 1421 | - db_bind_text(&addHist, ":perm", zPerm); | |
| 1422 | - db_step(&addHist); | |
| 1423 | - db_reset(&addHist); | |
| 1424 | - bHasFiles = 1; | |
| 1301 | + db_bind_text(&addFile, ":path", zFile); | |
| 1302 | + db_bind_text(&addFile, ":branch", zBranch); | |
| 1303 | + db_bind_int(&addFile, ":rid", rid); | |
| 1304 | + db_bind_text(&addFile, ":perm", zPerm); | |
| 1305 | + db_step(&addFile); | |
| 1306 | + db_reset(&addFile); | |
| 1425 | 1307 | } |
| 1426 | 1308 | }else |
| 1427 | 1309 | if( strncmp(zAction, "change", 6)==0 ){ |
| 1428 | 1310 | int rid = 0; |
| 1429 | 1311 | if( zKind==0 ){ |
| @@ -1431,24 +1313,26 @@ | ||
| 1431 | 1313 | } |
| 1432 | 1314 | if( strncmp(zKind, "dir", 3)!=0 ){ |
| 1433 | 1315 | if( deltaFlag ){ |
| 1434 | 1316 | Blob deltaSrc; |
| 1435 | 1317 | Blob target; |
| 1436 | - rid = db_int(0, "SELECT trid, max(trev) FROM xhist" | |
| 1437 | - " WHERE trev<=%d AND tpath=%Q", gsvn.rev, zPath); | |
| 1318 | + rid = db_int(0, "SELECT rid FROM blob WHERE uuid=(" | |
| 1319 | + " SELECT uuid FROM xfiles" | |
| 1320 | + " WHERE tpath=%Q AND tbranch=%Q" | |
| 1321 | + ")", zFile, zBranch); | |
| 1438 | 1322 | content_get(rid, &deltaSrc); |
| 1439 | 1323 | svn_apply_svndiff(&rec.content, &deltaSrc, &target); |
| 1440 | 1324 | rid = content_put(&target); |
| 1441 | 1325 | }else{ |
| 1442 | 1326 | rid = content_put(&rec.content); |
| 1443 | 1327 | } |
| 1444 | - db_bind_int(&addHist, ":rid", rid); | |
| 1445 | - db_bind_text(&addHist, ":path", zPath); | |
| 1446 | - db_bind_text(&addHist, ":perm", zPerm); | |
| 1447 | - db_step(&addHist); | |
| 1448 | - db_reset(&addHist); | |
| 1449 | - bHasFiles = 1; | |
| 1328 | + db_bind_text(&addFile, ":path", zFile); | |
| 1329 | + db_bind_text(&addFile, ":branch", zBranch); | |
| 1330 | + db_bind_int(&addFile, ":rid", rid); | |
| 1331 | + db_bind_text(&addFile, ":perm", zPerm); | |
| 1332 | + db_step(&addFile); | |
| 1333 | + db_reset(&addFile); | |
| 1450 | 1334 | } |
| 1451 | 1335 | }else |
| 1452 | 1336 | if( strncmp(zAction, "delete", 6)!=0 ){ /* already did this one above */ |
| 1453 | 1337 | fossil_fatal("Unknown Node-action"); |
| 1454 | 1338 | } |
| @@ -1455,20 +1339,19 @@ | ||
| 1455 | 1339 | }else{ |
| 1456 | 1340 | fossil_fatal("Unknown record type"); |
| 1457 | 1341 | } |
| 1458 | 1342 | svn_free_rec(&rec); |
| 1459 | 1343 | } |
| 1460 | - if( bHasFiles ){ | |
| 1461 | - svn_create_manifest(); | |
| 1462 | - } | |
| 1344 | + svn_finish_revision(); | |
| 1463 | 1345 | fossil_free(gsvn.zUser); |
| 1464 | 1346 | fossil_free(gsvn.zComment); |
| 1465 | 1347 | fossil_free(gsvn.zDate); |
| 1466 | - db_finalize(&addHist); | |
| 1467 | - db_finalize(&insTag); | |
| 1468 | - db_finalize(&cpyPath); | |
| 1348 | + db_finalize(&addFile); | |
| 1469 | 1349 | db_finalize(&delPath); |
| 1350 | + db_finalize(&addSrc); | |
| 1351 | + db_finalize(&addBranch); | |
| 1352 | + db_finalize(&cpyPath); | |
| 1470 | 1353 | fossil_print(" Done!\n"); |
| 1471 | 1354 | } |
| 1472 | 1355 | |
| 1473 | 1356 | /* |
| 1474 | 1357 | ** COMMAND: import |
| @@ -1507,11 +1390,10 @@ | ||
| 1507 | 1390 | void import_cmd(void){ |
| 1508 | 1391 | char *zPassword; |
| 1509 | 1392 | FILE *pIn; |
| 1510 | 1393 | Stmt q; |
| 1511 | 1394 | const char *zBase = find_option("base", 0, 1); |
| 1512 | - int lenFilter; | |
| 1513 | 1395 | int forceFlag = find_option("force", "f", 0)!=0; |
| 1514 | 1396 | int incrFlag = find_option("incremental", "i", 0)!=0; |
| 1515 | 1397 | gsvn.zTrunk = find_option("trunk", 0, 1); |
| 1516 | 1398 | gsvn.zBranches = find_option("branches", 0, 1); |
| 1517 | 1399 | gsvn.zTags = find_option("tags", 0, 1); |
| @@ -1574,29 +1456,27 @@ | ||
| 1574 | 1456 | db_finalize(&q); |
| 1575 | 1457 | }else |
| 1576 | 1458 | if( strncmp(g.argv[2], "svn", 3)==0 ){ |
| 1577 | 1459 | db_multi_exec( |
| 1578 | 1460 | "CREATE TEMP TABLE xrevisions(" |
| 1579 | - " trev INTEGER, tbranch TEXT, trid INT, PRIMARY KEY(tbranch, trev)" | |
| 1461 | + " tid INTEGER PRIMARY KEY, trev INTEGER, tbranch TEXT, ttype INT, trid INT," | |
| 1462 | + " UNIQUE(tbranch, ttype, trev)" | |
| 1580 | 1463 | ");" |
| 1581 | 1464 | "CREATE TEMP TABLE xfiles(" |
| 1582 | 1465 | " tpath TEXT, tbranch TEXT, tuuid TEXT, tperm TEXT," |
| 1583 | 1466 | " UNIQUE (tbranch, tpath) ON CONFLICT REPLACE" |
| 1584 | 1467 | ");" |
| 1585 | 1468 | "CREATE TEMP TABLE xsrc(" |
| 1586 | 1469 | " tpath TEXT, tbranch TEXT, tsrc TEXT, tsrcbranch TEXT, tsrcrev INT" |
| 1587 | 1470 | ");" |
| 1588 | - "CREATE TEMP TABLE xchanged(" | |
| 1589 | - " tbranch TEXT, ttype INT," | |
| 1590 | - " UNIQUE (tbranch) ON CONFLICT REPLACE" | |
| 1591 | - ");" | |
| 1592 | 1471 | "CREATE VIRTUAL TABLE temp.xfoci USING files_of_checkin;" |
| 1593 | 1472 | ); |
| 1594 | 1473 | if( zBase==0 ){ zBase = ""; } |
| 1595 | 1474 | if( strlen(zBase)>0 ){ |
| 1596 | 1475 | if( zBase[strlen(zBase)-1]!='/' ){ |
| 1597 | - zBase = mprintf("%s/", zBase); | |
| 1476 | + zBase = mprintf("%s/", zBase); | |
| 1477 | + } | |
| 1598 | 1478 | } |
| 1599 | 1479 | if( flatFlag ){ |
| 1600 | 1480 | gsvn.zTrunk = zBase; |
| 1601 | 1481 | gsvn.zBranches = 0; |
| 1602 | 1482 | gsvn.zTags = 0; |
| 1603 | 1483 |
| --- src/import.c | |
| +++ src/import.c | |
| @@ -718,129 +718,24 @@ | |
| 718 | fossil_fatal("bad fast-import line: [%s]", zLine); |
| 719 | return; |
| 720 | } |
| 721 | |
| 722 | static struct{ |
| 723 | char *zBranch; /* Name of a branch for a commit */ |
| 724 | char *zDate; /* Date/time stamp */ |
| 725 | char *zUser; /* User name */ |
| 726 | char *zComment; /* Comment of a commit */ |
| 727 | char *zFrom; /* from value as a UUID */ |
| 728 | int nMerge; /* Number of merge values */ |
| 729 | int nMergeAlloc; /* Number of slots in azMerge[] */ |
| 730 | char **azMerge; /* Merge values */ |
| 731 | int nFile; /* Number of aFile values */ |
| 732 | int nFileAlloc; /* Number of slots in aFile[] */ |
| 733 | ImportFile *aFile; /* Information about files in a commit */ |
| 734 | int fromLoaded; /* True zFrom content loaded into aFile[] */ |
| 735 | } gsvn; |
| 736 | |
| 737 | /* |
| 738 | ** Create a new entry in the gsvn.aFile[] array |
| 739 | */ |
| 740 | static ImportFile *svn_import_add_file(){ |
| 741 | ImportFile *pFile; |
| 742 | if( gsvn.nFile>=gsvn.nFileAlloc ){ |
| 743 | gsvn.nFileAlloc = gsvn.nFileAlloc*2 + 100; |
| 744 | gsvn.aFile = fossil_realloc(gsvn.aFile, gsvn.nFileAlloc*sizeof(gsvn.aFile[0])); |
| 745 | } |
| 746 | pFile = &gsvn.aFile[gsvn.nFile++]; |
| 747 | memset(pFile, 0, sizeof(*pFile)); |
| 748 | return pFile; |
| 749 | } |
| 750 | |
| 751 | /* |
| 752 | ** Load all file information out of the gsvn.zFrom check-in |
| 753 | */ |
| 754 | static void svn_import_prior_files(void){ |
| 755 | Manifest *p; |
| 756 | int rid; |
| 757 | ManifestFile *pOld; |
| 758 | ImportFile *pNew; |
| 759 | if( gsvn.fromLoaded ) return; |
| 760 | gsvn.fromLoaded = 1; |
| 761 | if( gsvn.zFrom==0 && gsvn.zPrevCheckin!=0 |
| 762 | && fossil_strcmp(gsvn.zBranch, gsvn.zPrevBranch)==0 |
| 763 | ){ |
| 764 | gsvn.zFrom = gsvn.zPrevCheckin; |
| 765 | gsvn.zPrevCheckin = 0; |
| 766 | } |
| 767 | if( gsvn.zFrom==0 ) return; |
| 768 | rid = fast_uuid_to_rid(gsvn.zFrom); |
| 769 | if( rid==0 ) return; |
| 770 | p = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 771 | if( p==0 ) return; |
| 772 | manifest_file_rewind(p); |
| 773 | while( (pOld = manifest_file_next(p, 0))!=0 ){ |
| 774 | pNew = import_add_file(); |
| 775 | pNew->zName = fossil_strdup(pOld->zName); |
| 776 | pNew->isExe = pOld->zPerm && strstr(pOld->zPerm, "x")!=0; |
| 777 | pNew->isLink = pOld->zPerm && strstr(pOld->zPerm, "l")!=0; |
| 778 | pNew->zUuid = fossil_strdup(pOld->zUuid); |
| 779 | pNew->isFrom = 1; |
| 780 | } |
| 781 | manifest_destroy(p); |
| 782 | } |
| 783 | |
| 784 | /* |
| 785 | ** Deallocate the state information. |
| 786 | ** |
| 787 | ** The azMerge[] and aFile[] arrays are zeroed but allocated space is |
| 788 | ** retained unless the freeAll flag is set. |
| 789 | */ |
| 790 | static void svn_import_reset(int freeAll){ |
| 791 | int i; |
| 792 | // gsvn.xFinish = 0; |
| 793 | // fossil_free(gsvn.zTag); gsvn.zTag = 0; |
| 794 | fossil_free(gsvn.zBranch); gsvn.zBranch = 0; |
| 795 | // fossil_free(gsvn.aData); gsvn.aData = 0; |
| 796 | // fossil_free(gsvn.zMark); gsvn.zMark = 0; |
| 797 | fossil_free(gsvn.zDate); gsvn.zDate = 0; |
| 798 | fossil_free(gsvn.zUser); gsvn.zUser = 0; |
| 799 | fossil_free(gsvn.zComment); gsvn.zComment = 0; |
| 800 | fossil_free(gsvn.zFrom); gsvn.zFrom = 0; |
| 801 | // fossil_free(gsvn.zFromMark); gsvn.zFromMark = 0; |
| 802 | for(i=0; i<gsvn.nMerge; i++){ |
| 803 | fossil_free(gsvn.azMerge[i]); gsvn.azMerge[i] = 0; |
| 804 | } |
| 805 | gsvn.nMerge = 0; |
| 806 | for(i=0; i<gsvn.nFile; i++){ |
| 807 | fossil_free(gsvn.aFile[i].zName); |
| 808 | fossil_free(gsvn.aFile[i].zUuid); |
| 809 | fossil_free(gsvn.aFile[i].zPrior); |
| 810 | } |
| 811 | memset(gsvn.aFile, 0, gsvn.nFile*sizeof(gsvn.aFile[0])); |
| 812 | gsvn.nFile = 0; |
| 813 | if( freeAll ){ |
| 814 | // fossil_free(gsvn.zPrevBranch); |
| 815 | // fossil_free(gsvn.zPrevCheckin); |
| 816 | fossil_free(gsvn.azMerge); |
| 817 | fossil_free(gsvn.aFile); |
| 818 | memset(&gsvn, 0, sizeof(gsvn)); |
| 819 | } |
| 820 | // gsvn.xFinish = finish_noop; |
| 821 | } |
| 822 | |
| 823 | static struct{ |
| 824 | int rev; /* SVN revision number */ |
| 825 | // int parentRev; /* SVN revision number of parent check-in */ |
| 826 | // char *zParentBranch; /* Name of branch of parent check-in */ |
| 827 | // char *zBranch; /* Name of a branch for a commit */ |
| 828 | char *zDate; /* Date/time stamp */ |
| 829 | char *zUser; /* User name */ |
| 830 | char *zComment; /* Comment of a commit */ |
| 831 | // int flatFlag; /* True if whole repo is a single file tree */ |
| 832 | const char *zTrunk; /* Name of trunk folder in repo root */ |
| 833 | int lenTrunk; /* String length of zTrunk */ |
| 834 | const char *zBranches; /* Name of branches folder in repo root */ |
| 835 | int lenBranches; /* String length of zBranches */ |
| 836 | const char *zTags; /* Name of tags folder in repo root */ |
| 837 | int lenTags; /* String length of zTags */ |
| 838 | } gsvn; |
| 839 | typedef struct { |
| 840 | char *zKey; |
| 841 | const char *zVal; |
| 842 | } KeyVal; |
| 843 | typedef struct { |
| 844 | KeyVal *aHeaders; |
| 845 | int nHeaders; |
| 846 | char *pRawProps; |
| @@ -852,11 +747,11 @@ | |
| 852 | |
| 853 | #define svn_find_header(rec, zHeader) \ |
| 854 | svn_find_keyval((rec).aHeaders, (rec).nHeaders, (zHeader)) |
| 855 | #define svn_find_prop(rec, zProp) \ |
| 856 | svn_find_keyval((rec).aProps, (rec).nProps, (zProp)) |
| 857 | static const char *svn_find_keyval( |
| 858 | KeyVal *aKeyVal, |
| 859 | int nKeyVal, |
| 860 | const char *zKey |
| 861 | ){ |
| 862 | int i; |
| @@ -1003,51 +898,24 @@ | |
| 1003 | rec->contentFlag = 0; |
| 1004 | } |
| 1005 | return 1; |
| 1006 | } |
| 1007 | |
| 1008 | static void svn_finish_revision( |
| 1009 | ){ |
| 1010 | Blob manifest; |
| 1011 | static Stmt insRev; |
| 1012 | static Stmt qParent; |
| 1013 | static Stmt qParent2; |
| 1014 | static Stmt qFiles; |
| 1015 | static Stmt qTags; |
| 1016 | int nBaseFilter; |
| 1017 | int nFilter; |
| 1018 | int rid; |
| 1019 | char *zParentBranch = 0; |
| 1020 | Blob mcksum; |
| 1021 | |
| 1022 | blob_zero(&manifest); |
| 1023 | nBaseFilter = blob_size(&gsvn.filter); |
| 1024 | if( !gsvn.flatFlag ){ |
| 1025 | if( gsvn.zBranch==0 ){ return; } |
| 1026 | if( strncmp(gsvn.zBranch, gsvn.zTrunk, gsvn.lenTrunk-1)==0 ){ |
| 1027 | blob_appendf(&gsvn.filter, "%s*", gsvn.zTrunk); |
| 1028 | }else{ |
| 1029 | blob_appendf(&gsvn.filter, "%s%s/*", gsvn.zBranches, gsvn.zBranch); |
| 1030 | } |
| 1031 | }else{ |
| 1032 | blob_append(&gsvn.filter, "*", 1); |
| 1033 | } |
| 1034 | if( db_int(0, "SELECT 1 FROM xhist WHERE trev=%d AND tpath GLOB %Q LIMIT 1", |
| 1035 | gsvn.rev, blob_str(&gsvn.filter))==0 |
| 1036 | ){ |
| 1037 | goto skip_revision; |
| 1038 | } |
| 1039 | db_static_prepare(&insRev, "REPLACE INTO xrevisions (trev, tbranch, tuuid) " |
| 1040 | "VALUES(:rev, :branch, " |
| 1041 | " (SELECT uuid FROM blob WHERE rid=:rid))"); |
| 1042 | db_static_prepare(&qParent, "SELECT tuuid, max(trev) FROM xrevisions " |
| 1043 | "WHERE trev<=:rev AND tbranch=:branch"); |
| 1044 | db_static_prepare(&qParent2, "SELECT tuuid, min(trev) " |
| 1045 | "FROM xrevisions WHERE tbranch=:branch"); |
| 1046 | db_static_prepare(&qFiles, "SELECT tpath, trid, tperm FROM xfiles " |
| 1047 | "WHERE tpath GLOB :filter ORDER BY tpath"); |
| 1048 | db_static_prepare(&qTags, "SELECT ttag FROM xtags WHERE trev=:rev"); |
| 1049 | if( !gsvn.flatFlag ){ |
| 1050 | if( gsvn.parentRev<0 ){ |
| 1051 | gsvn.parentRev = db_int(-1, "SELECT ifnull(max(trev),-1) FROM xrevisions " |
| 1052 | "WHERE tbranch=%Q", gsvn.zBranch); |
| 1053 | if( gsvn.parentRev<0 ){ |
| @@ -1216,14 +1084,26 @@ | |
| 1216 | ** Returns: 1 - It is on the trunk |
| 1217 | ** 2 - It is on a branch |
| 1218 | ** 3 - It is a tag |
| 1219 | ** 0 - It is none of the above |
| 1220 | */ |
| 1221 | static int *svn_parse_path(char *zPath, char **zBranch, char **zFile){ |
| 1222 | if( strncmp(zPath, gsvn.zTrunk, gsvn.lenTrunk)==0 ){ |
| 1223 | *zBranch = "trunk"; |
| 1224 | *zFile = zPath+gsvn.lenTrunk; |
| 1225 | return 1; |
| 1226 | }else |
| 1227 | if( strncmp(zPath, gsvn.zBranches, gsvn.lenBranches)==0 ){ |
| 1228 | *zFile = *zBranch = zPath+gsvn.lenBranches; |
| 1229 | while( **zFile && **zFile!='/' ){ (*zFile)++; } |
| @@ -1283,11 +1163,11 @@ | |
| 1283 | svn_free_rec(&rec); |
| 1284 | |
| 1285 | /* content */ |
| 1286 | db_prepare(&addFile, |
| 1287 | "INSERT INTO xfiles (tpath, tbranch, tuuid, tperm)" |
| 1288 | " VALUES(:path, :branch, :uuid, :perm)" |
| 1289 | ); |
| 1290 | db_prepare(&delPath, |
| 1291 | "DELETE FROM xfiles" |
| 1292 | " WHERE (tpath=:path OR (tpath>:path||'/' AND tpath<:path||'0'))" |
| 1293 | " AND tbranch=:branch" |
| @@ -1307,11 +1187,11 @@ | |
| 1307 | ); |
| 1308 | gsvn.rev = -1; |
| 1309 | while( svn_read_rec(pIn, &rec) ){ |
| 1310 | if( (zTemp = svn_find_header(rec, "Revision-number")) ){ /* revision node */ |
| 1311 | /* finish previous revision */ |
| 1312 | const char *zDate = NULL; |
| 1313 | if( gsvn.rev>=0 ){ |
| 1314 | svn_finish_revision(); |
| 1315 | fossil_free(gsvn.zUser); |
| 1316 | fossil_free(gsvn.zComment); |
| 1317 | fossil_free(gsvn.zDate); |
| @@ -1326,14 +1206,14 @@ | |
| 1326 | } |
| 1327 | gsvn.zDate = zDate; |
| 1328 | fossil_print("\rImporting SVN revision: %d", gsvn.rev); |
| 1329 | }else |
| 1330 | if( (zTemp = svn_find_header(rec, "Node-path")) ){ /* file/dir node */ |
| 1331 | const char *zAction = svn_find_header(rec, "Node-action"); |
| 1332 | const char *zKind = svn_find_header(rec, "Node-kind"); |
| 1333 | const char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path"); |
| 1334 | const char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0; |
| 1335 | char *zBranch; |
| 1336 | char *zFile; |
| 1337 | char *zSrcBranch; |
| 1338 | char *zSrcFile; |
| 1339 | int deltaFlag = 0; |
| @@ -1355,11 +1235,11 @@ | |
| 1355 | if( zTemp ){ |
| 1356 | srcRev = atoi(zTemp); |
| 1357 | }else{ |
| 1358 | fossil_fatal("Missing copyfrom-rev"); |
| 1359 | } |
| 1360 | if( svn_extract_branch(zSrcPath, &zSrcBranch, &zSrcFile)==0 ){ |
| 1361 | fossil_fatal("Copy from path outside the import paths"); |
| 1362 | } |
| 1363 | db_bind_text(&addSrc, ":path", zFile); |
| 1364 | db_bind_text(&addSrc, ":branch", zBranch); |
| 1365 | db_bind_text(&addSrc, ":srcpath", zSrcFile); |
| @@ -1397,13 +1277,15 @@ | |
| 1397 | int rid = 0; |
| 1398 | if( zSrcPath ){ |
| 1399 | int srcRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions" |
| 1400 | " WHERE trev<=%d AND tbranch=%Q", |
| 1401 | srcRev, zSrcBranch); |
| 1402 | rid = db_int(0, "SELECT rid FROM xfoci" |
| 1403 | " WHERE chekinID=%d AND filename=%Q", |
| 1404 | srcRid, zSrcFile) |
| 1405 | } |
| 1406 | if( deltaFlag ){ |
| 1407 | Blob deltaSrc; |
| 1408 | Blob target; |
| 1409 | if( rid!=0 ){ |
| @@ -1414,16 +1296,16 @@ | |
| 1414 | svn_apply_svndiff(&rec.content, &deltaSrc, &target); |
| 1415 | rid = content_put(&target); |
| 1416 | }else if( rec.contentFlag ){ |
| 1417 | rid = content_put(&rec.content); |
| 1418 | } |
| 1419 | db_bind_int(&addHist, ":rid", rid); |
| 1420 | db_bind_text(&addHist, ":path", zPath); |
| 1421 | db_bind_text(&addHist, ":perm", zPerm); |
| 1422 | db_step(&addHist); |
| 1423 | db_reset(&addHist); |
| 1424 | bHasFiles = 1; |
| 1425 | } |
| 1426 | }else |
| 1427 | if( strncmp(zAction, "change", 6)==0 ){ |
| 1428 | int rid = 0; |
| 1429 | if( zKind==0 ){ |
| @@ -1431,24 +1313,26 @@ | |
| 1431 | } |
| 1432 | if( strncmp(zKind, "dir", 3)!=0 ){ |
| 1433 | if( deltaFlag ){ |
| 1434 | Blob deltaSrc; |
| 1435 | Blob target; |
| 1436 | rid = db_int(0, "SELECT trid, max(trev) FROM xhist" |
| 1437 | " WHERE trev<=%d AND tpath=%Q", gsvn.rev, zPath); |
| 1438 | content_get(rid, &deltaSrc); |
| 1439 | svn_apply_svndiff(&rec.content, &deltaSrc, &target); |
| 1440 | rid = content_put(&target); |
| 1441 | }else{ |
| 1442 | rid = content_put(&rec.content); |
| 1443 | } |
| 1444 | db_bind_int(&addHist, ":rid", rid); |
| 1445 | db_bind_text(&addHist, ":path", zPath); |
| 1446 | db_bind_text(&addHist, ":perm", zPerm); |
| 1447 | db_step(&addHist); |
| 1448 | db_reset(&addHist); |
| 1449 | bHasFiles = 1; |
| 1450 | } |
| 1451 | }else |
| 1452 | if( strncmp(zAction, "delete", 6)!=0 ){ /* already did this one above */ |
| 1453 | fossil_fatal("Unknown Node-action"); |
| 1454 | } |
| @@ -1455,20 +1339,19 @@ | |
| 1455 | }else{ |
| 1456 | fossil_fatal("Unknown record type"); |
| 1457 | } |
| 1458 | svn_free_rec(&rec); |
| 1459 | } |
| 1460 | if( bHasFiles ){ |
| 1461 | svn_create_manifest(); |
| 1462 | } |
| 1463 | fossil_free(gsvn.zUser); |
| 1464 | fossil_free(gsvn.zComment); |
| 1465 | fossil_free(gsvn.zDate); |
| 1466 | db_finalize(&addHist); |
| 1467 | db_finalize(&insTag); |
| 1468 | db_finalize(&cpyPath); |
| 1469 | db_finalize(&delPath); |
| 1470 | fossil_print(" Done!\n"); |
| 1471 | } |
| 1472 | |
| 1473 | /* |
| 1474 | ** COMMAND: import |
| @@ -1507,11 +1390,10 @@ | |
| 1507 | void import_cmd(void){ |
| 1508 | char *zPassword; |
| 1509 | FILE *pIn; |
| 1510 | Stmt q; |
| 1511 | const char *zBase = find_option("base", 0, 1); |
| 1512 | int lenFilter; |
| 1513 | int forceFlag = find_option("force", "f", 0)!=0; |
| 1514 | int incrFlag = find_option("incremental", "i", 0)!=0; |
| 1515 | gsvn.zTrunk = find_option("trunk", 0, 1); |
| 1516 | gsvn.zBranches = find_option("branches", 0, 1); |
| 1517 | gsvn.zTags = find_option("tags", 0, 1); |
| @@ -1574,29 +1456,27 @@ | |
| 1574 | db_finalize(&q); |
| 1575 | }else |
| 1576 | if( strncmp(g.argv[2], "svn", 3)==0 ){ |
| 1577 | db_multi_exec( |
| 1578 | "CREATE TEMP TABLE xrevisions(" |
| 1579 | " trev INTEGER, tbranch TEXT, trid INT, PRIMARY KEY(tbranch, trev)" |
| 1580 | ");" |
| 1581 | "CREATE TEMP TABLE xfiles(" |
| 1582 | " tpath TEXT, tbranch TEXT, tuuid TEXT, tperm TEXT," |
| 1583 | " UNIQUE (tbranch, tpath) ON CONFLICT REPLACE" |
| 1584 | ");" |
| 1585 | "CREATE TEMP TABLE xsrc(" |
| 1586 | " tpath TEXT, tbranch TEXT, tsrc TEXT, tsrcbranch TEXT, tsrcrev INT" |
| 1587 | ");" |
| 1588 | "CREATE TEMP TABLE xchanged(" |
| 1589 | " tbranch TEXT, ttype INT," |
| 1590 | " UNIQUE (tbranch) ON CONFLICT REPLACE" |
| 1591 | ");" |
| 1592 | "CREATE VIRTUAL TABLE temp.xfoci USING files_of_checkin;" |
| 1593 | ); |
| 1594 | if( zBase==0 ){ zBase = ""; } |
| 1595 | if( strlen(zBase)>0 ){ |
| 1596 | if( zBase[strlen(zBase)-1]!='/' ){ |
| 1597 | zBase = mprintf("%s/", zBase); |
| 1598 | } |
| 1599 | if( flatFlag ){ |
| 1600 | gsvn.zTrunk = zBase; |
| 1601 | gsvn.zBranches = 0; |
| 1602 | gsvn.zTags = 0; |
| 1603 |
| --- src/import.c | |
| +++ src/import.c | |
| @@ -718,129 +718,24 @@ | |
| 718 | fossil_fatal("bad fast-import line: [%s]", zLine); |
| 719 | return; |
| 720 | } |
| 721 | |
| 722 | static struct{ |
| 723 | int rev; /* SVN revision number */ |
| 724 | char *zDate; /* Date/time stamp */ |
| 725 | char *zUser; /* User name */ |
| 726 | char *zComment; /* Comment of a commit */ |
| 727 | const char *zTrunk; /* Name of trunk folder in repo root */ |
| 728 | int lenTrunk; /* String length of zTrunk */ |
| 729 | const char *zBranches; /* Name of branches folder in repo root */ |
| 730 | int lenBranches; /* String length of zBranches */ |
| 731 | const char *zTags; /* Name of tags folder in repo root */ |
| 732 | int lenTags; /* String length of zTags */ |
| 733 | } gsvn; |
| 734 | typedef struct { |
| 735 | char *zKey; |
| 736 | char *zVal; |
| 737 | } KeyVal; |
| 738 | typedef struct { |
| 739 | KeyVal *aHeaders; |
| 740 | int nHeaders; |
| 741 | char *pRawProps; |
| @@ -852,11 +747,11 @@ | |
| 747 | |
| 748 | #define svn_find_header(rec, zHeader) \ |
| 749 | svn_find_keyval((rec).aHeaders, (rec).nHeaders, (zHeader)) |
| 750 | #define svn_find_prop(rec, zProp) \ |
| 751 | svn_find_keyval((rec).aProps, (rec).nProps, (zProp)) |
| 752 | static char *svn_find_keyval( |
| 753 | KeyVal *aKeyVal, |
| 754 | int nKeyVal, |
| 755 | const char *zKey |
| 756 | ){ |
| 757 | int i; |
| @@ -1003,51 +898,24 @@ | |
| 898 | rec->contentFlag = 0; |
| 899 | } |
| 900 | return 1; |
| 901 | } |
| 902 | |
| 903 | static void svn_finish_revision(){ |
| 904 | Blob manifest; |
| 905 | static Stmt insRev; |
| 906 | Blob mcksum; |
| 907 | |
| 908 | blob_zero(&manifest); |
| 909 | db_static_prepare(&getChanges, "SELECT tbranch, ttype FROM xchanged"); |
| 910 | db_static_prepare(&getFiles, "SELECT tpath, tuuid, tperm," |
| 911 | " tsrc, tsrcbranch, trev tsrcrev" |
| 912 | " FROM xfiles, xsrc" |
| 913 | " ON tpath, tbranch)" |
| 914 | " WHERE tbranch=:branch ORDER BY tpath"); |
| 915 | db_static_prepare(&setRid, "REPLACE INTO xrevisions(trev, tbranch, trid)" |
| 916 | " VALUES (%d, :branch, :rid)", gsvn.rev); |
| 917 | if( !gsvn.flatFlag ){ |
| 918 | if( gsvn.parentRev<0 ){ |
| 919 | gsvn.parentRev = db_int(-1, "SELECT ifnull(max(trev),-1) FROM xrevisions " |
| 920 | "WHERE tbranch=%Q", gsvn.zBranch); |
| 921 | if( gsvn.parentRev<0 ){ |
| @@ -1216,14 +1084,26 @@ | |
| 1084 | ** Returns: 1 - It is on the trunk |
| 1085 | ** 2 - It is on a branch |
| 1086 | ** 3 - It is a tag |
| 1087 | ** 0 - It is none of the above |
| 1088 | */ |
| 1089 | static int svn_parse_path(char *zPath, char **zBranch, char **zFile){ |
| 1090 | if( gsvn.lenTrunk==0 ){ |
| 1091 | *zBranch = "trunk"; |
| 1092 | *zFile = zPath; |
| 1093 | return 1; |
| 1094 | }else |
| 1095 | if( strncmp(zPath, gsvn.zTrunk, gsvn.lenTrunk-1)==0 ){ |
| 1096 | *zBranch = "trunk"; |
| 1097 | if( zPath[gsvn.lenTrunk-1]=='/' ){ |
| 1098 | *zFile = zPath+gsvn.lenTrunk;; |
| 1099 | }else if( zPath[gsvn.lenTrunk-1]==0 ){ |
| 1100 | *zFile = 0; |
| 1101 | }else{ |
| 1102 | *zFile = *zBranch = 0; |
| 1103 | return 0; |
| 1104 | } |
| 1105 | return 1; |
| 1106 | }else |
| 1107 | if( strncmp(zPath, gsvn.zBranches, gsvn.lenBranches)==0 ){ |
| 1108 | *zFile = *zBranch = zPath+gsvn.lenBranches; |
| 1109 | while( **zFile && **zFile!='/' ){ (*zFile)++; } |
| @@ -1283,11 +1163,11 @@ | |
| 1163 | svn_free_rec(&rec); |
| 1164 | |
| 1165 | /* content */ |
| 1166 | db_prepare(&addFile, |
| 1167 | "INSERT INTO xfiles (tpath, tbranch, tuuid, tperm)" |
| 1168 | " VALUES(:path, :branch, (SELECT uuid FROM blob WHERE rid=:rid), :perm)" |
| 1169 | ); |
| 1170 | db_prepare(&delPath, |
| 1171 | "DELETE FROM xfiles" |
| 1172 | " WHERE (tpath=:path OR (tpath>:path||'/' AND tpath<:path||'0'))" |
| 1173 | " AND tbranch=:branch" |
| @@ -1307,11 +1187,11 @@ | |
| 1187 | ); |
| 1188 | gsvn.rev = -1; |
| 1189 | while( svn_read_rec(pIn, &rec) ){ |
| 1190 | if( (zTemp = svn_find_header(rec, "Revision-number")) ){ /* revision node */ |
| 1191 | /* finish previous revision */ |
| 1192 | char *zDate = NULL; |
| 1193 | if( gsvn.rev>=0 ){ |
| 1194 | svn_finish_revision(); |
| 1195 | fossil_free(gsvn.zUser); |
| 1196 | fossil_free(gsvn.zComment); |
| 1197 | fossil_free(gsvn.zDate); |
| @@ -1326,14 +1206,14 @@ | |
| 1206 | } |
| 1207 | gsvn.zDate = zDate; |
| 1208 | fossil_print("\rImporting SVN revision: %d", gsvn.rev); |
| 1209 | }else |
| 1210 | if( (zTemp = svn_find_header(rec, "Node-path")) ){ /* file/dir node */ |
| 1211 | char *zAction = svn_find_header(rec, "Node-action"); |
| 1212 | char *zKind = svn_find_header(rec, "Node-kind"); |
| 1213 | char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path"); |
| 1214 | char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0; |
| 1215 | char *zBranch; |
| 1216 | char *zFile; |
| 1217 | char *zSrcBranch; |
| 1218 | char *zSrcFile; |
| 1219 | int deltaFlag = 0; |
| @@ -1355,11 +1235,11 @@ | |
| 1235 | if( zTemp ){ |
| 1236 | srcRev = atoi(zTemp); |
| 1237 | }else{ |
| 1238 | fossil_fatal("Missing copyfrom-rev"); |
| 1239 | } |
| 1240 | if( svn_parse_path(zSrcPath, &zSrcBranch, &zSrcFile)==0 ){ |
| 1241 | fossil_fatal("Copy from path outside the import paths"); |
| 1242 | } |
| 1243 | db_bind_text(&addSrc, ":path", zFile); |
| 1244 | db_bind_text(&addSrc, ":branch", zBranch); |
| 1245 | db_bind_text(&addSrc, ":srcpath", zSrcFile); |
| @@ -1397,13 +1277,15 @@ | |
| 1277 | int rid = 0; |
| 1278 | if( zSrcPath ){ |
| 1279 | int srcRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions" |
| 1280 | " WHERE trev<=%d AND tbranch=%Q", |
| 1281 | srcRev, zSrcBranch); |
| 1282 | rid = db_int(0, "SELECT rid FROM blob WHERE uuid=(" |
| 1283 | " SELECT uuid FROM xfoci" |
| 1284 | " WHERE chekinID=%d AND filename=%Q" |
| 1285 | ")", |
| 1286 | srcRid, zSrcFile); |
| 1287 | } |
| 1288 | if( deltaFlag ){ |
| 1289 | Blob deltaSrc; |
| 1290 | Blob target; |
| 1291 | if( rid!=0 ){ |
| @@ -1414,16 +1296,16 @@ | |
| 1296 | svn_apply_svndiff(&rec.content, &deltaSrc, &target); |
| 1297 | rid = content_put(&target); |
| 1298 | }else if( rec.contentFlag ){ |
| 1299 | rid = content_put(&rec.content); |
| 1300 | } |
| 1301 | db_bind_text(&addFile, ":path", zFile); |
| 1302 | db_bind_text(&addFile, ":branch", zBranch); |
| 1303 | db_bind_int(&addFile, ":rid", rid); |
| 1304 | db_bind_text(&addFile, ":perm", zPerm); |
| 1305 | db_step(&addFile); |
| 1306 | db_reset(&addFile); |
| 1307 | } |
| 1308 | }else |
| 1309 | if( strncmp(zAction, "change", 6)==0 ){ |
| 1310 | int rid = 0; |
| 1311 | if( zKind==0 ){ |
| @@ -1431,24 +1313,26 @@ | |
| 1313 | } |
| 1314 | if( strncmp(zKind, "dir", 3)!=0 ){ |
| 1315 | if( deltaFlag ){ |
| 1316 | Blob deltaSrc; |
| 1317 | Blob target; |
| 1318 | rid = db_int(0, "SELECT rid FROM blob WHERE uuid=(" |
| 1319 | " SELECT uuid FROM xfiles" |
| 1320 | " WHERE tpath=%Q AND tbranch=%Q" |
| 1321 | ")", zFile, zBranch); |
| 1322 | content_get(rid, &deltaSrc); |
| 1323 | svn_apply_svndiff(&rec.content, &deltaSrc, &target); |
| 1324 | rid = content_put(&target); |
| 1325 | }else{ |
| 1326 | rid = content_put(&rec.content); |
| 1327 | } |
| 1328 | db_bind_text(&addFile, ":path", zFile); |
| 1329 | db_bind_text(&addFile, ":branch", zBranch); |
| 1330 | db_bind_int(&addFile, ":rid", rid); |
| 1331 | db_bind_text(&addFile, ":perm", zPerm); |
| 1332 | db_step(&addFile); |
| 1333 | db_reset(&addFile); |
| 1334 | } |
| 1335 | }else |
| 1336 | if( strncmp(zAction, "delete", 6)!=0 ){ /* already did this one above */ |
| 1337 | fossil_fatal("Unknown Node-action"); |
| 1338 | } |
| @@ -1455,20 +1339,19 @@ | |
| 1339 | }else{ |
| 1340 | fossil_fatal("Unknown record type"); |
| 1341 | } |
| 1342 | svn_free_rec(&rec); |
| 1343 | } |
| 1344 | svn_finish_revision(); |
| 1345 | fossil_free(gsvn.zUser); |
| 1346 | fossil_free(gsvn.zComment); |
| 1347 | fossil_free(gsvn.zDate); |
| 1348 | db_finalize(&addFile); |
| 1349 | db_finalize(&delPath); |
| 1350 | db_finalize(&addSrc); |
| 1351 | db_finalize(&addBranch); |
| 1352 | db_finalize(&cpyPath); |
| 1353 | fossil_print(" Done!\n"); |
| 1354 | } |
| 1355 | |
| 1356 | /* |
| 1357 | ** COMMAND: import |
| @@ -1507,11 +1390,10 @@ | |
| 1390 | void import_cmd(void){ |
| 1391 | char *zPassword; |
| 1392 | FILE *pIn; |
| 1393 | Stmt q; |
| 1394 | const char *zBase = find_option("base", 0, 1); |
| 1395 | int forceFlag = find_option("force", "f", 0)!=0; |
| 1396 | int incrFlag = find_option("incremental", "i", 0)!=0; |
| 1397 | gsvn.zTrunk = find_option("trunk", 0, 1); |
| 1398 | gsvn.zBranches = find_option("branches", 0, 1); |
| 1399 | gsvn.zTags = find_option("tags", 0, 1); |
| @@ -1574,29 +1456,27 @@ | |
| 1456 | db_finalize(&q); |
| 1457 | }else |
| 1458 | if( strncmp(g.argv[2], "svn", 3)==0 ){ |
| 1459 | db_multi_exec( |
| 1460 | "CREATE TEMP TABLE xrevisions(" |
| 1461 | " tid INTEGER PRIMARY KEY, trev INTEGER, tbranch TEXT, ttype INT, trid INT," |
| 1462 | " UNIQUE(tbranch, ttype, trev)" |
| 1463 | ");" |
| 1464 | "CREATE TEMP TABLE xfiles(" |
| 1465 | " tpath TEXT, tbranch TEXT, tuuid TEXT, tperm TEXT," |
| 1466 | " UNIQUE (tbranch, tpath) ON CONFLICT REPLACE" |
| 1467 | ");" |
| 1468 | "CREATE TEMP TABLE xsrc(" |
| 1469 | " tpath TEXT, tbranch TEXT, tsrc TEXT, tsrcbranch TEXT, tsrcrev INT" |
| 1470 | ");" |
| 1471 | "CREATE VIRTUAL TABLE temp.xfoci USING files_of_checkin;" |
| 1472 | ); |
| 1473 | if( zBase==0 ){ zBase = ""; } |
| 1474 | if( strlen(zBase)>0 ){ |
| 1475 | if( zBase[strlen(zBase)-1]!='/' ){ |
| 1476 | zBase = mprintf("%s/", zBase); |
| 1477 | } |
| 1478 | } |
| 1479 | if( flatFlag ){ |
| 1480 | gsvn.zTrunk = zBase; |
| 1481 | gsvn.zBranches = 0; |
| 1482 | gsvn.zTags = 0; |
| 1483 |