Fossil SCM

Significant speed improvment

baruch 2014-10-31 08:05 svn-import
Commit 31b1e5a8260eecf7057e40163f6c8d259b1823ee
2 files changed +2 +228 -246
+2
--- src/db.c
+++ src/db.c
@@ -286,10 +286,12 @@
286286
pStmt->pNext = db.pAllStmt;
287287
pStmt->pPrev = 0;
288288
if( db.pAllStmt ) db.pAllStmt->pPrev = pStmt;
289289
db.pAllStmt = pStmt;
290290
va_end(ap);
291
+ }else{
292
+ db_reset(pStmt);
291293
}
292294
return rc;
293295
}
294296
295297
/*
296298
--- src/db.c
+++ src/db.c
@@ -286,10 +286,12 @@
286 pStmt->pNext = db.pAllStmt;
287 pStmt->pPrev = 0;
288 if( db.pAllStmt ) db.pAllStmt->pPrev = pStmt;
289 db.pAllStmt = pStmt;
290 va_end(ap);
 
 
291 }
292 return rc;
293 }
294
295 /*
296
--- src/db.c
+++ src/db.c
@@ -286,10 +286,12 @@
286 pStmt->pNext = db.pAllStmt;
287 pStmt->pPrev = 0;
288 if( db.pAllStmt ) db.pAllStmt->pPrev = pStmt;
289 db.pAllStmt = pStmt;
290 va_end(ap);
291 }else{
292 db_reset(pStmt);
293 }
294 return rc;
295 }
296
297 /*
298
+228 -246
--- src/import.c
+++ src/import.c
@@ -717,10 +717,19 @@
717717
trim_newline(zLine);
718718
fossil_fatal("bad fast-import line: [%s]", zLine);
719719
return;
720720
}
721721
722
+static struct{
723
+ int rev; /* SVN revision number */
724
+ int parent; /* SVN revision number of parent check-in */
725
+ char *zBranch; /* Name of a branch for a commit */
726
+ char *zDate; /* Date/time stamp */
727
+ char *zUser; /* User name */
728
+ char *zComment; /* Comment of a commit */
729
+ int flatFlag; /* True if whole repo is a single file tree */
730
+} gsvn;
722731
typedef struct {
723732
const char *zKey;
724733
const char *zVal;
725734
} KeyVal;
726735
typedef struct {
@@ -880,133 +889,117 @@
880889
rec->contentFlag = 0;
881890
}
882891
return 1;
883892
}
884893
885
-static void svn_create_manifests(int flatFlag){
886
- Blob manifest;
887
- Stmt qRev;
888
- Stmt qParent;
889
- Stmt qFiles;
890
- Stmt qTags;
891
- Stmt setUuid;
892
-
893
- if( !flatFlag ){
894
- db_multi_exec("DELETE FROM xrevisions WHERE tbranch ISNULL;"
895
- "UPDATE xrevisions SET tparent=("
896
- " SELECT ifnull(max(trev),-1) FROM xrevisions t"
897
- " WHERE t.trev<xrevisions.trev"
898
- " AND t.tbranch=xrevisions.tbranch"
899
- " )"
900
- " WHERE tparent ISNULL;"
901
- "WITH xprefix AS ( "
902
- " SELECT trev, CASE tbranch WHEN 'trunk' THEN 'trunk/'"
903
- " ELSE 'branches/'||tbranch||'/' END xpref"
904
- " FROM xrevisions"
905
- " ), "
906
- " x AS (SELECT trev xrev, xpref, length(xpref) xlen "
907
- " FROM xprefix) "
908
- " UPDATE xfiles SET tpath= "
909
- " CASE substr(tpath,1,(SELECT xlen FROM x WHERE xrev=trev))"
910
- " WHEN (SELECT xpref FROM x WHERE xrev=trev)"
911
- " THEN substr(tpath,(SELECT xlen FROM x WHERE xrev=trev)+1)"
912
- " END;"
913
- "DELETE FROM xfiles WHERE tpath ISNULL");
914
- }else{
915
- db_multi_exec("UPDATE xrevisions SET tparent=trev-1");
916
- }
917
- db_prepare(&qRev, "SELECT trev, tuser, tmsg, ttime, tparent, tbranch"
918
- " FROM xrevisions "
919
- " ORDER BY trev");
920
- db_prepare(&qParent, "SELECT tuuid, tbranch FROM xrevisions WHERE trev=:rev");
921
- db_prepare(&qFiles, "SELECT tpath, uuid, tperm"
922
- " FROM xfiles JOIN blob ON xfiles.trid=blob.rid"
923
- " WHERE trev=:rev ORDER BY tpath");
924
- db_prepare(&qTags, "SELECT ttag FROM xtags WHERE trev=:rev");
925
- db_prepare(&setUuid, "UPDATE xrevisions"
926
- " SET tuuid=(SELECT uuid FROM blob WHERE rid=:rid)"
927
- " WHERE trev=:rev");
928
- blob_zero(&manifest);
929
- while( db_step(&qRev)==SQLITE_ROW ){
930
- int rev = db_column_int(&qRev, 0);
931
- const char *zUser = db_column_text(&qRev, 1);
932
- const char *zMsg = db_column_text(&qRev, 2);
933
- const char *zTime = db_column_text(&qRev, 3);
934
- int parentRev = db_column_int(&qRev, 4);
935
- const char *zBranch = db_column_text(&qRev, 5);
936
- int rid;
937
- const char *zParentBranch = 0;
938
- Blob mcksum;
939
- blob_reset(&manifest);
940
- if( zMsg ){
941
- blob_appendf(&manifest, "C %F\n", zMsg);
942
- }else{
943
- blob_append(&manifest, "C (no\\scomment)\n", 16);
944
- }
945
- blob_appendf(&manifest, "D %s\n", zTime);
946
- db_bind_int(&qFiles, ":rev", rev);
947
- while( db_step(&qFiles)==SQLITE_ROW ){
948
- const char *zFile = db_column_text(&qFiles, 0);
949
- const char *zUuid = db_column_text(&qFiles, 1);
950
- const char *zPerm = db_column_text(&qFiles, 2);
951
- blob_appendf(&manifest, "F %F %s %s\n", zFile, zUuid, zPerm);
952
- }
953
- db_reset(&qFiles);
954
- if( parentRev>=0 ){
955
- const char *zParentUuid;
956
- db_bind_int(&qParent, ":rev", parentRev);
957
- db_step(&qParent);
958
- zParentUuid = db_column_text(&qParent, 0);
959
- blob_appendf(&manifest, "P %s\n", zParentUuid);
960
- if( !flatFlag ){
961
- zParentBranch = db_column_text(&qParent, 1);
962
- if( strcmp(zBranch, zParentBranch)!=0 ){
963
- blob_appendf(&manifest, "T *branch * %s\n", zBranch);
964
- blob_appendf(&manifest, "T *sym-%s *\n", zBranch);
965
- zParentBranch = mprintf("%s", zParentBranch);
966
- }else{
967
- zParentBranch = 0;
968
- }
969
- }
970
- db_reset(&qParent);
971
- }else{
972
- blob_appendf(&manifest, "T *branch * trunk\n");
973
- blob_appendf(&manifest, "T *sym-trunk *\n");
974
- }
975
- db_bind_int(&qTags, ":rev", rev);
976
- while( db_step(&qTags)==SQLITE_ROW ){
977
- const char *zTag = db_column_text(&qTags, 0);
978
- blob_appendf(&manifest, "T +sym-%s *\n", zTag);
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);
990
- blob_appendf(&manifest, "U %F\n",
991
- zUserOvrd ? zUserOvrd : login_name());
992
- }
993
- md5sum_blob(&manifest, &mcksum);
994
- blob_appendf(&manifest, "Z %b\n", &mcksum);
995
- blob_reset(&mcksum);
996
-
997
- rid = content_put(&manifest);
998
- db_bind_int(&setUuid, ":rid", rid);
999
- db_bind_int(&setUuid, ":rev", rev);
1000
- db_step(&setUuid);
1001
- db_reset(&setUuid);
1002
- }
1003
- db_finalize(&qRev);
1004
- db_finalize(&qParent);
1005
- db_finalize(&qFiles);
1006
- db_finalize(&qTags);
1007
- db_finalize(&setUuid);
894
+static void svn_create_manifest(
895
+){
896
+ Blob manifest;
897
+ static Stmt insRev;
898
+ static Stmt qParent;
899
+ static Stmt qFiles;
900
+ static Stmt qTags;
901
+ char zFilter[200];
902
+ int nFilter;
903
+ int rid;
904
+ const char *zParentBranch = 0;
905
+ Blob mcksum;
906
+
907
+ db_static_prepare(&insRev, "REPLACE INTO xrevisions (trev, tbranch, tuuid) "
908
+ "VALUES(:rev, :branch, "
909
+ " (SELECT uuid FROM blob WHERE rid=:rid))");
910
+ db_static_prepare(&qParent, "SELECT tuuid, tbranch FROM xrevisions "
911
+ "WHERE trev=:rev");
912
+ db_static_prepare(&qFiles, "SELECT tpath, trid, tperm FROM xfiles "
913
+ "WHERE tpath GLOB :filter ORDER BY tpath");
914
+ db_static_prepare(&qTags, "SELECT ttag FROM xtags WHERE trev=:rev");
915
+ if( db_int(0, "SELECT 1 FROM xfiles LIMIT 1")==0 ){ return; }
916
+ if( !gsvn.flatFlag ){
917
+ if( gsvn.zBranch==0 || gsvn.zBranch[0]=='\0' ){ return; }
918
+ if( gsvn.parent<0 ){
919
+ gsvn.parent = db_int(-1, "SELECT ifnull(max(trev),-1) FROM xrevisions "
920
+ "WHERE tbranch=%Q", gsvn.zBranch);
921
+ }
922
+ db_bind_int(&insRev, ":rev", gsvn.rev);
923
+ db_bind_text(&insRev, ":branch", gsvn.zBranch);
924
+ db_bind_int(&insRev, ":rid", 0);
925
+ db_step(&insRev);
926
+ db_reset(&insRev);
927
+ }else{
928
+ static int prevRev = -1;
929
+ gsvn.parent = prevRev;
930
+ prevRev = gsvn.rev;
931
+ }
932
+ blob_zero(&manifest);
933
+ if( gsvn.zComment ){
934
+ blob_appendf(&manifest, "C %F\n", gsvn.zComment);
935
+ }else{
936
+ blob_append(&manifest, "C (no\\scomment)\n", 16);
937
+ }
938
+ blob_appendf(&manifest, "D %s\n", gsvn.zDate);
939
+ if( strncmp(gsvn.zBranch, "trunk", 5)==0 ){
940
+ memcpy(zFilter, "trunk/*", 8);
941
+ nFilter = 6;
942
+ }else{
943
+ sqlite3_snprintf(sizeof(zFilter), zFilter, "branches/%s/*", gsvn.zBranch);
944
+ nFilter = strlen(zFilter)-1;
945
+ }
946
+ db_bind_text(&qFiles, ":filter", zFilter);
947
+ while( db_step(&qFiles)==SQLITE_ROW ){
948
+ const char *zFile = db_column_text(&qFiles, 0);
949
+ int rid = db_column_int(&qFiles, 1);
950
+ const char *zPerm = db_column_text(&qFiles, 2);
951
+ const char *zUuid;
952
+ zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
953
+ blob_appendf(&manifest, "F %F %s %s\n", zFile+nFilter, zUuid, zPerm);
954
+ fossil_free(zUuid);
955
+ }
956
+ if( gsvn.parent>=0 ){
957
+ const char *zParentUuid;
958
+ db_bind_int(&qParent, ":rev", gsvn.parent);
959
+ db_step(&qParent);
960
+ zParentUuid = db_column_text(&qParent, 0);
961
+ blob_appendf(&manifest, "P %s\n", zParentUuid);
962
+ if( !gsvn.flatFlag ){
963
+ zParentBranch = db_column_text(&qParent, 1);
964
+ if( strcmp(gsvn.zBranch, zParentBranch)!=0 ){
965
+ blob_appendf(&manifest, "T *branch * %s\n", gsvn.zBranch);
966
+ blob_appendf(&manifest, "T *sym-%s *\n", gsvn.zBranch);
967
+ zParentBranch = mprintf("%s", zParentBranch);
968
+ }else{
969
+ zParentBranch = 0;
970
+ }
971
+ }
972
+ }else{
973
+ blob_appendf(&manifest, "T *branch * trunk\n");
974
+ blob_appendf(&manifest, "T *sym-trunk *\n");
975
+ }
976
+ db_bind_int(&qTags, ":rev", gsvn.rev);
977
+ while( db_step(&qTags)==SQLITE_ROW ){
978
+ const char *zTag = db_column_text(&qTags, 0);
979
+ blob_appendf(&manifest, "T +sym-%s *\n", zTag);
980
+ }
981
+ blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", gsvn.rev);
982
+ if( zParentBranch ) {
983
+ blob_appendf(&manifest, "T -sym-%s *\n", zParentBranch);
984
+ }
985
+ if( gsvn.zUser ){
986
+ blob_appendf(&manifest, "U %F\n", gsvn.zUser);
987
+ }else{
988
+ const char *zUserOvrd = find_option("user-override",0,1);
989
+ blob_appendf(&manifest, "U %F\n", zUserOvrd ? zUserOvrd : login_name());
990
+ }
991
+ md5sum_blob(&manifest, &mcksum);
992
+ blob_appendf(&manifest, "Z %b\n", &mcksum);
993
+ blob_reset(&mcksum);
994
+
995
+ rid = content_put(&manifest);
996
+ blob_reset(&manifest);
997
+ db_bind_int(&insRev, ":rev", gsvn.rev);
998
+ db_bind_text(&insRev, ":branch", gsvn.zBranch);
999
+ db_bind_int(&insRev, ":rid", rid);
1000
+ db_step(&insRev);
10081001
}
10091002
10101003
static u64 svn_get_varint(const char **pz){
10111004
unsigned int v = 0;
10121005
do{
@@ -1062,23 +1055,18 @@
10621055
10631056
/*
10641057
** Read the svn-dump format from pIn and insert the corresponding
10651058
** content into the database.
10661059
*/
1067
-static void svn_dump_import(FILE *pIn, int flatFlag){
1060
+static void svn_dump_import(FILE *pIn){
10681061
SvnRecord rec;
10691062
int ver;
10701063
const char *zTemp;
10711064
const char *zUuid;
1072
- char zBranch[200] = {0};
1073
- Stmt insRev;
1074
- Stmt insFile;
1065
+ Stmt addHist;
10751066
Stmt insTag;
1076
- Stmt delFile;
1077
- Stmt setBranch;
1078
- Stmt setParent;
1079
- int rev = 0;
1067
+ Stmt cpyPath;
10801068
10811069
/* version */
10821070
if( svn_read_rec(pIn, &rec)
10831071
&& (zTemp = svn_find_header(rec, "SVN-fs-dump-format-version")) ){
10841072
ver = atoi(zTemp);
@@ -1093,71 +1081,55 @@
10931081
if( !svn_read_rec(pIn, &rec) || !(zUuid = svn_find_header(rec, "UUID")) ){
10941082
fossil_fatal("Missing UUID!");
10951083
}
10961084
svn_free_rec(&rec);
10971085
/* content */
1098
- db_prepare(&insRev,
1099
- "INSERT INTO xrevisions (trev, tuser, tmsg, ttime) "
1100
- "VALUES(:rev, :user, :msg, :time)"
1101
- );
1102
- db_prepare(&insFile,
1103
- "INSERT INTO xfiles (trev, tpath, trid, tperm) "
1104
- "VALUES(:rev, :path, :rid, :perm)"
1086
+ db_prepare(&addHist,
1087
+ "INSERT INTO xhist (trev, tpath, trid, tperm) "
1088
+ "VALUES(:rev, :path, :rid, :perm)"
11051089
);
11061090
db_prepare(&insTag, "INSERT INTO xtags (trev, ttag) VALUES(:rev, :tag)");
1107
- db_prepare(&delFile,
1108
- "DELETE FROM xfiles "
1109
- "WHERE trev=:rev "
1110
- " AND (tpath=:path OR (tpath>:path||'/' AND tpath<:path||'0'))"
1111
- );
1112
- db_prepare(&setBranch,
1113
- "UPDATE xrevisions SET tbranch=:branch "
1114
- "WHERE trev=:rev"
1115
- );
1116
- db_prepare(&setParent,
1117
- "UPDATE xrevisions SET tparent=:parent "
1118
- "WHERE trev=:rev"
1119
- );
1091
+ db_prepare(&cpyPath,
1092
+ "WITH xsrc AS (SELECT * FROM ("
1093
+ " SELECT tpath, trid, tperm, max(trev) trev FROM xhist"
1094
+ " WHERE trev<=:srcrev GROUP BY tpath"
1095
+ " ) WHERE trid NOTNULL)"
1096
+ "INSERT INTO xhist (trev, tpath, trid, tperm)"
1097
+ " SELECT :rev, :path||substr(tpath, length(:srcpath)+1), trid, tperm"
1098
+ " FROM xsrc WHERE tpath>:srcpath||'/' AND tpath<:srcpath||0"
1099
+ );
1100
+ gsvn.rev = -1;
11201101
while( svn_read_rec(pIn, &rec) ){
1121
- if( zTemp = svn_find_header(rec, "Revision-number") ){
1122
- const char *zUser = svn_find_prop(rec, "svn:author");
1123
- const char *zLog = svn_find_prop(rec, "svn:log");
1124
- const char *zDate = svn_find_prop(rec, "svn:date");
1125
- if( !flatFlag ){
1126
- if( *zBranch ){
1127
- db_bind_text(&setBranch, ":branch", zBranch);
1128
- db_bind_int(&setBranch, ":rev", rev);
1129
- db_step(&setBranch);
1130
- db_reset(&setBranch);
1131
- zBranch[0] = 0;
1132
- }
1133
- }
1134
- zDate = date_in_standard_format(zDate);
1135
- rev = atoi(zTemp);
1136
- db_bind_int(&insRev, ":rev", rev);
1137
- db_bind_text(&insRev, ":user", zUser);
1138
- db_bind_text(&insRev, ":msg", zLog);
1139
- db_bind_text(&insRev, ":time", zDate);
1140
- db_step(&insRev);
1141
- db_reset(&insRev);
1142
- fossil_free(zDate);
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
- }else
1149
- if( zTemp = svn_find_header(rec, "Node-path") ){
1102
+ if( (zTemp = svn_find_header(rec, "Revision-number")) ){ /* revision node */
1103
+ /* finish previous revision */
1104
+ if( gsvn.rev>=0 ){
1105
+ svn_create_manifest();
1106
+ fossil_free(gsvn.zUser);
1107
+ fossil_free(gsvn.zComment);
1108
+ fossil_free(gsvn.zDate);
1109
+ fossil_free(gsvn.zBranch);
1110
+ }
1111
+ /* start new revision */
1112
+ gsvn.rev = atoi(zTemp);
1113
+ gsvn.zUser = mprintf("%s", svn_find_prop(rec, "svn:author"));
1114
+ gsvn.zComment = mprintf("%s", svn_find_prop(rec, "svn:log"));
1115
+ gsvn.zDate = date_in_standard_format(svn_find_prop(rec, "svn:date"));
1116
+ gsvn.parent = -1;
1117
+ gsvn.zBranch = 0;
1118
+ fossil_print("\rImporting SVN revision: %d", gsvn.rev);
1119
+ db_bind_int(&addHist, ":rev", gsvn.rev);
1120
+ db_bind_int(&cpyPath, ":rev", gsvn.rev);
1121
+ }else
1122
+ if( (zTemp = svn_find_header(rec, "Node-path")) ){ /* file/dir node */
11501123
const char *zPath = zTemp;
11511124
const char *zAction = svn_find_header(rec, "Node-action");
11521125
const char *zKind = svn_find_header(rec, "Node-kind");
11531126
const char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path");
11541127
const char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0;
11551128
int deltaFlag = 0;
1156
- int srcRev = -1;
1157
- int rid = 0;
1158
- if( zTemp = svn_find_header(rec, "Text-delta") ){
1129
+ int srcRev = 0;
1130
+ if( (zTemp = svn_find_header(rec, "Text-delta")) ){
11591131
deltaFlag = strncmp(zTemp, "true", 4)==0;
11601132
}
11611133
if( zSrcPath ){
11621134
zTemp = svn_find_header(rec, "Node-copyfrom-rev");
11631135
if( zTemp ){
@@ -1164,53 +1136,56 @@
11641136
srcRev = atoi(zTemp);
11651137
}else{
11661138
fossil_fatal("Missing copyfrom-rev");
11671139
}
11681140
}
1169
- if( !flatFlag ){
1141
+ if( !gsvn.flatFlag ){
11701142
if( strncmp(zPath, "branches/", 9)==0 ){
1171
- int i;
1172
- sqlite3_snprintf(sizeof(zBranch), zBranch, "%s", zPath+9);
1173
- for( i=0; zBranch[i]; i++ ){
1174
- if( zBranch[i]=='/' ) zBranch[i]=0;
1175
- }
1143
+ int nBranch;
1144
+ zTemp = zPath+9;
1145
+ while( *zTemp && *zTemp!='/' ){ zTemp++; }
1146
+ nBranch = zTemp-zPath+9;
1147
+ gsvn.zBranch = fossil_malloc(nBranch+1);
1148
+ memcpy(gsvn.zBranch, zPath+9, nBranch);
1149
+ gsvn.zBranch[nBranch] = '\0';
11761150
}else
11771151
if( strncmp(zPath, "trunk/", 6)==0 ){
1178
- memcpy(zBranch, "trunk", 6);
1152
+ gsvn.zBranch = mprintf("trunk");
1153
+ }else
1154
+ if( strncmp(zPath, "tags/", 5)!=0
1155
+ && strcmp(zPath, "branches")!=0
1156
+ && strcmp(zPath, "trunk")!=0
1157
+ && strcmp(zPath, "tags")!=0){
1158
+ fossil_fatal("Write outside repository layout: %s", zPath);
11791159
}
11801160
}
11811161
if( strncmp(zAction, "delete", 6)==0
11821162
|| strncmp(zAction, "replace", 7)==0 )
11831163
{
1184
- db_bind_int(&delFile, ":rev", rev);
1185
- db_bind_text(&delFile, ":path", zPath);
1186
- db_step(&delFile);
1187
- db_reset(&delFile);
1164
+ db_bind_null(&addHist, ":rid");
1165
+ db_bind_text(&addHist, ":path", zPath);
1166
+ db_bind_null(&addHist, ":perm");
1167
+ db_step(&addHist);
1168
+ db_reset(&addHist);
11881169
} /* no 'else' here since 'replace' does both a 'delete' and an 'add' */
11891170
if( strncmp(zAction, "add", 3)==0
11901171
|| strncmp(zAction, "replace", 7)==0 )
11911172
{
11921173
if( zKind==0 ){
11931174
fossil_fatal("Missing Node-kind");
11941175
}else if( strncmp(zKind, "dir", 3)==0 ){
11951176
if( zSrcPath ){
1196
- db_multi_exec(
1197
- "INSERT INTO xfiles (trev, tpath, trid, tperm) "
1198
- " SELECT %d, %Q||substr(tpath, length(%Q)+1), trid, tperm "
1199
- " FROM xfiles "
1200
- " WHERE trev=%d AND tpath GLOB '%q/*'",
1201
- rev, zPath, zSrcPath, srcRev, zSrcPath
1202
- );
1203
- if( !flatFlag ){
1177
+ db_bind_int(&cpyPath, ":srcrev", srcRev);
1178
+ db_bind_text(&cpyPath, ":path", zPath);
1179
+ db_bind_text(&cpyPath, ":srcpath", zSrcPath);
1180
+ db_step(&cpyPath);
1181
+ db_reset(&cpyPath);
1182
+ if( !gsvn.flatFlag ){
12041183
if( strncmp(zPath, "branches/", 9)==0 ){
1205
- zTemp = zPath+9;
1206
- while( *zTemp && *zTemp!='/' ){ zTemp++; }
1184
+ zTemp = zPath+9+strlen(gsvn.zBranch);
12071185
if( *zTemp==0 ){
1208
- db_bind_int(&setParent, ":parent", srcRev);
1209
- db_bind_int(&setParent, ":rev", rev);
1210
- db_step(&setParent);
1211
- db_reset(&setParent);
1186
+ gsvn.parent = srcRev;
12121187
}
12131188
}else if( strncmp(zPath, "tags/", 5)==0 ){
12141189
zTemp = zPath+5;
12151190
db_bind_int(&insTag, ":rev", srcRev);
12161191
db_bind_text(&insTag, ":tag", zTemp);
@@ -1218,14 +1193,17 @@
12181193
db_reset(&insTag);
12191194
}
12201195
}
12211196
}
12221197
}else{
1198
+ int rid = 0;
12231199
if( zSrcPath ){
1224
- rid = db_int(0,
1225
- "SELECT trid FROM xfiles WHERE trev=%d AND tpath=%Q",
1226
- srcRev, zSrcPath);
1200
+ rid = db_int(0, "SELECT trid, max(trev) FROM xhist"
1201
+ " WHERE trev<=%d AND tpath=%Q", srcRev, zSrcPath);
1202
+ if( rid==0 ){
1203
+ fossil_fatal("Reference to non-existent path/revision");
1204
+ }
12271205
}
12281206
if( deltaFlag ){
12291207
Blob deltaSrc;
12301208
Blob target;
12311209
if( rid!=0 ){
@@ -1236,64 +1214,58 @@
12361214
svn_apply_svndiff(&rec.content, &deltaSrc, &target);
12371215
rid = content_put(&target);
12381216
}else if( rec.contentFlag ){
12391217
rid = content_put(&rec.content);
12401218
}
1241
- db_bind_int(&insFile, ":rev", rev);
1242
- db_bind_int(&insFile, ":rid", rid);
1243
- db_bind_text(&insFile, ":path", zPath);
1244
- db_bind_text(&insFile, ":perm", zPerm);
1245
- db_step(&insFile);
1246
- db_reset(&insFile);
1219
+ db_bind_int(&addHist, ":rid", rid);
1220
+ db_bind_text(&addHist, ":path", zPath);
1221
+ db_bind_text(&addHist, ":perm", zPerm);
1222
+ db_step(&addHist);
1223
+ db_reset(&addHist);
12471224
}
12481225
}else
12491226
if( strncmp(zAction, "change", 6)==0 ){
1227
+ int rid = 0;
12501228
if( zKind==0 ){
12511229
fossil_fatal("Missing Node-kind");
12521230
}
12531231
if( strncmp(zKind, "dir", 3)==0 ) continue;
12541232
if( deltaFlag ){
12551233
Blob deltaSrc;
12561234
Blob target;
1257
- rid = db_int(0, "SELECT trid FROM xfiles WHERE tpath=%Q AND trev=%d",
1258
- zPath, rev-1);
1235
+ rid = db_int(0, "SELECT trid, max(trev) FROM xhist"
1236
+ " WHERE trev<=%d AND tpath=%Q", gsvn.rev-1, zPath);
12591237
content_get(rid, &deltaSrc);
12601238
svn_apply_svndiff(&rec.content, &deltaSrc, &target);
12611239
rid = content_put(&target);
12621240
}else{
12631241
rid = content_put(&rec.content);
12641242
}
1265
- db_bind_int(&insFile, ":rev", rev);
1266
- db_bind_int(&insFile, ":rid", rid);
1267
- db_bind_text(&insFile, ":path", zPath);
1268
- db_bind_text(&insFile, ":perm", zPerm);
1269
- db_step(&insFile);
1270
- db_reset(&insFile);
1243
+ db_bind_int(&addHist, ":rid", rid);
1244
+ db_bind_text(&addHist, ":path", zPath);
1245
+ db_bind_text(&addHist, ":perm", zPerm);
1246
+ db_step(&addHist);
1247
+ db_reset(&addHist);
12711248
}else
1272
- if( strncmp(zAction, "delete", 6)==0){ /* already did this above */
1273
- }else{
1249
+ if( strncmp(zAction, "delete", 6)!=0 ){ /* already did this above */
12741250
fossil_fatal("Unknown Node-action");
12751251
}
12761252
}else{
12771253
fossil_fatal("Unknown record type");
12781254
}
12791255
svn_free_rec(&rec);
12801256
}
1281
- if( !flatFlag ){
1282
- if( *zBranch ){
1283
- db_bind_text(&setBranch, ":branch", zBranch);
1284
- db_bind_int(&setBranch, ":rev", rev);
1285
- db_step(&setBranch);
1286
- }
1287
- }
1288
- db_finalize(&insRev);
1289
- db_finalize(&insFile);
1257
+ if( gsvn.rev>0 ){
1258
+ svn_create_manifest();
1259
+ }
1260
+ fossil_free(gsvn.zUser);
1261
+ fossil_free(gsvn.zComment);
1262
+ fossil_free(gsvn.zDate);
1263
+ db_finalize(&addHist);
12901264
db_finalize(&insTag);
1291
- db_finalize(&delFile);
1292
- db_finalize(&setBranch);
1293
- db_finalize(&setParent);
1294
- svn_create_manifests(flatFlag);
1265
+ db_finalize(&cpyPath);
1266
+ fossil_print(" Done!\n");
12951267
}
12961268
12971269
/*
12981270
** COMMAND: import
12991271
**
@@ -1325,11 +1297,11 @@
13251297
char *zPassword;
13261298
FILE *pIn;
13271299
Stmt q;
13281300
int forceFlag = find_option("force", "f", 0)!=0;
13291301
int incrFlag = find_option("incremental", "i", 0)!=0;
1330
- int flatFlag = find_option("flat", 0, 0)!=0;
1302
+ gsvn.flatFlag = find_option("flat", 0, 0)!=0;
13311303
13321304
verify_all_options();
13331305
if( g.argc!=4 && g.argc!=5 ){
13341306
usage("FORMAT REPOSITORY-NAME");
13351307
}
@@ -1386,24 +1358,34 @@
13861358
db_finalize(&q);
13871359
}else
13881360
if( strncmp(g.argv[2], "svn", 3)==0 ){
13891361
db_multi_exec(
13901362
"CREATE TEMP TABLE xrevisions("
1391
- " trev INTEGER PRIMARY KEY, tuser TEXT, tmsg TEXT, ttime DATETIME,"
1392
- " tparent INT, tbranch TEXT, tuuid TEXT"
1363
+ " trev INTEGER PRIMARY KEY, tbranch TEXT, tuuid TEXT"
1364
+ ");"
1365
+ "CREATE TEMP TABLE xhist("
1366
+ " trev INT, tpath TEXT NOT NULL, trid TEXT, tperm TEXT,"
1367
+ " UNIQUE (trev, tpath) ON CONFLICT REPLACE"
13931368
");"
13941369
"CREATE TEMP TABLE xfiles("
1395
- " trev INT, tpath TEXT, trid TEXT, tperm TEXT,"
1396
- " UNIQUE (trev, tpath) ON CONFLICT REPLACE"
1370
+ " tpath TEXT NOT NULL, trid TEXT, tperm TEXT,"
1371
+ " UNIQUE (tpath) ON CONFLICT REPLACE"
13971372
");"
1373
+ "CREATE TEMP TRIGGER xfilesdeltrig AFTER INSERT ON xhist FOR EACH ROW"
1374
+ " WHEN new.trid ISNULL"
1375
+ " BEGIN DELETE FROM xfiles WHERE xfiles.tpath=new.tpath; END;"
1376
+ "CREATE TEMP TRIGGER xfilesaddtrig AFTER INSERT ON xhist FOR EACH ROW"
1377
+ " WHEN new.trid NOTNULL BEGIN INSERT INTO xfiles(tpath,trid,tperm)"
1378
+ " VALUES(new.tpath, new.trid, new.tperm); END;"
13981379
"CREATE TEMP TABLE xtags("
13991380
" trev INT, ttag TEXT"
14001381
");"
14011382
);
1402
- svn_dump_import(pIn, flatFlag);
1383
+ svn_dump_import(pIn);
14031384
}
14041385
1386
+ verify_cancel();
14051387
db_end_transaction(0);
14061388
db_begin_transaction();
14071389
fossil_print("Rebuilding repository meta-data...\n");
14081390
rebuild_db(0, 1, !incrFlag);
14091391
verify_cancel();
14101392
--- src/import.c
+++ src/import.c
@@ -717,10 +717,19 @@
717 trim_newline(zLine);
718 fossil_fatal("bad fast-import line: [%s]", zLine);
719 return;
720 }
721
 
 
 
 
 
 
 
 
 
722 typedef struct {
723 const char *zKey;
724 const char *zVal;
725 } KeyVal;
726 typedef struct {
@@ -880,133 +889,117 @@
880 rec->contentFlag = 0;
881 }
882 return 1;
883 }
884
885 static void svn_create_manifests(int flatFlag){
886 Blob manifest;
887 Stmt qRev;
888 Stmt qParent;
889 Stmt qFiles;
890 Stmt qTags;
891 Stmt setUuid;
892
893 if( !flatFlag ){
894 db_multi_exec("DELETE FROM xrevisions WHERE tbranch ISNULL;"
895 "UPDATE xrevisions SET tparent=("
896 " SELECT ifnull(max(trev),-1) FROM xrevisions t"
897 " WHERE t.trev<xrevisions.trev"
898 " AND t.tbranch=xrevisions.tbranch"
899 " )"
900 " WHERE tparent ISNULL;"
901 "WITH xprefix AS ( "
902 " SELECT trev, CASE tbranch WHEN 'trunk' THEN 'trunk/'"
903 " ELSE 'branches/'||tbranch||'/' END xpref"
904 " FROM xrevisions"
905 " ), "
906 " x AS (SELECT trev xrev, xpref, length(xpref) xlen "
907 " FROM xprefix) "
908 " UPDATE xfiles SET tpath= "
909 " CASE substr(tpath,1,(SELECT xlen FROM x WHERE xrev=trev))"
910 " WHEN (SELECT xpref FROM x WHERE xrev=trev)"
911 " THEN substr(tpath,(SELECT xlen FROM x WHERE xrev=trev)+1)"
912 " END;"
913 "DELETE FROM xfiles WHERE tpath ISNULL");
914 }else{
915 db_multi_exec("UPDATE xrevisions SET tparent=trev-1");
916 }
917 db_prepare(&qRev, "SELECT trev, tuser, tmsg, ttime, tparent, tbranch"
918 " FROM xrevisions "
919 " ORDER BY trev");
920 db_prepare(&qParent, "SELECT tuuid, tbranch FROM xrevisions WHERE trev=:rev");
921 db_prepare(&qFiles, "SELECT tpath, uuid, tperm"
922 " FROM xfiles JOIN blob ON xfiles.trid=blob.rid"
923 " WHERE trev=:rev ORDER BY tpath");
924 db_prepare(&qTags, "SELECT ttag FROM xtags WHERE trev=:rev");
925 db_prepare(&setUuid, "UPDATE xrevisions"
926 " SET tuuid=(SELECT uuid FROM blob WHERE rid=:rid)"
927 " WHERE trev=:rev");
928 blob_zero(&manifest);
929 while( db_step(&qRev)==SQLITE_ROW ){
930 int rev = db_column_int(&qRev, 0);
931 const char *zUser = db_column_text(&qRev, 1);
932 const char *zMsg = db_column_text(&qRev, 2);
933 const char *zTime = db_column_text(&qRev, 3);
934 int parentRev = db_column_int(&qRev, 4);
935 const char *zBranch = db_column_text(&qRev, 5);
936 int rid;
937 const char *zParentBranch = 0;
938 Blob mcksum;
939 blob_reset(&manifest);
940 if( zMsg ){
941 blob_appendf(&manifest, "C %F\n", zMsg);
942 }else{
943 blob_append(&manifest, "C (no\\scomment)\n", 16);
944 }
945 blob_appendf(&manifest, "D %s\n", zTime);
946 db_bind_int(&qFiles, ":rev", rev);
947 while( db_step(&qFiles)==SQLITE_ROW ){
948 const char *zFile = db_column_text(&qFiles, 0);
949 const char *zUuid = db_column_text(&qFiles, 1);
950 const char *zPerm = db_column_text(&qFiles, 2);
951 blob_appendf(&manifest, "F %F %s %s\n", zFile, zUuid, zPerm);
952 }
953 db_reset(&qFiles);
954 if( parentRev>=0 ){
955 const char *zParentUuid;
956 db_bind_int(&qParent, ":rev", parentRev);
957 db_step(&qParent);
958 zParentUuid = db_column_text(&qParent, 0);
959 blob_appendf(&manifest, "P %s\n", zParentUuid);
960 if( !flatFlag ){
961 zParentBranch = db_column_text(&qParent, 1);
962 if( strcmp(zBranch, zParentBranch)!=0 ){
963 blob_appendf(&manifest, "T *branch * %s\n", zBranch);
964 blob_appendf(&manifest, "T *sym-%s *\n", zBranch);
965 zParentBranch = mprintf("%s", zParentBranch);
966 }else{
967 zParentBranch = 0;
968 }
969 }
970 db_reset(&qParent);
971 }else{
972 blob_appendf(&manifest, "T *branch * trunk\n");
973 blob_appendf(&manifest, "T *sym-trunk *\n");
974 }
975 db_bind_int(&qTags, ":rev", rev);
976 while( db_step(&qTags)==SQLITE_ROW ){
977 const char *zTag = db_column_text(&qTags, 0);
978 blob_appendf(&manifest, "T +sym-%s *\n", zTag);
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);
990 blob_appendf(&manifest, "U %F\n",
991 zUserOvrd ? zUserOvrd : login_name());
992 }
993 md5sum_blob(&manifest, &mcksum);
994 blob_appendf(&manifest, "Z %b\n", &mcksum);
995 blob_reset(&mcksum);
996
997 rid = content_put(&manifest);
998 db_bind_int(&setUuid, ":rid", rid);
999 db_bind_int(&setUuid, ":rev", rev);
1000 db_step(&setUuid);
1001 db_reset(&setUuid);
1002 }
1003 db_finalize(&qRev);
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{
@@ -1062,23 +1055,18 @@
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){
1068 SvnRecord rec;
1069 int ver;
1070 const char *zTemp;
1071 const char *zUuid;
1072 char zBranch[200] = {0};
1073 Stmt insRev;
1074 Stmt insFile;
1075 Stmt insTag;
1076 Stmt delFile;
1077 Stmt setBranch;
1078 Stmt setParent;
1079 int rev = 0;
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);
@@ -1093,71 +1081,55 @@
1093 if( !svn_read_rec(pIn, &rec) || !(zUuid = svn_find_header(rec, "UUID")) ){
1094 fossil_fatal("Missing UUID!");
1095 }
1096 svn_free_rec(&rec);
1097 /* content */
1098 db_prepare(&insRev,
1099 "INSERT INTO xrevisions (trev, tuser, tmsg, ttime) "
1100 "VALUES(:rev, :user, :msg, :time)"
1101 );
1102 db_prepare(&insFile,
1103 "INSERT INTO xfiles (trev, tpath, trid, tperm) "
1104 "VALUES(:rev, :path, :rid, :perm)"
1105 );
1106 db_prepare(&insTag, "INSERT INTO xtags (trev, ttag) VALUES(:rev, :tag)");
1107 db_prepare(&delFile,
1108 "DELETE FROM xfiles "
1109 "WHERE trev=:rev "
1110 " AND (tpath=:path OR (tpath>:path||'/' AND tpath<:path||'0'))"
1111 );
1112 db_prepare(&setBranch,
1113 "UPDATE xrevisions SET tbranch=:branch "
1114 "WHERE trev=:rev"
1115 );
1116 db_prepare(&setParent,
1117 "UPDATE xrevisions SET tparent=:parent "
1118 "WHERE trev=:rev"
1119 );
1120 while( svn_read_rec(pIn, &rec) ){
1121 if( zTemp = svn_find_header(rec, "Revision-number") ){
1122 const char *zUser = svn_find_prop(rec, "svn:author");
1123 const char *zLog = svn_find_prop(rec, "svn:log");
1124 const char *zDate = svn_find_prop(rec, "svn:date");
1125 if( !flatFlag ){
1126 if( *zBranch ){
1127 db_bind_text(&setBranch, ":branch", zBranch);
1128 db_bind_int(&setBranch, ":rev", rev);
1129 db_step(&setBranch);
1130 db_reset(&setBranch);
1131 zBranch[0] = 0;
1132 }
1133 }
1134 zDate = date_in_standard_format(zDate);
1135 rev = atoi(zTemp);
1136 db_bind_int(&insRev, ":rev", rev);
1137 db_bind_text(&insRev, ":user", zUser);
1138 db_bind_text(&insRev, ":msg", zLog);
1139 db_bind_text(&insRev, ":time", zDate);
1140 db_step(&insRev);
1141 db_reset(&insRev);
1142 fossil_free(zDate);
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 }else
1149 if( zTemp = svn_find_header(rec, "Node-path") ){
1150 const char *zPath = zTemp;
1151 const char *zAction = svn_find_header(rec, "Node-action");
1152 const char *zKind = svn_find_header(rec, "Node-kind");
1153 const char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path");
1154 const char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0;
1155 int deltaFlag = 0;
1156 int srcRev = -1;
1157 int rid = 0;
1158 if( zTemp = svn_find_header(rec, "Text-delta") ){
1159 deltaFlag = strncmp(zTemp, "true", 4)==0;
1160 }
1161 if( zSrcPath ){
1162 zTemp = svn_find_header(rec, "Node-copyfrom-rev");
1163 if( zTemp ){
@@ -1164,53 +1136,56 @@
1164 srcRev = atoi(zTemp);
1165 }else{
1166 fossil_fatal("Missing copyfrom-rev");
1167 }
1168 }
1169 if( !flatFlag ){
1170 if( strncmp(zPath, "branches/", 9)==0 ){
1171 int i;
1172 sqlite3_snprintf(sizeof(zBranch), zBranch, "%s", zPath+9);
1173 for( i=0; zBranch[i]; i++ ){
1174 if( zBranch[i]=='/' ) zBranch[i]=0;
1175 }
 
 
1176 }else
1177 if( strncmp(zPath, "trunk/", 6)==0 ){
1178 memcpy(zBranch, "trunk", 6);
 
 
 
 
 
 
1179 }
1180 }
1181 if( strncmp(zAction, "delete", 6)==0
1182 || strncmp(zAction, "replace", 7)==0 )
1183 {
1184 db_bind_int(&delFile, ":rev", rev);
1185 db_bind_text(&delFile, ":path", zPath);
1186 db_step(&delFile);
1187 db_reset(&delFile);
 
1188 } /* no 'else' here since 'replace' does both a 'delete' and an 'add' */
1189 if( strncmp(zAction, "add", 3)==0
1190 || strncmp(zAction, "replace", 7)==0 )
1191 {
1192 if( zKind==0 ){
1193 fossil_fatal("Missing Node-kind");
1194 }else if( strncmp(zKind, "dir", 3)==0 ){
1195 if( zSrcPath ){
1196 db_multi_exec(
1197 "INSERT INTO xfiles (trev, tpath, trid, tperm) "
1198 " SELECT %d, %Q||substr(tpath, length(%Q)+1), trid, tperm "
1199 " FROM xfiles "
1200 " WHERE trev=%d AND tpath GLOB '%q/*'",
1201 rev, zPath, zSrcPath, srcRev, zSrcPath
1202 );
1203 if( !flatFlag ){
1204 if( strncmp(zPath, "branches/", 9)==0 ){
1205 zTemp = zPath+9;
1206 while( *zTemp && *zTemp!='/' ){ zTemp++; }
1207 if( *zTemp==0 ){
1208 db_bind_int(&setParent, ":parent", srcRev);
1209 db_bind_int(&setParent, ":rev", rev);
1210 db_step(&setParent);
1211 db_reset(&setParent);
1212 }
1213 }else if( strncmp(zPath, "tags/", 5)==0 ){
1214 zTemp = zPath+5;
1215 db_bind_int(&insTag, ":rev", srcRev);
1216 db_bind_text(&insTag, ":tag", zTemp);
@@ -1218,14 +1193,17 @@
1218 db_reset(&insTag);
1219 }
1220 }
1221 }
1222 }else{
 
1223 if( zSrcPath ){
1224 rid = db_int(0,
1225 "SELECT trid FROM xfiles WHERE trev=%d AND tpath=%Q",
1226 srcRev, zSrcPath);
 
 
1227 }
1228 if( deltaFlag ){
1229 Blob deltaSrc;
1230 Blob target;
1231 if( rid!=0 ){
@@ -1236,64 +1214,58 @@
1236 svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1237 rid = content_put(&target);
1238 }else if( rec.contentFlag ){
1239 rid = content_put(&rec.content);
1240 }
1241 db_bind_int(&insFile, ":rev", rev);
1242 db_bind_int(&insFile, ":rid", rid);
1243 db_bind_text(&insFile, ":path", zPath);
1244 db_bind_text(&insFile, ":perm", zPerm);
1245 db_step(&insFile);
1246 db_reset(&insFile);
1247 }
1248 }else
1249 if( strncmp(zAction, "change", 6)==0 ){
 
1250 if( zKind==0 ){
1251 fossil_fatal("Missing Node-kind");
1252 }
1253 if( strncmp(zKind, "dir", 3)==0 ) continue;
1254 if( deltaFlag ){
1255 Blob deltaSrc;
1256 Blob target;
1257 rid = db_int(0, "SELECT trid FROM xfiles WHERE tpath=%Q AND trev=%d",
1258 zPath, rev-1);
1259 content_get(rid, &deltaSrc);
1260 svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1261 rid = content_put(&target);
1262 }else{
1263 rid = content_put(&rec.content);
1264 }
1265 db_bind_int(&insFile, ":rev", rev);
1266 db_bind_int(&insFile, ":rid", rid);
1267 db_bind_text(&insFile, ":path", zPath);
1268 db_bind_text(&insFile, ":perm", zPerm);
1269 db_step(&insFile);
1270 db_reset(&insFile);
1271 }else
1272 if( strncmp(zAction, "delete", 6)==0){ /* already did this above */
1273 }else{
1274 fossil_fatal("Unknown Node-action");
1275 }
1276 }else{
1277 fossil_fatal("Unknown record type");
1278 }
1279 svn_free_rec(&rec);
1280 }
1281 if( !flatFlag ){
1282 if( *zBranch ){
1283 db_bind_text(&setBranch, ":branch", zBranch);
1284 db_bind_int(&setBranch, ":rev", rev);
1285 db_step(&setBranch);
1286 }
1287 }
1288 db_finalize(&insRev);
1289 db_finalize(&insFile);
1290 db_finalize(&insTag);
1291 db_finalize(&delFile);
1292 db_finalize(&setBranch);
1293 db_finalize(&setParent);
1294 svn_create_manifests(flatFlag);
1295 }
1296
1297 /*
1298 ** COMMAND: import
1299 **
@@ -1325,11 +1297,11 @@
1325 char *zPassword;
1326 FILE *pIn;
1327 Stmt q;
1328 int forceFlag = find_option("force", "f", 0)!=0;
1329 int incrFlag = find_option("incremental", "i", 0)!=0;
1330 int flatFlag = find_option("flat", 0, 0)!=0;
1331
1332 verify_all_options();
1333 if( g.argc!=4 && g.argc!=5 ){
1334 usage("FORMAT REPOSITORY-NAME");
1335 }
@@ -1386,24 +1358,34 @@
1386 db_finalize(&q);
1387 }else
1388 if( strncmp(g.argv[2], "svn", 3)==0 ){
1389 db_multi_exec(
1390 "CREATE TEMP TABLE xrevisions("
1391 " trev INTEGER PRIMARY KEY, tuser TEXT, tmsg TEXT, ttime DATETIME,"
1392 " tparent INT, tbranch TEXT, tuuid TEXT"
 
 
 
1393 ");"
1394 "CREATE TEMP TABLE xfiles("
1395 " trev INT, tpath TEXT, trid TEXT, tperm TEXT,"
1396 " UNIQUE (trev, tpath) ON CONFLICT REPLACE"
1397 ");"
 
 
 
 
 
 
1398 "CREATE TEMP TABLE xtags("
1399 " trev INT, ttag TEXT"
1400 ");"
1401 );
1402 svn_dump_import(pIn, flatFlag);
1403 }
1404
 
1405 db_end_transaction(0);
1406 db_begin_transaction();
1407 fossil_print("Rebuilding repository meta-data...\n");
1408 rebuild_db(0, 1, !incrFlag);
1409 verify_cancel();
1410
--- src/import.c
+++ src/import.c
@@ -717,10 +717,19 @@
717 trim_newline(zLine);
718 fossil_fatal("bad fast-import line: [%s]", zLine);
719 return;
720 }
721
722 static struct{
723 int rev; /* SVN revision number */
724 int parent; /* SVN revision number of parent check-in */
725 char *zBranch; /* Name of a branch for a commit */
726 char *zDate; /* Date/time stamp */
727 char *zUser; /* User name */
728 char *zComment; /* Comment of a commit */
729 int flatFlag; /* True if whole repo is a single file tree */
730 } gsvn;
731 typedef struct {
732 const char *zKey;
733 const char *zVal;
734 } KeyVal;
735 typedef struct {
@@ -880,133 +889,117 @@
889 rec->contentFlag = 0;
890 }
891 return 1;
892 }
893
894 static void svn_create_manifest(
895 ){
896 Blob manifest;
897 static Stmt insRev;
898 static Stmt qParent;
899 static Stmt qFiles;
900 static Stmt qTags;
901 char zFilter[200];
902 int nFilter;
903 int rid;
904 const char *zParentBranch = 0;
905 Blob mcksum;
906
907 db_static_prepare(&insRev, "REPLACE INTO xrevisions (trev, tbranch, tuuid) "
908 "VALUES(:rev, :branch, "
909 " (SELECT uuid FROM blob WHERE rid=:rid))");
910 db_static_prepare(&qParent, "SELECT tuuid, tbranch FROM xrevisions "
911 "WHERE trev=:rev");
912 db_static_prepare(&qFiles, "SELECT tpath, trid, tperm FROM xfiles "
913 "WHERE tpath GLOB :filter ORDER BY tpath");
914 db_static_prepare(&qTags, "SELECT ttag FROM xtags WHERE trev=:rev");
915 if( db_int(0, "SELECT 1 FROM xfiles LIMIT 1")==0 ){ return; }
916 if( !gsvn.flatFlag ){
917 if( gsvn.zBranch==0 || gsvn.zBranch[0]=='\0' ){ return; }
918 if( gsvn.parent<0 ){
919 gsvn.parent = db_int(-1, "SELECT ifnull(max(trev),-1) FROM xrevisions "
920 "WHERE tbranch=%Q", gsvn.zBranch);
921 }
922 db_bind_int(&insRev, ":rev", gsvn.rev);
923 db_bind_text(&insRev, ":branch", gsvn.zBranch);
924 db_bind_int(&insRev, ":rid", 0);
925 db_step(&insRev);
926 db_reset(&insRev);
927 }else{
928 static int prevRev = -1;
929 gsvn.parent = prevRev;
930 prevRev = gsvn.rev;
931 }
932 blob_zero(&manifest);
933 if( gsvn.zComment ){
934 blob_appendf(&manifest, "C %F\n", gsvn.zComment);
935 }else{
936 blob_append(&manifest, "C (no\\scomment)\n", 16);
937 }
938 blob_appendf(&manifest, "D %s\n", gsvn.zDate);
939 if( strncmp(gsvn.zBranch, "trunk", 5)==0 ){
940 memcpy(zFilter, "trunk/*", 8);
941 nFilter = 6;
942 }else{
943 sqlite3_snprintf(sizeof(zFilter), zFilter, "branches/%s/*", gsvn.zBranch);
944 nFilter = strlen(zFilter)-1;
945 }
946 db_bind_text(&qFiles, ":filter", zFilter);
947 while( db_step(&qFiles)==SQLITE_ROW ){
948 const char *zFile = db_column_text(&qFiles, 0);
949 int rid = db_column_int(&qFiles, 1);
950 const char *zPerm = db_column_text(&qFiles, 2);
951 const char *zUuid;
952 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
953 blob_appendf(&manifest, "F %F %s %s\n", zFile+nFilter, zUuid, zPerm);
954 fossil_free(zUuid);
955 }
956 if( gsvn.parent>=0 ){
957 const char *zParentUuid;
958 db_bind_int(&qParent, ":rev", gsvn.parent);
959 db_step(&qParent);
960 zParentUuid = db_column_text(&qParent, 0);
961 blob_appendf(&manifest, "P %s\n", zParentUuid);
962 if( !gsvn.flatFlag ){
963 zParentBranch = db_column_text(&qParent, 1);
964 if( strcmp(gsvn.zBranch, zParentBranch)!=0 ){
965 blob_appendf(&manifest, "T *branch * %s\n", gsvn.zBranch);
966 blob_appendf(&manifest, "T *sym-%s *\n", gsvn.zBranch);
967 zParentBranch = mprintf("%s", zParentBranch);
968 }else{
969 zParentBranch = 0;
970 }
971 }
972 }else{
973 blob_appendf(&manifest, "T *branch * trunk\n");
974 blob_appendf(&manifest, "T *sym-trunk *\n");
975 }
976 db_bind_int(&qTags, ":rev", gsvn.rev);
977 while( db_step(&qTags)==SQLITE_ROW ){
978 const char *zTag = db_column_text(&qTags, 0);
979 blob_appendf(&manifest, "T +sym-%s *\n", zTag);
980 }
981 blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", gsvn.rev);
982 if( zParentBranch ) {
983 blob_appendf(&manifest, "T -sym-%s *\n", zParentBranch);
984 }
985 if( gsvn.zUser ){
986 blob_appendf(&manifest, "U %F\n", gsvn.zUser);
987 }else{
988 const char *zUserOvrd = find_option("user-override",0,1);
989 blob_appendf(&manifest, "U %F\n", zUserOvrd ? zUserOvrd : login_name());
990 }
991 md5sum_blob(&manifest, &mcksum);
992 blob_appendf(&manifest, "Z %b\n", &mcksum);
993 blob_reset(&mcksum);
994
995 rid = content_put(&manifest);
996 blob_reset(&manifest);
997 db_bind_int(&insRev, ":rev", gsvn.rev);
998 db_bind_text(&insRev, ":branch", gsvn.zBranch);
999 db_bind_int(&insRev, ":rid", rid);
1000 db_step(&insRev);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1001 }
1002
1003 static u64 svn_get_varint(const char **pz){
1004 unsigned int v = 0;
1005 do{
@@ -1062,23 +1055,18 @@
1055
1056 /*
1057 ** Read the svn-dump format from pIn and insert the corresponding
1058 ** content into the database.
1059 */
1060 static void svn_dump_import(FILE *pIn){
1061 SvnRecord rec;
1062 int ver;
1063 const char *zTemp;
1064 const char *zUuid;
1065 Stmt addHist;
 
 
1066 Stmt insTag;
1067 Stmt cpyPath;
 
 
 
1068
1069 /* version */
1070 if( svn_read_rec(pIn, &rec)
1071 && (zTemp = svn_find_header(rec, "SVN-fs-dump-format-version")) ){
1072 ver = atoi(zTemp);
@@ -1093,71 +1081,55 @@
1081 if( !svn_read_rec(pIn, &rec) || !(zUuid = svn_find_header(rec, "UUID")) ){
1082 fossil_fatal("Missing UUID!");
1083 }
1084 svn_free_rec(&rec);
1085 /* content */
1086 db_prepare(&addHist,
1087 "INSERT INTO xhist (trev, tpath, trid, tperm) "
1088 "VALUES(:rev, :path, :rid, :perm)"
 
 
 
 
1089 );
1090 db_prepare(&insTag, "INSERT INTO xtags (trev, ttag) VALUES(:rev, :tag)");
1091 db_prepare(&cpyPath,
1092 "WITH xsrc AS (SELECT * FROM ("
1093 " SELECT tpath, trid, tperm, max(trev) trev FROM xhist"
1094 " WHERE trev<=:srcrev GROUP BY tpath"
1095 " ) WHERE trid NOTNULL)"
1096 "INSERT INTO xhist (trev, tpath, trid, tperm)"
1097 " SELECT :rev, :path||substr(tpath, length(:srcpath)+1), trid, tperm"
1098 " FROM xsrc WHERE tpath>:srcpath||'/' AND tpath<:srcpath||0"
1099 );
1100 gsvn.rev = -1;
 
 
 
1101 while( svn_read_rec(pIn, &rec) ){
1102 if( (zTemp = svn_find_header(rec, "Revision-number")) ){ /* revision node */
1103 /* finish previous revision */
1104 if( gsvn.rev>=0 ){
1105 svn_create_manifest();
1106 fossil_free(gsvn.zUser);
1107 fossil_free(gsvn.zComment);
1108 fossil_free(gsvn.zDate);
1109 fossil_free(gsvn.zBranch);
1110 }
1111 /* start new revision */
1112 gsvn.rev = atoi(zTemp);
1113 gsvn.zUser = mprintf("%s", svn_find_prop(rec, "svn:author"));
1114 gsvn.zComment = mprintf("%s", svn_find_prop(rec, "svn:log"));
1115 gsvn.zDate = date_in_standard_format(svn_find_prop(rec, "svn:date"));
1116 gsvn.parent = -1;
1117 gsvn.zBranch = 0;
1118 fossil_print("\rImporting SVN revision: %d", gsvn.rev);
1119 db_bind_int(&addHist, ":rev", gsvn.rev);
1120 db_bind_int(&cpyPath, ":rev", gsvn.rev);
1121 }else
1122 if( (zTemp = svn_find_header(rec, "Node-path")) ){ /* file/dir node */
 
 
 
 
 
 
 
 
1123 const char *zPath = zTemp;
1124 const char *zAction = svn_find_header(rec, "Node-action");
1125 const char *zKind = svn_find_header(rec, "Node-kind");
1126 const char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path");
1127 const char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0;
1128 int deltaFlag = 0;
1129 int srcRev = 0;
1130 if( (zTemp = svn_find_header(rec, "Text-delta")) ){
 
1131 deltaFlag = strncmp(zTemp, "true", 4)==0;
1132 }
1133 if( zSrcPath ){
1134 zTemp = svn_find_header(rec, "Node-copyfrom-rev");
1135 if( zTemp ){
@@ -1164,53 +1136,56 @@
1136 srcRev = atoi(zTemp);
1137 }else{
1138 fossil_fatal("Missing copyfrom-rev");
1139 }
1140 }
1141 if( !gsvn.flatFlag ){
1142 if( strncmp(zPath, "branches/", 9)==0 ){
1143 int nBranch;
1144 zTemp = zPath+9;
1145 while( *zTemp && *zTemp!='/' ){ zTemp++; }
1146 nBranch = zTemp-zPath+9;
1147 gsvn.zBranch = fossil_malloc(nBranch+1);
1148 memcpy(gsvn.zBranch, zPath+9, nBranch);
1149 gsvn.zBranch[nBranch] = '\0';
1150 }else
1151 if( strncmp(zPath, "trunk/", 6)==0 ){
1152 gsvn.zBranch = mprintf("trunk");
1153 }else
1154 if( strncmp(zPath, "tags/", 5)!=0
1155 && strcmp(zPath, "branches")!=0
1156 && strcmp(zPath, "trunk")!=0
1157 && strcmp(zPath, "tags")!=0){
1158 fossil_fatal("Write outside repository layout: %s", zPath);
1159 }
1160 }
1161 if( strncmp(zAction, "delete", 6)==0
1162 || strncmp(zAction, "replace", 7)==0 )
1163 {
1164 db_bind_null(&addHist, ":rid");
1165 db_bind_text(&addHist, ":path", zPath);
1166 db_bind_null(&addHist, ":perm");
1167 db_step(&addHist);
1168 db_reset(&addHist);
1169 } /* no 'else' here since 'replace' does both a 'delete' and an 'add' */
1170 if( strncmp(zAction, "add", 3)==0
1171 || strncmp(zAction, "replace", 7)==0 )
1172 {
1173 if( zKind==0 ){
1174 fossil_fatal("Missing Node-kind");
1175 }else if( strncmp(zKind, "dir", 3)==0 ){
1176 if( zSrcPath ){
1177 db_bind_int(&cpyPath, ":srcrev", srcRev);
1178 db_bind_text(&cpyPath, ":path", zPath);
1179 db_bind_text(&cpyPath, ":srcpath", zSrcPath);
1180 db_step(&cpyPath);
1181 db_reset(&cpyPath);
1182 if( !gsvn.flatFlag ){
 
 
1183 if( strncmp(zPath, "branches/", 9)==0 ){
1184 zTemp = zPath+9+strlen(gsvn.zBranch);
 
1185 if( *zTemp==0 ){
1186 gsvn.parent = srcRev;
 
 
 
1187 }
1188 }else if( strncmp(zPath, "tags/", 5)==0 ){
1189 zTemp = zPath+5;
1190 db_bind_int(&insTag, ":rev", srcRev);
1191 db_bind_text(&insTag, ":tag", zTemp);
@@ -1218,14 +1193,17 @@
1193 db_reset(&insTag);
1194 }
1195 }
1196 }
1197 }else{
1198 int rid = 0;
1199 if( zSrcPath ){
1200 rid = db_int(0, "SELECT trid, max(trev) FROM xhist"
1201 " WHERE trev<=%d AND tpath=%Q", srcRev, zSrcPath);
1202 if( rid==0 ){
1203 fossil_fatal("Reference to non-existent path/revision");
1204 }
1205 }
1206 if( deltaFlag ){
1207 Blob deltaSrc;
1208 Blob target;
1209 if( rid!=0 ){
@@ -1236,64 +1214,58 @@
1214 svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1215 rid = content_put(&target);
1216 }else if( rec.contentFlag ){
1217 rid = content_put(&rec.content);
1218 }
1219 db_bind_int(&addHist, ":rid", rid);
1220 db_bind_text(&addHist, ":path", zPath);
1221 db_bind_text(&addHist, ":perm", zPerm);
1222 db_step(&addHist);
1223 db_reset(&addHist);
 
1224 }
1225 }else
1226 if( strncmp(zAction, "change", 6)==0 ){
1227 int rid = 0;
1228 if( zKind==0 ){
1229 fossil_fatal("Missing Node-kind");
1230 }
1231 if( strncmp(zKind, "dir", 3)==0 ) continue;
1232 if( deltaFlag ){
1233 Blob deltaSrc;
1234 Blob target;
1235 rid = db_int(0, "SELECT trid, max(trev) FROM xhist"
1236 " WHERE trev<=%d AND tpath=%Q", gsvn.rev-1, zPath);
1237 content_get(rid, &deltaSrc);
1238 svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1239 rid = content_put(&target);
1240 }else{
1241 rid = content_put(&rec.content);
1242 }
1243 db_bind_int(&addHist, ":rid", rid);
1244 db_bind_text(&addHist, ":path", zPath);
1245 db_bind_text(&addHist, ":perm", zPerm);
1246 db_step(&addHist);
1247 db_reset(&addHist);
 
1248 }else
1249 if( strncmp(zAction, "delete", 6)!=0 ){ /* already did this above */
 
1250 fossil_fatal("Unknown Node-action");
1251 }
1252 }else{
1253 fossil_fatal("Unknown record type");
1254 }
1255 svn_free_rec(&rec);
1256 }
1257 if( gsvn.rev>0 ){
1258 svn_create_manifest();
1259 }
1260 fossil_free(gsvn.zUser);
1261 fossil_free(gsvn.zComment);
1262 fossil_free(gsvn.zDate);
1263 db_finalize(&addHist);
 
 
1264 db_finalize(&insTag);
1265 db_finalize(&cpyPath);
1266 fossil_print(" Done!\n");
 
 
1267 }
1268
1269 /*
1270 ** COMMAND: import
1271 **
@@ -1325,11 +1297,11 @@
1297 char *zPassword;
1298 FILE *pIn;
1299 Stmt q;
1300 int forceFlag = find_option("force", "f", 0)!=0;
1301 int incrFlag = find_option("incremental", "i", 0)!=0;
1302 gsvn.flatFlag = find_option("flat", 0, 0)!=0;
1303
1304 verify_all_options();
1305 if( g.argc!=4 && g.argc!=5 ){
1306 usage("FORMAT REPOSITORY-NAME");
1307 }
@@ -1386,24 +1358,34 @@
1358 db_finalize(&q);
1359 }else
1360 if( strncmp(g.argv[2], "svn", 3)==0 ){
1361 db_multi_exec(
1362 "CREATE TEMP TABLE xrevisions("
1363 " trev INTEGER PRIMARY KEY, tbranch TEXT, tuuid TEXT"
1364 ");"
1365 "CREATE TEMP TABLE xhist("
1366 " trev INT, tpath TEXT NOT NULL, trid TEXT, tperm TEXT,"
1367 " UNIQUE (trev, tpath) ON CONFLICT REPLACE"
1368 ");"
1369 "CREATE TEMP TABLE xfiles("
1370 " tpath TEXT NOT NULL, trid TEXT, tperm TEXT,"
1371 " UNIQUE (tpath) ON CONFLICT REPLACE"
1372 ");"
1373 "CREATE TEMP TRIGGER xfilesdeltrig AFTER INSERT ON xhist FOR EACH ROW"
1374 " WHEN new.trid ISNULL"
1375 " BEGIN DELETE FROM xfiles WHERE xfiles.tpath=new.tpath; END;"
1376 "CREATE TEMP TRIGGER xfilesaddtrig AFTER INSERT ON xhist FOR EACH ROW"
1377 " WHEN new.trid NOTNULL BEGIN INSERT INTO xfiles(tpath,trid,tperm)"
1378 " VALUES(new.tpath, new.trid, new.tperm); END;"
1379 "CREATE TEMP TABLE xtags("
1380 " trev INT, ttag TEXT"
1381 ");"
1382 );
1383 svn_dump_import(pIn);
1384 }
1385
1386 verify_cancel();
1387 db_end_transaction(0);
1388 db_begin_transaction();
1389 fossil_print("Rebuilding repository meta-data...\n");
1390 rebuild_db(0, 1, !incrFlag);
1391 verify_cancel();
1392

Keyboard Shortcuts

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