Fossil with Commonmark

Check-in [9604c28207]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Working on fixing/rewriting svn-import function. This is not in a stable state yet. DO NOT TEST
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | svn-import
Files: files | file ages | folders
SHA1:9604c28207d0aea31510a2c717d94c2c5e4fcf0e
User & Date: baruch 2014-12-31 15:46:06
Context
2014-12-31
23:33
More work. Still not usable check-in: 2ea79975b6 user: baruch tags: svn-import
15:46
Working on fixing/rewriting svn-import function. This is not in a stable state yet. DO NOT TEST check-in: 9604c28207 user: baruch tags: svn-import
2014-12-24
09:00
merge trunk check-in: 2caad83d8c user: baruch tags: svn-import
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/foci.c.

    23     23   #include "config.h"
    24     24   #include "foci.h"
    25     25   #include <assert.h>
    26     26   
    27     27   /*
    28     28   ** The schema for the virtual table:
    29     29   */
    30         -static const char zFociSchema[] = 
           30  +static const char zFociSchema[] =
    31     31   @ CREATE TABLE files_of_checkin(
    32     32   @  checkinID    INTEGER,    -- RID for the checkin manifest
    33     33   @  filename     TEXT,       -- Name of a file
    34     34   @  uuid         TEXT,       -- SHA1 hash of the file
    35     35   @  previousName TEXT,       -- Name of the file in previous checkin
    36         -@  prem         TEXT        -- Permissions on the file
           36  +@  perm         TEXT        -- Permissions on the file
    37     37   @ );
    38     38   ;
    39     39   
    40     40   #if INTERFACE
    41     41   /*
    42     42   ** The subclasses of sqlite3_vtab  and sqlite3_vtab_cursor tables
    43     43   ** that implement the files_of_checkin virtual table.
................................................................................
   137    137   
   138    138   static int fociEof(sqlite3_vtab_cursor *pCursor){
   139    139     FociCursor *pCsr = (FociCursor *)pCursor;
   140    140     return pCsr->pFile==0;
   141    141   }
   142    142   
   143    143   static int fociFilter(
   144         -  sqlite3_vtab_cursor *pCursor, 
          144  +  sqlite3_vtab_cursor *pCursor,
   145    145     int idxNum, const char *idxStr,
   146    146     int argc, sqlite3_value **argv
   147    147   ){
   148    148     FociCursor *pCur = (FociCursor *)pCursor;
   149    149     manifest_destroy(pCur->pMan);
   150    150     if( idxNum ){
   151    151       pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0);
................................................................................
   156    156       pCur->pMan = 0;
   157    157       pCur->iFile = 0;
   158    158     }
   159    159     return SQLITE_OK;
   160    160   }
   161    161   
   162    162   static int fociColumn(
   163         -  sqlite3_vtab_cursor *pCursor, 
   164         -  sqlite3_context *ctx, 
          163  +  sqlite3_vtab_cursor *pCursor,
          164  +  sqlite3_context *ctx,
   165    165     int i
   166    166   ){
   167    167     FociCursor *pCsr = (FociCursor *)pCursor;
   168    168     switch( i ){
   169    169       case 0:            /* checkinID */
   170    170         sqlite3_result_int(ctx, pCsr->pMan->rid);
   171    171         break;

Changes to src/import.c.

    10     10   ** merchantability or fitness for a particular purpose.
    11     11   **
    12     12   ** Author contact information:
    13     13   **   drh@sqlite.org
    14     14   **
    15     15   *******************************************************************************
    16     16   **
    17         -** This file contains code used to import the content of a Git
    18         -** repository in the git-fast-import format as a new Fossil
           17  +** This file contains code used to import the content of a Git/SVN
           18  +** repository in the git-fast-import/svn-dump formats as a new Fossil
    19     19   ** repository.
    20     20   */
    21     21   #include "config.h"
    22     22   #include "import.h"
    23     23   #include <assert.h>
    24     24   
    25     25   #if INTERFACE
