Fossil SCM
import branches
Commit
c95c183e7be7dbe812b391ac32dd6552b9b4263f
Parent
8d2e67512d58518…
1 file changed
+120
-18
+120
-18
| --- src/import.c | ||
| +++ src/import.c | ||
| @@ -877,28 +877,64 @@ | ||
| 877 | 877 | ); |
| 878 | 878 | } |
| 879 | 879 | return 1; |
| 880 | 880 | } |
| 881 | 881 | |
| 882 | -static void svn_create_manifests(){ | |
| 882 | +static void svn_create_manifests(int flatFlag){ | |
| 883 | 883 | Blob manifest; |
| 884 | 884 | Stmt qRev; |
| 885 | + Stmt qParent; | |
| 885 | 886 | Stmt qFiles; |
| 886 | - int parentRid = 0; | |
| 887 | + Stmt setUuid; | |
| 887 | 888 | |
| 888 | - blob_zero(&manifest); | |
| 889 | - db_prepare(&qRev, "SELECT trev, tuser, tmsg, ttime FROM xrevisions" | |
| 889 | + if( !flatFlag ){ | |
| 890 | + db_multi_exec("DELETE FROM xrevisions WHERE tbranch ISNULL;" | |
| 891 | + "" | |
| 892 | + " WITH xprefix AS ( " | |
| 893 | + " SELECT trev, CASE tbranch WHEN 'trunk' THEN 'trunk/'" | |
| 894 | + " ELSE 'branches/'||tbranch||'/' END xpref" | |
| 895 | + " FROM xrevisions" | |
| 896 | + " ), " | |
| 897 | + " x AS (SELECT trev xrev, xpref, length(xpref) xlen " | |
| 898 | + " FROM xprefix) " | |
| 899 | + "UPDATE xfiles SET tpath= " | |
| 900 | + " CASE substr(tpath,1,(SELECT xlen FROM x WHERE xrev=trev))" | |
| 901 | + " WHEN (SELECT xpref FROM x WHERE xrev=trev)" | |
| 902 | + " THEN substr(tpath,(SELECT xlen FROM x WHERE xrev=trev)+1)" | |
| 903 | + " END;" | |
| 904 | + "DELETE FROM xfiles WHERE tpath ISNULL;" | |
| 905 | + "UPDATE xrevisions SET tparent=(" | |
| 906 | + " SELECT ifnull(max(trev),-1) FROM xrevisions t" | |
| 907 | + " WHERE t.trev<xrevisions.trev" | |
| 908 | + " AND t.tbranch=xrevisions.tbranch" | |
| 909 | + " )" | |
| 910 | + " WHERE tparent ISNULL"); | |
| 911 | + }else{ | |
| 912 | + db_multi_exec("UPDATE xrevisions SET tparent=trev-1"); | |
| 913 | + } | |
| 914 | + db_prepare(&qRev, "SELECT trev, tuser, tmsg, ttime, tparent, tbranch" | |
| 915 | + " FROM xrevisions " | |
| 890 | 916 | " ORDER BY trev"); |
| 917 | + db_prepare(&qParent, "SELECT tuuid, tbranch FROM xrevisions WHERE trev=:rev"); | |
| 891 | 918 | db_prepare(&qFiles, "SELECT tpath, uuid, tperm" |
| 892 | 919 | " FROM xfiles JOIN blob ON xfiles.trid=blob.rid" |
| 893 | 920 | " WHERE trev=:rev ORDER BY tpath"); |
| 921 | + db_prepare(&setUuid, "UPDATE xrevisions" | |
| 922 | + " SET tuuid=(SELECT uuid FROM blob WHERE rid=:rid)" | |
| 923 | + " WHERE trev=:rev"); | |
| 924 | + blob_zero(&manifest); | |
| 894 | 925 | while( db_step(&qRev)==SQLITE_ROW ){ |
| 895 | 926 | int rev = db_column_int(&qRev, 0); |
| 896 | 927 | const char *zUser = db_column_text(&qRev, 1); |
| 897 | 928 | const char *zMsg = db_column_text(&qRev, 2); |
| 898 | 929 | const char *zTime = db_column_text(&qRev, 3); |
| 930 | + int parentRev = db_column_int(&qRev, 4); | |
| 931 | + const char *zBranch = db_column_text(&qRev, 5); | |
| 932 | + int rid; | |
| 899 | 933 | Blob mcksum; |
| 934 | + const char *zParentUuid = 0; | |
| 935 | + const char *zParentBranch = 0; | |
| 900 | 936 | blob_reset(&manifest); |
| 901 | 937 | if( zMsg ){ |
| 902 | 938 | blob_appendf(&manifest, "C %F\n", zMsg); |
| 903 | 939 | }else{ |
| 904 | 940 | blob_append(&manifest, "C (no\\scomment)\n", 16); |
| @@ -910,20 +946,28 @@ | ||
| 910 | 946 | const char *zUuid = db_column_text(&qFiles, 1); |
| 911 | 947 | const char *zPerm = db_column_text(&qFiles, 2); |
| 912 | 948 | blob_appendf(&manifest, "F %F %s %s\n", zFile, zUuid, zPerm); |
| 913 | 949 | } |
| 914 | 950 | db_reset(&qFiles); |
| 915 | - if( parentRid>0 ){ | |
| 916 | - const char *zParent; | |
| 917 | - zParent = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", parentRid); | |
| 918 | - blob_appendf(&manifest, "P %s\n", zParent); | |
| 919 | - fossil_free(zParent); | |
| 951 | + if( parentRev>=0 ){ | |
| 952 | + db_bind_int(&qParent, ":rev", parentRev); | |
| 953 | + db_step(&qParent); | |
| 954 | + zParentUuid = db_column_text(&qParent, 0); | |
| 955 | + blob_appendf(&manifest, "P %s\n", zParentUuid); | |
| 956 | + if( !flatFlag ){ | |
| 957 | + zParentBranch = db_column_text(&qParent, 1); | |
| 958 | + if( strcmp(zBranch, zParentBranch)!=0 ){ | |
| 959 | + blob_appendf(&manifest, "T *branch * %s\n", zBranch); | |
| 960 | + blob_appendf(&manifest, "T *sym-%s *\n", zBranch); | |
| 961 | + } | |
| 962 | + } | |
| 963 | + db_reset(&qParent); | |
| 920 | 964 | }else{ |
| 921 | - blob_appendf(&manifest, "R d41d8cd98f00b204e9800998ecf8427e\n"); | |
| 922 | 965 | blob_appendf(&manifest, "T *branch * trunk\n"); |
| 923 | 966 | blob_appendf(&manifest, "T *sym-trunk *\n"); |
| 924 | 967 | } |
| 968 | + blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", rev); | |
| 925 | 969 | if( zUser ){ |
| 926 | 970 | blob_appendf(&manifest, "U %F\n", zUser); |
| 927 | 971 | }else{ |
| 928 | 972 | const char *zUserOvrd = find_option("user-override",0,1); |
| 929 | 973 | blob_appendf(&manifest, "U %F\n", |
| @@ -931,27 +975,36 @@ | ||
| 931 | 975 | } |
| 932 | 976 | md5sum_blob(&manifest, &mcksum); |
| 933 | 977 | blob_appendf(&manifest, "Z %b\n", &mcksum); |
| 934 | 978 | blob_reset(&mcksum); |
| 935 | 979 | |
| 936 | - parentRid = content_put(&manifest); | |
| 980 | + rid = content_put(&manifest); | |
| 981 | + db_bind_int(&setUuid, ":rid", rid); | |
| 982 | + db_bind_int(&setUuid, ":rev", rev); | |
| 983 | + db_step(&setUuid); | |
| 984 | + db_reset(&setUuid); | |
| 937 | 985 | } |
| 938 | 986 | db_finalize(&qRev); |
| 987 | + db_finalize(&qParent); | |
| 939 | 988 | db_finalize(&qFiles); |
| 989 | + db_finalize(&setUuid); | |
| 940 | 990 | } |
| 941 | 991 | /* |
| 942 | 992 | ** Read the svn-dump format from pIn and insert the corresponding |
| 943 | 993 | ** content into the database. |
| 944 | 994 | */ |
| 945 | -static void svn_dump_import(FILE *pIn){ | |
| 995 | +static void svn_dump_import(FILE *pIn, int flatFlag){ | |
| 946 | 996 | SvnRecord rec; |
| 947 | 997 | int ver; |
| 948 | 998 | const char *zTemp; |
| 949 | 999 | const char *zUuid; |
| 1000 | + char zBranch[200] = {0}; | |
| 950 | 1001 | Stmt insRev; |
| 951 | 1002 | Stmt insFile; |
| 952 | 1003 | Stmt delFile; |
| 1004 | + Stmt setBranch; | |
| 1005 | + Stmt setParent; | |
| 953 | 1006 | int rev = 0; |
| 954 | 1007 | |
| 955 | 1008 | /* version */ |
| 956 | 1009 | if( svn_read_rec(pIn, &rec) |
| 957 | 1010 | && (zTemp = svn_find_header(rec, "SVN-fs-dump-format-version")) ){ |
| @@ -979,16 +1032,33 @@ | ||
| 979 | 1032 | ); |
| 980 | 1033 | db_prepare(&delFile, |
| 981 | 1034 | "DELETE FROM xfiles " |
| 982 | 1035 | "WHERE trev=:rev " |
| 983 | 1036 | " AND (tpath=:path OR (tpath>:path||'/' AND tpath<:path||'0'))" |
| 1037 | + ); | |
| 1038 | + db_prepare(&setBranch, | |
| 1039 | + "UPDATE xrevisions SET tbranch=:branch " | |
| 1040 | + "WHERE trev=:rev" | |
| 1041 | + ); | |
| 1042 | + db_prepare(&setParent, | |
| 1043 | + "UPDATE xrevisions SET tparent=:parent " | |
| 1044 | + "WHERE trev=:rev" | |
| 984 | 1045 | ); |
| 985 | 1046 | while( svn_read_rec(pIn, &rec) ){ |
| 986 | 1047 | if( zTemp = svn_find_header(rec, "Revision-number") ){ |
| 987 | 1048 | const char *zUser = svn_find_prop(rec, "svn:author"); |
| 988 | 1049 | const char *zLog = svn_find_prop(rec, "svn:log"); |
| 989 | 1050 | const char *zDate = svn_find_prop(rec, "svn:date"); |
| 1051 | + if( !flatFlag ){ | |
| 1052 | + if( *zBranch ){ | |
| 1053 | + db_bind_text(&setBranch, ":branch", zBranch); | |
| 1054 | + db_bind_int(&setBranch, ":rev", rev); | |
| 1055 | + db_step(&setBranch); | |
| 1056 | + db_reset(&setBranch); | |
| 1057 | + zBranch[0] = 0; | |
| 1058 | + } | |
| 1059 | + } | |
| 990 | 1060 | zDate = date_in_standard_format(zDate); |
| 991 | 1061 | rev = atoi(zTemp); |
| 992 | 1062 | db_bind_int(&insRev, ":rev", rev); |
| 993 | 1063 | db_bind_text(&insRev, ":user", zUser); |
| 994 | 1064 | db_bind_text(&insRev, ":msg", zLog); |
| @@ -1015,10 +1085,22 @@ | ||
| 1015 | 1085 | if( zTemp ){ |
| 1016 | 1086 | srcRev = atoi(zTemp); |
| 1017 | 1087 | }else{ |
| 1018 | 1088 | fossil_fatal("Missing copyfrom-rev"); |
| 1019 | 1089 | } |
| 1090 | + } | |
| 1091 | + if( !flatFlag ){ | |
| 1092 | + if( strncmp(zPath, "branches/", 9)==0 ){ | |
| 1093 | + int i; | |
| 1094 | + sqlite3_snprintf(sizeof(zBranch), zBranch, "%s", zPath+9); | |
| 1095 | + for( i=0; zBranch[i]; i++ ){ | |
| 1096 | + if( zBranch[i]=='/' ) zBranch[i]=0; | |
| 1097 | + } | |
| 1098 | + }else | |
| 1099 | + if( strncmp(zPath, "trunk/", 6)==0 ){ | |
| 1100 | + memcpy(zBranch, "trunk", 6); | |
| 1101 | + } | |
| 1020 | 1102 | } |
| 1021 | 1103 | if( strncmp(zAction, "delete", 6)==0 |
| 1022 | 1104 | || strncmp(zAction, "replace", 7)==0 ) |
| 1023 | 1105 | { |
| 1024 | 1106 | db_bind_int(&delFile, ":rev", rev); |
| @@ -1038,14 +1120,24 @@ | ||
| 1038 | 1120 | " SELECT %d, %Q||substr(tpath, length(%Q)+1), trid, tperm " |
| 1039 | 1121 | " FROM xfiles " |
| 1040 | 1122 | " WHERE trev=%d AND tpath GLOB '%q/*'", |
| 1041 | 1123 | rev, zPath, zSrcPath, srcRev, zSrcPath |
| 1042 | 1124 | ); |
| 1125 | + if( !flatFlag && strncmp(zPath, "branches/", 9)==0 ){ | |
| 1126 | + zTemp = zPath+9; | |
| 1127 | + while( *zTemp && *zTemp!='/' ){ zTemp++; } | |
| 1128 | + if( *zTemp==0 ){ | |
| 1129 | + db_bind_int(&setParent, ":parent", srcRev); | |
| 1130 | + db_bind_int(&setParent, ":rev", rev); | |
| 1131 | + db_step(&setParent); | |
| 1132 | + db_reset(&setParent); | |
| 1133 | + } | |
| 1134 | + } | |
| 1043 | 1135 | } |
| 1044 | 1136 | }else{ |
| 1045 | 1137 | if( blob_size(&rec.content)==0 && zSrcPath ){ |
| 1046 | - rid = db_int(rid, | |
| 1138 | + rid = db_int(0, | |
| 1047 | 1139 | "SELECT trid FROM xfiles WHERE trev=%d AND tpath=%Q", |
| 1048 | 1140 | srcRev, zSrcPath); |
| 1049 | 1141 | }else{ |
| 1050 | 1142 | rid = content_put(&rec.content); |
| 1051 | 1143 | } |
| @@ -1073,14 +1165,23 @@ | ||
| 1073 | 1165 | }else{ |
| 1074 | 1166 | fossil_fatal("Unknown record type"); |
| 1075 | 1167 | } |
| 1076 | 1168 | svn_free_rec(&rec); |
| 1077 | 1169 | } |
| 1078 | - svn_create_manifests(); | |
| 1170 | + if( !flatFlag ){ | |
| 1171 | + if( *zBranch ){ | |
| 1172 | + db_bind_text(&setBranch, ":branch", zBranch); | |
| 1173 | + db_bind_int(&setBranch, ":rev", rev); | |
| 1174 | + db_step(&setBranch); | |
| 1175 | + } | |
| 1176 | + } | |
| 1079 | 1177 | db_finalize(&insRev); |
| 1080 | 1178 | db_finalize(&insFile); |
| 1081 | 1179 | db_finalize(&delFile); |
| 1180 | + db_finalize(&setBranch); | |
| 1181 | + db_finalize(&setParent); | |
| 1182 | + svn_create_manifests(flatFlag); | |
| 1082 | 1183 | } |
| 1083 | 1184 | |
| 1084 | 1185 | /* |
| 1085 | 1186 | ** COMMAND: import |
| 1086 | 1187 | ** |
| @@ -1106,16 +1207,17 @@ | ||
| 1106 | 1207 | ** Options: |
| 1107 | 1208 | ** --incremental allow importing into an existing repository |
| 1108 | 1209 | ** |
| 1109 | 1210 | ** See also: export |
| 1110 | 1211 | */ |
| 1111 | -void git_import_cmd(void){ | |
| 1212 | +void import_cmd(void){ | |
| 1112 | 1213 | char *zPassword; |
| 1113 | 1214 | FILE *pIn; |
| 1114 | 1215 | Stmt q; |
| 1115 | 1216 | int forceFlag = find_option("force", "f", 0)!=0; |
| 1116 | 1217 | int incrFlag = find_option("incremental", "i", 0)!=0; |
| 1218 | + int flatFlag = find_option("flat", 0, 0)!=0; | |
| 1117 | 1219 | |
| 1118 | 1220 | verify_all_options(); |
| 1119 | 1221 | if( g.argc!=4 && g.argc!=5 ){ |
| 1120 | 1222 | usage("FORMAT REPOSITORY-NAME"); |
| 1121 | 1223 | } |
| @@ -1172,19 +1274,19 @@ | ||
| 1172 | 1274 | db_finalize(&q); |
| 1173 | 1275 | }else |
| 1174 | 1276 | if( strncmp(g.argv[2], "svn", 3)==0 ){ |
| 1175 | 1277 | db_multi_exec( |
| 1176 | 1278 | "CREATE TEMP TABLE xrevisions(" |
| 1177 | - " trev INT, tuser TEXT, tmsg TEXT, ttime DATETIME" | |
| 1279 | + " trev INT, tuser TEXT, tmsg TEXT, ttime DATETIME, tparent INT," | |
| 1280 | + " tbranch TEXT, tuuid TEXT" | |
| 1178 | 1281 | ");" |
| 1179 | 1282 | "CREATE TEMP TABLE xfiles(" |
| 1180 | 1283 | " trev INT, tpath TEXT, trid TEXT, tperm TEXT," |
| 1181 | 1284 | " UNIQUE (trev, tpath) ON CONFLICT REPLACE" |
| 1182 | 1285 | ");" |
| 1183 | 1286 | ); |
| 1184 | - | |
| 1185 | - svn_dump_import(pIn); | |
| 1287 | + svn_dump_import(pIn, flatFlag); | |
| 1186 | 1288 | } |
| 1187 | 1289 | |
| 1188 | 1290 | db_end_transaction(0); |
| 1189 | 1291 | db_begin_transaction(); |
| 1190 | 1292 | fossil_print("Rebuilding repository meta-data...\n"); |
| 1191 | 1293 |
| --- src/import.c | |
| +++ src/import.c | |
| @@ -877,28 +877,64 @@ | |
| 877 | ); |
| 878 | } |
| 879 | return 1; |
| 880 | } |
| 881 | |
| 882 | static void svn_create_manifests(){ |
| 883 | Blob manifest; |
| 884 | Stmt qRev; |
| 885 | Stmt qFiles; |
| 886 | int parentRid = 0; |
| 887 | |
| 888 | blob_zero(&manifest); |
| 889 | db_prepare(&qRev, "SELECT trev, tuser, tmsg, ttime FROM xrevisions" |
| 890 | " ORDER BY trev"); |
| 891 | db_prepare(&qFiles, "SELECT tpath, uuid, tperm" |
| 892 | " FROM xfiles JOIN blob ON xfiles.trid=blob.rid" |
| 893 | " WHERE trev=:rev ORDER BY tpath"); |
| 894 | while( db_step(&qRev)==SQLITE_ROW ){ |
| 895 | int rev = db_column_int(&qRev, 0); |
| 896 | const char *zUser = db_column_text(&qRev, 1); |
| 897 | const char *zMsg = db_column_text(&qRev, 2); |
| 898 | const char *zTime = db_column_text(&qRev, 3); |
| 899 | Blob mcksum; |
| 900 | blob_reset(&manifest); |
| 901 | if( zMsg ){ |
| 902 | blob_appendf(&manifest, "C %F\n", zMsg); |
| 903 | }else{ |
| 904 | blob_append(&manifest, "C (no\\scomment)\n", 16); |
| @@ -910,20 +946,28 @@ | |
| 910 | const char *zUuid = db_column_text(&qFiles, 1); |
| 911 | const char *zPerm = db_column_text(&qFiles, 2); |
| 912 | blob_appendf(&manifest, "F %F %s %s\n", zFile, zUuid, zPerm); |
| 913 | } |
| 914 | db_reset(&qFiles); |
| 915 | if( parentRid>0 ){ |
| 916 | const char *zParent; |
| 917 | zParent = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", parentRid); |
| 918 | blob_appendf(&manifest, "P %s\n", zParent); |
| 919 | fossil_free(zParent); |
| 920 | }else{ |
| 921 | blob_appendf(&manifest, "R d41d8cd98f00b204e9800998ecf8427e\n"); |
| 922 | blob_appendf(&manifest, "T *branch * trunk\n"); |
| 923 | blob_appendf(&manifest, "T *sym-trunk *\n"); |
| 924 | } |
| 925 | if( zUser ){ |
| 926 | blob_appendf(&manifest, "U %F\n", zUser); |
| 927 | }else{ |
| 928 | const char *zUserOvrd = find_option("user-override",0,1); |
| 929 | blob_appendf(&manifest, "U %F\n", |
| @@ -931,27 +975,36 @@ | |
| 931 | } |
| 932 | md5sum_blob(&manifest, &mcksum); |
| 933 | blob_appendf(&manifest, "Z %b\n", &mcksum); |
| 934 | blob_reset(&mcksum); |
| 935 | |
| 936 | parentRid = content_put(&manifest); |
| 937 | } |
| 938 | db_finalize(&qRev); |
| 939 | db_finalize(&qFiles); |
| 940 | } |
| 941 | /* |
| 942 | ** Read the svn-dump format from pIn and insert the corresponding |
| 943 | ** content into the database. |
| 944 | */ |
| 945 | static void svn_dump_import(FILE *pIn){ |
| 946 | SvnRecord rec; |
| 947 | int ver; |
| 948 | const char *zTemp; |
| 949 | const char *zUuid; |
| 950 | Stmt insRev; |
| 951 | Stmt insFile; |
| 952 | Stmt delFile; |
| 953 | int rev = 0; |
| 954 | |
| 955 | /* version */ |
| 956 | if( svn_read_rec(pIn, &rec) |
| 957 | && (zTemp = svn_find_header(rec, "SVN-fs-dump-format-version")) ){ |
| @@ -979,16 +1032,33 @@ | |
| 979 | ); |
| 980 | db_prepare(&delFile, |
| 981 | "DELETE FROM xfiles " |
| 982 | "WHERE trev=:rev " |
| 983 | " AND (tpath=:path OR (tpath>:path||'/' AND tpath<:path||'0'))" |
| 984 | ); |
| 985 | while( svn_read_rec(pIn, &rec) ){ |
| 986 | if( zTemp = svn_find_header(rec, "Revision-number") ){ |
| 987 | const char *zUser = svn_find_prop(rec, "svn:author"); |
| 988 | const char *zLog = svn_find_prop(rec, "svn:log"); |
| 989 | const char *zDate = svn_find_prop(rec, "svn:date"); |
| 990 | zDate = date_in_standard_format(zDate); |
| 991 | rev = atoi(zTemp); |
| 992 | db_bind_int(&insRev, ":rev", rev); |
| 993 | db_bind_text(&insRev, ":user", zUser); |
| 994 | db_bind_text(&insRev, ":msg", zLog); |
| @@ -1015,10 +1085,22 @@ | |
| 1015 | if( zTemp ){ |
| 1016 | srcRev = atoi(zTemp); |
| 1017 | }else{ |
| 1018 | fossil_fatal("Missing copyfrom-rev"); |
| 1019 | } |
| 1020 | } |
| 1021 | if( strncmp(zAction, "delete", 6)==0 |
| 1022 | || strncmp(zAction, "replace", 7)==0 ) |
| 1023 | { |
| 1024 | db_bind_int(&delFile, ":rev", rev); |
| @@ -1038,14 +1120,24 @@ | |
| 1038 | " SELECT %d, %Q||substr(tpath, length(%Q)+1), trid, tperm " |
| 1039 | " FROM xfiles " |
| 1040 | " WHERE trev=%d AND tpath GLOB '%q/*'", |
| 1041 | rev, zPath, zSrcPath, srcRev, zSrcPath |
| 1042 | ); |
| 1043 | } |
| 1044 | }else{ |
| 1045 | if( blob_size(&rec.content)==0 && zSrcPath ){ |
| 1046 | rid = db_int(rid, |
| 1047 | "SELECT trid FROM xfiles WHERE trev=%d AND tpath=%Q", |
| 1048 | srcRev, zSrcPath); |
| 1049 | }else{ |
| 1050 | rid = content_put(&rec.content); |
| 1051 | } |
| @@ -1073,14 +1165,23 @@ | |
| 1073 | }else{ |
| 1074 | fossil_fatal("Unknown record type"); |
| 1075 | } |
| 1076 | svn_free_rec(&rec); |
| 1077 | } |
| 1078 | svn_create_manifests(); |
| 1079 | db_finalize(&insRev); |
| 1080 | db_finalize(&insFile); |
| 1081 | db_finalize(&delFile); |
| 1082 | } |
| 1083 | |
| 1084 | /* |
| 1085 | ** COMMAND: import |
| 1086 | ** |
| @@ -1106,16 +1207,17 @@ | |
| 1106 | ** Options: |
| 1107 | ** --incremental allow importing into an existing repository |
| 1108 | ** |
| 1109 | ** See also: export |
| 1110 | */ |
| 1111 | void git_import_cmd(void){ |
| 1112 | char *zPassword; |
| 1113 | FILE *pIn; |
| 1114 | Stmt q; |
| 1115 | int forceFlag = find_option("force", "f", 0)!=0; |
| 1116 | int incrFlag = find_option("incremental", "i", 0)!=0; |
| 1117 | |
| 1118 | verify_all_options(); |
| 1119 | if( g.argc!=4 && g.argc!=5 ){ |
| 1120 | usage("FORMAT REPOSITORY-NAME"); |
| 1121 | } |
| @@ -1172,19 +1274,19 @@ | |
| 1172 | db_finalize(&q); |
| 1173 | }else |
| 1174 | if( strncmp(g.argv[2], "svn", 3)==0 ){ |
| 1175 | db_multi_exec( |
| 1176 | "CREATE TEMP TABLE xrevisions(" |
| 1177 | " trev INT, tuser TEXT, tmsg TEXT, ttime DATETIME" |
| 1178 | ");" |
| 1179 | "CREATE TEMP TABLE xfiles(" |
| 1180 | " trev INT, tpath TEXT, trid TEXT, tperm TEXT," |
| 1181 | " UNIQUE (trev, tpath) ON CONFLICT REPLACE" |
| 1182 | ");" |
| 1183 | ); |
| 1184 | |
| 1185 | svn_dump_import(pIn); |
| 1186 | } |
| 1187 | |
| 1188 | db_end_transaction(0); |
| 1189 | db_begin_transaction(); |
| 1190 | fossil_print("Rebuilding repository meta-data...\n"); |
| 1191 |
| --- src/import.c | |
| +++ src/import.c | |
| @@ -877,28 +877,64 @@ | |
| 877 | ); |
| 878 | } |
| 879 | return 1; |
| 880 | } |
| 881 | |
| 882 | static void svn_create_manifests(int flatFlag){ |
| 883 | Blob manifest; |
| 884 | Stmt qRev; |
| 885 | Stmt qParent; |
| 886 | Stmt qFiles; |
| 887 | Stmt setUuid; |
| 888 | |
| 889 | if( !flatFlag ){ |
| 890 | db_multi_exec("DELETE FROM xrevisions WHERE tbranch ISNULL;" |
| 891 | "" |
| 892 | " WITH xprefix AS ( " |
| 893 | " SELECT trev, CASE tbranch WHEN 'trunk' THEN 'trunk/'" |
| 894 | " ELSE 'branches/'||tbranch||'/' END xpref" |
| 895 | " FROM xrevisions" |
| 896 | " ), " |
| 897 | " x AS (SELECT trev xrev, xpref, length(xpref) xlen " |
| 898 | " FROM xprefix) " |
| 899 | "UPDATE xfiles SET tpath= " |
| 900 | " CASE substr(tpath,1,(SELECT xlen FROM x WHERE xrev=trev))" |
| 901 | " WHEN (SELECT xpref FROM x WHERE xrev=trev)" |
| 902 | " THEN substr(tpath,(SELECT xlen FROM x WHERE xrev=trev)+1)" |
| 903 | " END;" |
| 904 | "DELETE FROM xfiles WHERE tpath ISNULL;" |
| 905 | "UPDATE xrevisions SET tparent=(" |
| 906 | " SELECT ifnull(max(trev),-1) FROM xrevisions t" |
| 907 | " WHERE t.trev<xrevisions.trev" |
| 908 | " AND t.tbranch=xrevisions.tbranch" |
| 909 | " )" |
| 910 | " WHERE tparent ISNULL"); |
| 911 | }else{ |
| 912 | db_multi_exec("UPDATE xrevisions SET tparent=trev-1"); |
| 913 | } |
| 914 | db_prepare(&qRev, "SELECT trev, tuser, tmsg, ttime, tparent, tbranch" |
| 915 | " FROM xrevisions " |
| 916 | " ORDER BY trev"); |
| 917 | db_prepare(&qParent, "SELECT tuuid, tbranch FROM xrevisions WHERE trev=:rev"); |
| 918 | db_prepare(&qFiles, "SELECT tpath, uuid, tperm" |
| 919 | " FROM xfiles JOIN blob ON xfiles.trid=blob.rid" |
| 920 | " WHERE trev=:rev ORDER BY tpath"); |
| 921 | db_prepare(&setUuid, "UPDATE xrevisions" |
| 922 | " SET tuuid=(SELECT uuid FROM blob WHERE rid=:rid)" |
| 923 | " WHERE trev=:rev"); |
| 924 | blob_zero(&manifest); |
| 925 | while( db_step(&qRev)==SQLITE_ROW ){ |
| 926 | int rev = db_column_int(&qRev, 0); |
| 927 | const char *zUser = db_column_text(&qRev, 1); |
| 928 | const char *zMsg = db_column_text(&qRev, 2); |
| 929 | const char *zTime = db_column_text(&qRev, 3); |
| 930 | int parentRev = db_column_int(&qRev, 4); |
| 931 | const char *zBranch = db_column_text(&qRev, 5); |
| 932 | int rid; |
| 933 | Blob mcksum; |
| 934 | const char *zParentUuid = 0; |
| 935 | const char *zParentBranch = 0; |
| 936 | blob_reset(&manifest); |
| 937 | if( zMsg ){ |
| 938 | blob_appendf(&manifest, "C %F\n", zMsg); |
| 939 | }else{ |
| 940 | blob_append(&manifest, "C (no\\scomment)\n", 16); |
| @@ -910,20 +946,28 @@ | |
| 946 | const char *zUuid = db_column_text(&qFiles, 1); |
| 947 | const char *zPerm = db_column_text(&qFiles, 2); |
| 948 | blob_appendf(&manifest, "F %F %s %s\n", zFile, zUuid, zPerm); |
| 949 | } |
| 950 | db_reset(&qFiles); |
| 951 | if( parentRev>=0 ){ |
| 952 | db_bind_int(&qParent, ":rev", parentRev); |
| 953 | db_step(&qParent); |
| 954 | zParentUuid = db_column_text(&qParent, 0); |
| 955 | blob_appendf(&manifest, "P %s\n", zParentUuid); |
| 956 | if( !flatFlag ){ |
| 957 | zParentBranch = db_column_text(&qParent, 1); |
| 958 | if( strcmp(zBranch, zParentBranch)!=0 ){ |
| 959 | blob_appendf(&manifest, "T *branch * %s\n", zBranch); |
| 960 | blob_appendf(&manifest, "T *sym-%s *\n", zBranch); |
| 961 | } |
| 962 | } |
| 963 | db_reset(&qParent); |
| 964 | }else{ |
| 965 | blob_appendf(&manifest, "T *branch * trunk\n"); |
| 966 | blob_appendf(&manifest, "T *sym-trunk *\n"); |
| 967 | } |
| 968 | blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", rev); |
| 969 | if( zUser ){ |
| 970 | blob_appendf(&manifest, "U %F\n", zUser); |
| 971 | }else{ |
| 972 | const char *zUserOvrd = find_option("user-override",0,1); |
| 973 | blob_appendf(&manifest, "U %F\n", |
| @@ -931,27 +975,36 @@ | |
| 975 | } |
| 976 | md5sum_blob(&manifest, &mcksum); |
| 977 | blob_appendf(&manifest, "Z %b\n", &mcksum); |
| 978 | blob_reset(&mcksum); |
| 979 | |
| 980 | rid = content_put(&manifest); |
| 981 | db_bind_int(&setUuid, ":rid", rid); |
| 982 | db_bind_int(&setUuid, ":rev", rev); |
| 983 | db_step(&setUuid); |
| 984 | db_reset(&setUuid); |
| 985 | } |
| 986 | db_finalize(&qRev); |
| 987 | db_finalize(&qParent); |
| 988 | db_finalize(&qFiles); |
| 989 | db_finalize(&setUuid); |
| 990 | } |
| 991 | /* |
| 992 | ** Read the svn-dump format from pIn and insert the corresponding |
| 993 | ** content into the database. |
| 994 | */ |
| 995 | static void svn_dump_import(FILE *pIn, int flatFlag){ |
| 996 | SvnRecord rec; |
| 997 | int ver; |
| 998 | const char *zTemp; |
| 999 | const char *zUuid; |
| 1000 | char zBranch[200] = {0}; |
| 1001 | Stmt insRev; |
| 1002 | Stmt insFile; |
| 1003 | Stmt delFile; |
| 1004 | Stmt setBranch; |
| 1005 | Stmt setParent; |
| 1006 | int rev = 0; |
| 1007 | |
| 1008 | /* version */ |
| 1009 | if( svn_read_rec(pIn, &rec) |
| 1010 | && (zTemp = svn_find_header(rec, "SVN-fs-dump-format-version")) ){ |
| @@ -979,16 +1032,33 @@ | |
| 1032 | ); |
| 1033 | db_prepare(&delFile, |
| 1034 | "DELETE FROM xfiles " |
| 1035 | "WHERE trev=:rev " |
| 1036 | " AND (tpath=:path OR (tpath>:path||'/' AND tpath<:path||'0'))" |
| 1037 | ); |
| 1038 | db_prepare(&setBranch, |
| 1039 | "UPDATE xrevisions SET tbranch=:branch " |
| 1040 | "WHERE trev=:rev" |
| 1041 | ); |
| 1042 | db_prepare(&setParent, |
| 1043 | "UPDATE xrevisions SET tparent=:parent " |
| 1044 | "WHERE trev=:rev" |
| 1045 | ); |
| 1046 | while( svn_read_rec(pIn, &rec) ){ |
| 1047 | if( zTemp = svn_find_header(rec, "Revision-number") ){ |
| 1048 | const char *zUser = svn_find_prop(rec, "svn:author"); |
| 1049 | const char *zLog = svn_find_prop(rec, "svn:log"); |
| 1050 | const char *zDate = svn_find_prop(rec, "svn:date"); |
| 1051 | if( !flatFlag ){ |
| 1052 | if( *zBranch ){ |
| 1053 | db_bind_text(&setBranch, ":branch", zBranch); |
| 1054 | db_bind_int(&setBranch, ":rev", rev); |
| 1055 | db_step(&setBranch); |
| 1056 | db_reset(&setBranch); |
| 1057 | zBranch[0] = 0; |
| 1058 | } |
| 1059 | } |
| 1060 | zDate = date_in_standard_format(zDate); |
| 1061 | rev = atoi(zTemp); |
| 1062 | db_bind_int(&insRev, ":rev", rev); |
| 1063 | db_bind_text(&insRev, ":user", zUser); |
| 1064 | db_bind_text(&insRev, ":msg", zLog); |
| @@ -1015,10 +1085,22 @@ | |
| 1085 | if( zTemp ){ |
| 1086 | srcRev = atoi(zTemp); |
| 1087 | }else{ |
| 1088 | fossil_fatal("Missing copyfrom-rev"); |
| 1089 | } |
| 1090 | } |
| 1091 | if( !flatFlag ){ |
| 1092 | if( strncmp(zPath, "branches/", 9)==0 ){ |
| 1093 | int i; |
| 1094 | sqlite3_snprintf(sizeof(zBranch), zBranch, "%s", zPath+9); |
| 1095 | for( i=0; zBranch[i]; i++ ){ |
| 1096 | if( zBranch[i]=='/' ) zBranch[i]=0; |
| 1097 | } |
| 1098 | }else |
| 1099 | if( strncmp(zPath, "trunk/", 6)==0 ){ |
| 1100 | memcpy(zBranch, "trunk", 6); |
| 1101 | } |
| 1102 | } |
| 1103 | if( strncmp(zAction, "delete", 6)==0 |
| 1104 | || strncmp(zAction, "replace", 7)==0 ) |
| 1105 | { |
| 1106 | db_bind_int(&delFile, ":rev", rev); |
| @@ -1038,14 +1120,24 @@ | |
| 1120 | " SELECT %d, %Q||substr(tpath, length(%Q)+1), trid, tperm " |
| 1121 | " FROM xfiles " |
| 1122 | " WHERE trev=%d AND tpath GLOB '%q/*'", |
| 1123 | rev, zPath, zSrcPath, srcRev, zSrcPath |
| 1124 | ); |
| 1125 | if( !flatFlag && strncmp(zPath, "branches/", 9)==0 ){ |
| 1126 | zTemp = zPath+9; |
| 1127 | while( *zTemp && *zTemp!='/' ){ zTemp++; } |
| 1128 | if( *zTemp==0 ){ |
| 1129 | db_bind_int(&setParent, ":parent", srcRev); |
| 1130 | db_bind_int(&setParent, ":rev", rev); |
| 1131 | db_step(&setParent); |
| 1132 | db_reset(&setParent); |
| 1133 | } |
| 1134 | } |
| 1135 | } |
| 1136 | }else{ |
| 1137 | if( blob_size(&rec.content)==0 && zSrcPath ){ |
| 1138 | rid = db_int(0, |
| 1139 | "SELECT trid FROM xfiles WHERE trev=%d AND tpath=%Q", |
| 1140 | srcRev, zSrcPath); |
| 1141 | }else{ |
| 1142 | rid = content_put(&rec.content); |
| 1143 | } |
| @@ -1073,14 +1165,23 @@ | |
| 1165 | }else{ |
| 1166 | fossil_fatal("Unknown record type"); |
| 1167 | } |
| 1168 | svn_free_rec(&rec); |
| 1169 | } |
| 1170 | if( !flatFlag ){ |
| 1171 | if( *zBranch ){ |
| 1172 | db_bind_text(&setBranch, ":branch", zBranch); |
| 1173 | db_bind_int(&setBranch, ":rev", rev); |
| 1174 | db_step(&setBranch); |
| 1175 | } |
| 1176 | } |
| 1177 | db_finalize(&insRev); |
| 1178 | db_finalize(&insFile); |
| 1179 | db_finalize(&delFile); |
| 1180 | db_finalize(&setBranch); |
| 1181 | db_finalize(&setParent); |
| 1182 | svn_create_manifests(flatFlag); |
| 1183 | } |
| 1184 | |
| 1185 | /* |
| 1186 | ** COMMAND: import |
| 1187 | ** |
| @@ -1106,16 +1207,17 @@ | |
| 1207 | ** Options: |
| 1208 | ** --incremental allow importing into an existing repository |
| 1209 | ** |
| 1210 | ** See also: export |
| 1211 | */ |
| 1212 | void import_cmd(void){ |
| 1213 | char *zPassword; |
| 1214 | FILE *pIn; |
| 1215 | Stmt q; |
| 1216 | int forceFlag = find_option("force", "f", 0)!=0; |
| 1217 | int incrFlag = find_option("incremental", "i", 0)!=0; |
| 1218 | int flatFlag = find_option("flat", 0, 0)!=0; |
| 1219 | |
| 1220 | verify_all_options(); |
| 1221 | if( g.argc!=4 && g.argc!=5 ){ |
| 1222 | usage("FORMAT REPOSITORY-NAME"); |
| 1223 | } |
| @@ -1172,19 +1274,19 @@ | |
| 1274 | db_finalize(&q); |
| 1275 | }else |
| 1276 | if( strncmp(g.argv[2], "svn", 3)==0 ){ |
| 1277 | db_multi_exec( |
| 1278 | "CREATE TEMP TABLE xrevisions(" |
| 1279 | " trev INT, tuser TEXT, tmsg TEXT, ttime DATETIME, tparent INT," |
| 1280 | " tbranch TEXT, tuuid TEXT" |
| 1281 | ");" |
| 1282 | "CREATE TEMP TABLE xfiles(" |
| 1283 | " trev INT, tpath TEXT, trid TEXT, tperm TEXT," |
| 1284 | " UNIQUE (trev, tpath) ON CONFLICT REPLACE" |
| 1285 | ");" |
| 1286 | ); |
| 1287 | svn_dump_import(pIn, flatFlag); |
| 1288 | } |
| 1289 | |
| 1290 | db_end_transaction(0); |
| 1291 | db_begin_transaction(); |
| 1292 | fossil_print("Rebuilding repository meta-data...\n"); |
| 1293 |