................................................................................
   716    716   malformed_line:
   717    717     trim_newline(zLine);
   718    718     fossil_fatal("bad fast-import line: [%s]", zLine);
   719    719     return;
   720    720   }
   721    721   
   722    722   static struct{
   723         -  int rev;                    /* SVN revision number */
   724         -  int parentRev;              /* SVN revision number of parent check-in */
   725         -  char *zParentBranch;        /* Name of branch of parent check-in */
   726    723     char *zBranch;              /* Name of a branch for a commit */
   727    724     char *zDate;                /* Date/time stamp */
   728    725     char *zUser;                /* User name */
   729    726     char *zComment;             /* Comment of a commit */
   730         -  int flatFlag;               /* True if whole repo is a single file tree */
          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 */
   731    832     const char *zTrunk;         /* Name of trunk folder in repo root */
   732    833     int lenTrunk;               /* String length of zTrunk */
   733    834     const char *zBranches;      /* Name of branches folder in repo root */
   734    835     int lenBranches;            /* String length of zBranches */
   735    836     const char *zTags;          /* Name of tags folder in repo root */
   736    837     int lenTags;                /* String length of zTags */
   737         -  Blob filter;                /* Path to repo root */
   738    838   } gsvn;
   739    839   typedef struct {
   740    840     char *zKey;
   741    841     const char *zVal;
   742    842   } KeyVal;
   743    843   typedef struct {
   744    844     KeyVal *aHeaders;
................................................................................
   772    872     int i;
   773    873     for(i=0; i<rec->nHeaders; i++){
   774    874       fossil_free(rec->aHeaders[i].zKey);
   775    875     }
   776    876     fossil_free(rec->aHeaders);
   777    877     fossil_free(rec->aProps);
   778    878     fossil_free(rec->pRawProps);
   779         -  blob_reset(&rec->content);  
          879  +  blob_reset(&rec->content);
   780    880   }
   781    881   
   782    882   static int svn_read_headers(FILE *pIn, SvnRecord *rec){
   783    883     char zLine[1000];
   784    884   
   785    885     rec->aHeaders = 0;
   786    886     rec->nHeaders = 0;
................................................................................
   901   1001       }
   902   1002     }else{
   903   1003       rec->contentFlag = 0;
   904   1004     }
   905   1005     return 1;
   906   1006   }
   907   1007   
   908         -static void svn_create_manifest(
         1008  +static void svn_finish_revision(
   909   1009   ){
   910   1010     Blob manifest;
   911   1011     static Stmt insRev;
   912   1012     static Stmt qParent;
   913   1013     static Stmt qParent2;
   914   1014     static Stmt qFiles;
   915   1015     static Stmt qTags;
................................................................................
  1107   1207           *zOut++ = *zCpy++;
  1108   1208         }
  1109   1209       }
  1110   1210       zDiff += lenData;
  1111   1211     }
  1112   1212   }
  1113   1213   
  1114         -static char *svn_extract_branch(const char *zPath){
  1115         -  int nFilter = blob_size(&gsvn.filter);
  1116         -  char *zBranch = 0;
  1117         -  if( strncmp(zPath, blob_str(&gsvn.filter), nFilter)==0 ){
  1118         -    if( strncmp(zPath+nFilter, gsvn.zBranches, gsvn.lenBranches)==0 ){
  1119         -      int lenBranch;
  1120         -      const char *zTemp = zPath+nFilter+gsvn.lenBranches;
  1121         -      while( *zTemp && *zTemp!='/' ){ zTemp++; }
  1122         -      lenBranch = zTemp-(zPath+nFilter+gsvn.lenBranches);
  1123         -      zTemp = zPath+nFilter+gsvn.lenBranches;
  1124         -      zBranch = fossil_malloc(lenBranch+1);
  1125         -      memcpy(zBranch, zTemp, lenBranch);
  1126         -      zBranch[lenBranch] = '\0';
  1127         -    }else
  1128         -    if( strncmp(zPath+nFilter, gsvn.zTrunk, gsvn.lenTrunk-1)==0 ){
  1129         -      zBranch = mprintf("trunk");
         1214  +/*
         1215  +** Extract the name of the branch or tag that the given path is on.
         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)++; }
         1230  +    if( *zFile ){
         1231  +      **zFile = '\0';
         1232  +      (*zFile)++;
         1233  +    }else{
         1234  +      *zFile = 0;
         1235  +    }
         1236  +    return 2;
         1237  +  }else
         1238  +  if( strncmp(zPath, gsvn.zTags, gsvn.lenTags)==0 ){
         1239  +    *zFile = *zBranch = zPath+gsvn.lenTags;
         1240  +    while( **zFile && **zFile!='/' ){ (*zFile)++; }
         1241  +    if( *zFile ){
         1242  +      **zFile = '\0';
         1243  +      (*zFile)++;
         1244  +    }else{
         1245  +      *zFile = 0;
  1130   1246       }
         1247  +    return 3;
  1131   1248     }
  1132         -  return zBranch;
         1249  +  *zFile = *zBranch = 0;
         1250  +  return 0;
  1133   1251   }
  1134   1252   
  1135   1253   /*
  1136   1254   ** Read the svn-dump format from pIn and insert the corresponding
  1137   1255   ** content into the database.
  1138   1256   */
  1139   1257   static void svn_dump_import(FILE *pIn){
  1140   1258     SvnRecord rec;
  1141   1259     int ver;
  1142         -  const char *zTemp;
         1260  +  char *zTemp;
  1143   1261     const char *zUuid;
  1144         -  Stmt addHist;
  1145         -  Stmt insTag;
  1146         -  Stmt cpyPath;
         1262  +  Stmt addFile;
  1147   1263     Stmt delPath;
  1148         -  int bHasFiles = 0;
  1149         -  int nFilter = blob_size(&gsvn.filter);
         1264  +  Stmt addSrc;
         1265  +  Stmt addBranch;
         1266  +  Stmt cpyPath;
  1150   1267   
  1151   1268     /* version */
  1152   1269     if( svn_read_rec(pIn, &rec)
  1153   1270      && (zTemp = svn_find_header(rec, "SVN-fs-dump-format-version")) ){
  1154   1271       ver = atoi(zTemp);
  1155   1272       if( ver!=2 && ver!=3 ){
  1156   1273         fossil_fatal("Unknown svn-dump format version: %d", ver);
................................................................................
  1160   1277     }
  1161   1278     svn_free_rec(&rec);
  1162   1279     /* UUID */
  1163   1280     if( !svn_read_rec(pIn, &rec) || !(zUuid = svn_find_header(rec, "UUID")) ){
  1164   1281       fossil_fatal("Missing UUID!");
  1165   1282     }
  1166   1283     svn_free_rec(&rec);
         1284  +
  1167   1285     /* content */
  1168         -  db_prepare(&addHist,
  1169         -    "INSERT INTO xhist (trev, tpath, trid, tperm) "
  1170         -    "VALUES(:rev, :path, :rid, :perm)"
  1171         -  );
  1172         -  db_prepare(&insTag, "INSERT INTO xtags (trev, ttag) VALUES(:rev, :tag)");
  1173         -  db_prepare(&cpyPath,
  1174         -    "WITH xsrc AS (SELECT * FROM ("
  1175         -    "  SELECT tpath, trid, tperm, max(trev) trev FROM xhist"
  1176         -    "  WHERE trev<=:srcrev GROUP BY tpath"
  1177         -    " ) WHERE trid NOTNULL)"
  1178         -    "INSERT INTO xhist (trev, tpath, trid, tperm)"
  1179         -    " SELECT :rev, :path||substr(tpath, length(:srcpath)+1), trid, tperm"
  1180         -    " FROM xsrc WHERE tpath>:srcpath||'/' AND tpath<:srcpath||'0'"
         1286  +  db_prepare(&addFile,
         1287  +    "INSERT INTO xfiles (tpath, tbranch, tuuid, tperm)"
         1288  +    " VALUES(:path, :branch, :uuid, :perm)"
  1181   1289     );
  1182   1290     db_prepare(&delPath,
  1183         -    "INSERT INTO xhist (trev, tpath, trid, tperm)"
  1184         -    " SELECT :rev, tpath, NULL, NULL"
  1185         -    " FROM xfiles WHERE (tpath>:path||'/' AND tpath<:path||'0') OR tpath=:path"
         1291  +    "DELETE FROM xfiles"
         1292  +    " WHERE (tpath=:path OR (tpath>:path||'/' AND tpath<:path||'0'))"
         1293  +    "     AND tbranch=:branch"
         1294  +  );
         1295  +  db_prepare(&addSrc,
         1296  +    "INSERT INTO xsrc (tpath, tbranch, tsrc, tsrcbranch, tsrcrev)"
         1297  +    " VALUES(:path, :branch, :srcpath, :srcbranch, :srcrev)"
         1298  +  );
         1299  +  db_prepare(&addBranch,
         1300  +    "INSERT INTO xchanges (tbranch, ttype) VALUES(:branch, :type)"
         1301  +  );
         1302  +  db_prepare(&cpyPath,
         1303  +    "INSERT INTO xfiles (tpath, tbranch, tuuid, tperm)"
         1304  +    " SELECT :path||substr(filename, length(:srcpath)+1), :branch, uuid, perm"
         1305  +    " FROM xfoci"
         1306  +    " WHERE chekinID=:rid AND filename>:srcpath||'/' AND filename<:srcpath||'0'"
  1186   1307     );
  1187   1308     gsvn.rev = -1;
  1188   1309     while( svn_read_rec(pIn, &rec) ){
  1189   1310       if( (zTemp = svn_find_header(rec, "Revision-number")) ){ /* revision node */
  1190   1311         /* finish previous revision */
  1191   1312         const char *zDate = NULL;
  1192         -      if( bHasFiles ){
  1193         -        svn_create_manifest();
         1313  +      if( gsvn.rev>=0 ){
         1314  +        svn_finish_revision();
         1315  +        fossil_free(gsvn.zUser);
         1316  +        fossil_free(gsvn.zComment);
         1317  +        fossil_free(gsvn.zDate);
  1194   1318         }
  1195         -      fossil_free(gsvn.zUser);
  1196         -      fossil_free(gsvn.zComment);
  1197         -      fossil_free(gsvn.zDate);
  1198         -      fossil_free(gsvn.zBranch);
  1199         -      fossil_free(gsvn.zParentBranch);
  1200   1319         /* start new revision */
  1201   1320         gsvn.rev = atoi(zTemp);
  1202   1321         gsvn.zUser = mprintf("%s", svn_find_prop(rec, "svn:author"));
  1203   1322         gsvn.zComment = mprintf("%s", svn_find_prop(rec, "svn:log"));
  1204   1323         zDate = svn_find_prop(rec, "svn:date");
  1205   1324         if( zDate ){
  1206         -        gsvn.zDate = date_in_standard_format(zDate);
         1325  +        zDate = date_in_standard_format(zDate);
  1207   1326         }
  1208         -      gsvn.parentRev = -1;
  1209         -      gsvn.zParentBranch = 0;
  1210         -      gsvn.zBranch = 0;
  1211         -      bHasFiles = 0;
         1327  +      gsvn.zDate = zDate;
  1212   1328         fossil_print("\rImporting SVN revision: %d", gsvn.rev);
  1213         -      db_bind_int(&addHist, ":rev", gsvn.rev);
  1214         -      db_bind_int(&cpyPath, ":rev", gsvn.rev);
  1215         -      db_bind_int(&delPath, ":rev", gsvn.rev);
  1216   1329       }else
  1217   1330       if( (zTemp = svn_find_header(rec, "Node-path")) ){ /* file/dir node */
  1218         -      const char *zPath = zTemp;
  1219   1331         const char *zAction = svn_find_header(rec, "Node-action");
  1220   1332         const char *zKind = svn_find_header(rec, "Node-kind");
  1221   1333         const char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path");
  1222   1334         const char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0;
         1335  +      char *zBranch;
         1336  +      char *zFile;
         1337  +      char *zSrcBranch;
         1338  +      char *zSrcFile;
  1223   1339         int deltaFlag = 0;
  1224   1340         int srcRev = 0;
         1341  +      int branchType = svn_parse_path(zTemp, &zBranch, &zFile);
         1342  +      if( branchType==0 ){
         1343  +        svn_free_rec(&rec);
         1344  +        continue;
         1345  +      }
         1346  +      db_bind_text(&addBranch, ":branch", zBranch);
         1347  +      db_bind_int(&addBranch, ":type", branchType);
         1348  +      db_step(&addBranch);
         1349  +      db_reset(&addBranch);
  1225   1350         if( (zTemp = svn_find_header(rec, "Text-delta")) ){
  1226   1351           deltaFlag = strncmp(zTemp, "true", 4)==0;
  1227   1352         }
  1228   1353         if( zSrcPath ){
  1229   1354           zTemp = svn_find_header(rec, "Node-copyfrom-rev");
  1230   1355           if( zTemp ){
  1231   1356             srcRev = atoi(zTemp);
  1232   1357           }else{
  1233   1358             fossil_fatal("Missing copyfrom-rev");
  1234   1359           }
  1235         -      }
  1236         -      if( !gsvn.flatFlag ){
  1237         -        char *zBranch;
  1238         -        if( (zBranch=svn_extract_branch(zPath))!=0 ){
  1239         -          if( gsvn.zBranch!=0 ){
  1240         -            if( strcmp(zBranch, gsvn.zBranch)!=0
  1241         -             && strncmp(zAction, "delete", 6)!=0)
  1242         -            {
  1243         -              fossil_fatal("Commit to multiple branches");
  1244         -            }
  1245         -            fossil_free(zBranch);
  1246         -          }else{
  1247         -            gsvn.zBranch = zBranch;
  1248         -          }
         1360  +        if( svn_extract_branch(zSrcPath, &zSrcBranch, &zSrcFile)==0 ){
         1361  +          fossil_fatal("Copy from path outside the import paths");
  1249   1362           }
         1363  +        db_bind_text(&addSrc, ":path", zFile);
         1364  +        db_bind_text(&addSrc, ":branch", zBranch);
         1365  +        db_bind_text(&addSrc, ":srcpath", zSrcFile);
         1366  +        db_bind_text(&addSrc, ":srcbranch", zSrcBranch);
         1367  +        db_bind_int(&addSrc, ":srcrev", srcRev);
         1368  +        db_step(&addSrc);
         1369  +        db_reset(&addSrc);
  1250   1370         }
  1251   1371         if( strncmp(zAction, "delete", 6)==0
  1252   1372          || strncmp(zAction, "replace", 7)==0 )
  1253   1373         {
  1254         -        db_bind_text(&delPath, ":path", zPath);
         1374  +        db_bind_text(&delPath, ":path", zFile);
         1375  +        db_bind_text(&delPath, ":branch", zBranch);
  1255   1376           db_step(&delPath);
  1256   1377           db_reset(&delPath);
  1257         -        bHasFiles = 1;
  1258   1378         } /* no 'else' here since 'replace' does both a 'delete' and an 'add' */
  1259   1379         if( strncmp(zAction, "add", 3)==0
  1260   1380          || strncmp(zAction, "replace", 7)==0 )
  1261   1381         {
  1262   1382           if( zKind==0 ){
  1263   1383             fossil_fatal("Missing Node-kind");
  1264   1384           }else if( strncmp(zKind, "dir", 3)==0 ){
  1265   1385             if( zSrcPath ){
  1266         -            db_bind_int(&cpyPath, ":srcrev", srcRev);
  1267         -            db_bind_text(&cpyPath, ":path", zPath);
  1268         -            db_bind_text(&cpyPath, ":srcpath", zSrcPath);
         1386  +            int srcRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions"
         1387  +                                   " WHERE trev<=%d AND tbranch=%Q",
         1388  +                                srcRev, zSrcBranch);
         1389  +            db_bind_text(&cpyPath, ":path", zFile);
         1390  +            db_bind_text(&cpyPath, ":branch", zBranch);
         1391  +            db_bind_text(&cpyPath, ":srcpath", zSrcFile);
         1392  +            db_bind_int(&cpyPath, ":rid", srcRid);
  1269   1393               db_step(&cpyPath);
  1270   1394               db_reset(&cpyPath);
  1271         -            bHasFiles = 1;
  1272         -            if( !gsvn.flatFlag ){
  1273         -              if( strncmp(zPath+nFilter, gsvn.zBranches, gsvn.lenBranches)==0 ){
  1274         -                zTemp = zPath+nFilter+gsvn.lenBranches+strlen(gsvn.zBranch);
  1275         -                if( *zTemp==0 ){
  1276         -                  gsvn.parentRev = srcRev;
  1277         -                  gsvn.zParentBranch = svn_extract_branch(zSrcPath);
  1278         -                }
  1279         -              }else if( strncmp(zPath+nFilter, gsvn.zTags, gsvn.lenTags)==0 ){
  1280         -                zTemp = zPath+nFilter+gsvn.lenTags;
  1281         -                db_bind_int(&insTag, ":rev", srcRev);
  1282         -                db_bind_text(&insTag, ":tag", zTemp);
  1283         -                db_step(&insTag);
  1284         -                db_reset(&insTag);
  1285         -              }
  1286         -            }
  1287   1395             }
  1288   1396           }else{
  1289   1397             int rid = 0;
  1290   1398             if( zSrcPath ){
  1291         -            rid = db_int(0, "SELECT trid, max(trev) FROM xhist"
  1292         -                            " WHERE trev<=%d AND tpath=%Q", srcRev, zSrcPath);
  1293         -            if( rid==0 ){
  1294         -              fossil_fatal("Reference to non-existent path/revision");
  1295         -            }
         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)
  1296   1405             }
  1297   1406             if( deltaFlag ){
  1298   1407               Blob deltaSrc;
  1299   1408               Blob target;
  1300   1409               if( rid!=0 ){
  1301   1410                 content_get(rid, &deltaSrc);
  1302   1411               }else{
................................................................................
  1336   1445             db_bind_text(&addHist, ":path", zPath);
  1337   1446             db_bind_text(&addHist, ":perm", zPerm);
  1338   1447             db_step(&addHist);
  1339   1448             db_reset(&addHist);
  1340   1449             bHasFiles = 1;
  1341   1450           }
  1342   1451         }else
  1343         -      if( strncmp(zAction, "delete", 6)!=0 ){ /* already did this above */
         1452  +      if( strncmp(zAction, "delete", 6)!=0 ){ /* already did this one above */
  1344   1453           fossil_fatal("Unknown Node-action");
  1345   1454         }
  1346   1455       }else{
  1347   1456         fossil_fatal("Unknown record type");
  1348   1457       }
  1349   1458       svn_free_rec(&rec);
  1350   1459     }
................................................................................
  1372   1481   ** data is read from standard input.
  1373   1482   **
  1374   1483   ** The following formats are currently understood by this command
  1375   1484   **
  1376   1485   **   git          Import from the git-fast-export file format
  1377   1486   **
  1378   1487   **   svn          Import from the svnadmin-dump file format. The default
  1379         -**                behaviour is to treat 3 folders in the SVN root as special,
  1380         -**                following the common layout of SVN repositories. These are
  1381         -**                (by default) trunk/, branches/ and tags/
         1488  +**                behaviour (unless overridden by --flat) is to treat 3 folders
         1489  +**                in the SVN root as special, following the common layout of
         1490  +**                SVN repositories. These are (by default) trunk/, branches/
         1491  +**                and tags/
  1382   1492   **                Options:
  1383   1493   **                  --trunk FOLDER     Name of trunk folder
  1384   1494   **                  --branches FOLDER  Name of branches folder
  1385   1495   **                  --tags FOLDER      Name of tags folder
  1386         -**                  --filter PATH      Path to project root in repository
         1496  +**                  --base PATH        Path to project root in repository
  1387   1497   **                  --flat             The whole dump is a single branch
  1388   1498   **
  1389   1499   ** The --incremental option allows an existing repository to be extended
  1390   1500   ** with new content.
  1391   1501   **
  1392   1502   ** Options:
  1393   1503   **   --incremental  allow importing into an existing repository
................................................................................
  1394   1504   **
  1395   1505   ** See also: export
  1396   1506   */
  1397   1507   void import_cmd(void){
  1398   1508     char *zPassword;
  1399   1509     FILE *pIn;
  1400   1510     Stmt q;
  1401         -  const char *zFilter = find_option("filter", 0, 1);
         1511  +  const char *zBase = find_option("base", 0, 1);
  1402   1512     int lenFilter;
  1403   1513     int forceFlag = find_option("force", "f", 0)!=0;
  1404   1514     int incrFlag = find_option("incremental", "i", 0)!=0;
  1405   1515     gsvn.zTrunk = find_option("trunk", 0, 1);
  1406   1516     gsvn.zBranches = find_option("branches", 0, 1);
  1407   1517     gsvn.zTags = find_option("tags", 0, 1);
  1408         -  gsvn.flatFlag = find_option("flat", 0, 0)!=0;
         1518  +  int flatFlag = find_option("flat", 0, 0)!=0;
  1409   1519   
  1410   1520     verify_all_options();
  1411   1521     if( g.argc!=4  && g.argc!=5 ){
  1412   1522       usage("FORMAT REPOSITORY-NAME");
  1413   1523     }
  1414   1524     if( g.argc==5 ){
  1415   1525       pIn = fossil_fopen(g.argv[4], "rb");
................................................................................
  1462   1572         import_reset(0);
  1463   1573       }
  1464   1574       db_finalize(&q);
  1465   1575     }else
  1466   1576     if( strncmp(g.argv[2], "svn", 3)==0 ){
  1467   1577       db_multi_exec(
  1468   1578          "CREATE TEMP TABLE xrevisions("
  1469         -       " trev INTEGER PRIMARY KEY, tbranch TEXT, tuuid TEXT"
  1470         -       ");"
  1471         -       "CREATE TEMP TABLE xhist("
  1472         -       " trev INT, tpath TEXT NOT NULL, trid TEXT, tperm TEXT,"
  1473         -       " UNIQUE (trev, tpath) ON CONFLICT REPLACE"
         1579  +       " trev INTEGER, tbranch TEXT, trid INT, PRIMARY KEY(tbranch, trev)"
  1474   1580          ");"
  1475   1581          "CREATE TEMP TABLE xfiles("
  1476         -       " tpath TEXT NOT NULL, trid TEXT, tperm TEXT,"
  1477         -       " UNIQUE (tpath) ON CONFLICT REPLACE"
         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"
  1478   1587          ");"
  1479         -       "CREATE TEMP TRIGGER xfilesdeltrig AFTER INSERT ON xhist FOR EACH ROW"
  1480         -       " WHEN new.trid ISNULL"
  1481         -       " BEGIN DELETE FROM xfiles WHERE xfiles.tpath=new.tpath; END;"
  1482         -       "CREATE TEMP TRIGGER xfilesaddtrig AFTER INSERT ON xhist FOR EACH ROW"
  1483         -       " WHEN new.trid NOTNULL BEGIN INSERT INTO xfiles(tpath,trid,tperm)"
  1484         -       " VALUES(new.tpath, new.trid, new.tperm); END;"
  1485         -       "CREATE TEMP TABLE xtags("
  1486         -       " trev INT, ttag TEXT"
         1588  +       "CREATE TEMP TABLE xchanged("
         1589  +       " tbranch TEXT, ttype INT,"
         1590  +       " UNIQUE (tbranch) ON CONFLICT REPLACE"
  1487   1591          ");"
         1592  +       "CREATE VIRTUAL TABLE temp.xfoci USING files_of_checkin;"
  1488   1593       );
  1489         -    if( gsvn.zTrunk==0 ){ gsvn.zTrunk = "trunk/"; }
  1490         -    if( gsvn.zBranches==0 ){ gsvn.zBranches = "branches/"; }
  1491         -    if( gsvn.zTags==0 ){ gsvn.zTags = "tags/"; }
  1492         -    gsvn.lenTrunk = strlen(gsvn.zTrunk);
  1493         -    gsvn.lenBranches = strlen(gsvn.zBranches);
  1494         -    gsvn.lenTags = strlen(gsvn.zTags);
  1495         -    if( gsvn.zTrunk[gsvn.lenTrunk-1]!='/' ){
  1496         -      gsvn.zTrunk = mprintf("%s/", gsvn.zTrunk);
  1497         -      gsvn.lenTrunk++;
         1594  +    if( zBase==0 ){ zBase = ""; }
         1595  +    if( strlen(zBase)>0 ){
         1596  +      if( zBase[strlen(zBase)-1]!='/' ){
         1597  +      zBase = mprintf("%s/", zBase);
  1498   1598       }
  1499         -    if( gsvn.zBranches[gsvn.lenBranches-1]!='/' ){
  1500         -      gsvn.zBranches = mprintf("%s/", gsvn.zBranches);
  1501         -      gsvn.lenBranches++;
  1502         -    }
  1503         -    if( gsvn.zTags[gsvn.lenTags-1]!='/' ){
  1504         -      gsvn.zTags = mprintf("%s/", gsvn.zTags);
  1505         -      gsvn.lenTags++;
  1506         -    }
  1507         -    if( zFilter==0 ){ zFilter = ""; }
  1508         -    lenFilter = strlen(zFilter);
  1509         -    blob_zero(&gsvn.filter);
  1510         -    blob_set(&gsvn.filter, zFilter);
  1511         -    if( lenFilter>0 && zFilter[lenFilter-1]!='/' ){
  1512         -      blob_append(&gsvn.filter, "/", 1);
         1599  +    if( flatFlag ){
         1600  +      gsvn.zTrunk = zBase;
         1601  +      gsvn.zBranches = 0;
         1602  +      gsvn.zTags = 0;
         1603  +      gsvn.lenTrunk = strlen(zBase);
         1604  +      gsvn.lenBranches = 0;
         1605  +      gsvn.lenTags = 0;
         1606  +    }else{
         1607  +      if( gsvn.zTrunk==0 ){ gsvn.zTrunk = "trunk/"; }
         1608  +      if( gsvn.zBranches==0 ){ gsvn.zBranches = "branches/"; }
         1609  +      if( gsvn.zTags==0 ){ gsvn.zTags = "tags/"; }
         1610  +      gsvn.zTrunk = mprintf("%s%s", zBase, gsvn.zTrunk);
         1611  +      gsvn.zBranches = mprintf("%s%s", zBase, gsvn.zBranches);
         1612  +      gsvn.zTags = mprintf("%s%s", zBase, gsvn.zTags);
         1613  +      gsvn.lenTrunk = strlen(gsvn.zTrunk);
         1614  +      gsvn.lenBranches = strlen(gsvn.zBranches);
         1615  +      gsvn.lenTags = strlen(gsvn.zTags);
         1616  +      if( gsvn.zTrunk[gsvn.lenTrunk-1]!='/' ){
         1617  +        gsvn.zTrunk = mprintf("%s/", gsvn.zTrunk);
         1618  +        gsvn.lenTrunk++;
         1619  +      }
         1620  +      if( gsvn.zBranches[gsvn.lenBranches-1]!='/' ){
         1621  +        gsvn.zBranches = mprintf("%s/", gsvn.zBranches);
         1622  +        gsvn.lenBranches++;
         1623  +      }
         1624  +      if( gsvn.zTags[gsvn.lenTags-1]!='/' ){
         1625  +        gsvn.zTags = mprintf("%s/", gsvn.zTags);
         1626  +        gsvn.lenTags++;
         1627  +      }
  1513   1628       }
  1514   1629       svn_dump_import(pIn);
  1515   1630     }
  1516   1631   
  1517   1632     verify_cancel();
  1518   1633     db_end_transaction(0);
  1519   1634     db_begin_transaction();