]> andersk Git - svn-all-fast-export.git/blobdiff - src/svn.cpp
Skip entries in recursion if said entries are in the changelist already
[svn-all-fast-export.git] / src / svn.cpp
index 73e7cb48adc3e9a29901dd3472fd1daab474dee6..d97a0e533b7a668d6722cec10f7eb84c16836106 100644 (file)
@@ -160,7 +160,7 @@ int SvnPrivate::openRepository(const QString &pathToRepository)
     return EXIT_SUCCESS;
 }
 
-enum RuleType { AnyRule = 0, NoIgnoreRule = 0x01, NoRecurseRule = 0x02 };
+enum RuleType { AnyRule = 0, NoIgnoreRule = 0x01 };
 
 static MatchRuleList::ConstIterator
 findMatchRule(const MatchRuleList &matchRules, int revnum, const QString &current,
@@ -175,8 +175,6 @@ findMatchRule(const MatchRuleList &matchRules, int revnum, const QString &curren
             continue;
         if (it->action == Rules::Match::Ignore && ruleMask & NoIgnoreRule)
             continue;
-        if (it->action == Rules::Match::Recurse && ruleMask & NoRecurseRule)
-            continue;
         if (it->rx.indexIn(current) == 0)
             return it;
     }
@@ -356,12 +354,13 @@ public:
     int prepareTransactions();
     int commit();
 
-    int exportEntry(const char *path, const svn_fs_path_change_t *change);
+    int exportEntry(const char *path, const svn_fs_path_change_t *change, apr_hash_t *changes);
     int exportInternal(const char *path, const svn_fs_path_change_t *change,
                        const char *path_from, svn_revnum_t rev_from,
                        const QString &current, const Rules::Match &rule);
     int recurse(const char *path, const svn_fs_path_change_t *change,
-                const char *path_from, svn_revnum_t rev_from, apr_pool_t *pool);
+                const char *path_from, svn_revnum_t rev_from,
+                apr_hash_t *changes, apr_pool_t *pool);
 };
 
 int SvnPrivate::exportRevision(int revnum)
@@ -405,7 +404,7 @@ int SvnRevision::prepareTransactions()
         const char *key = reinterpret_cast<const char *>(vkey);
         svn_fs_path_change_t *change = reinterpret_cast<svn_fs_path_change_t *>(value);
 
-        if (exportEntry(key, change) == EXIT_FAILURE)
+        if (exportEntry(key, change, changes) == EXIT_FAILURE)
             return EXIT_FAILURE;
     }
 
@@ -444,7 +443,8 @@ int SvnRevision::commit()
     return EXIT_SUCCESS;
 }
 
-int SvnRevision::exportEntry(const char *key, const svn_fs_path_change_t *change)
+int SvnRevision::exportEntry(const char *key, const svn_fs_path_change_t *change,
+                             apr_hash_t *changes)
 {
     AprAutoPool revpool(pool.data());
     QString current = QString::fromUtf8(key);
@@ -456,7 +456,7 @@ int SvnRevision::exportEntry(const char *key, const svn_fs_path_change_t *change
 
     // is this a directory?
     svn_boolean_t is_dir;
-    SVN_ERR(svn_fs_is_dir(&is_dir, fs_root, key, pool));
+    SVN_ERR(svn_fs_is_dir(&is_dir, fs_root, key, revpool));
     if (is_dir) {
         if (path_from == NULL) {
             // no, it's a new directory being added
@@ -473,28 +473,13 @@ int SvnRevision::exportEntry(const char *key, const svn_fs_path_change_t *change
     MatchRuleList::ConstIterator match = findMatchRule(matchRules, revnum, current);
     if (match != matchRules.constEnd()) {
         const Rules::Match &rule = *match;
-        switch (rule.action) {
-        case Rules::Match::Ignore:
-            // ignore rule
-            qDebug() << "   " << qPrintable(current) << "rev" << revnum
-                     << "-> ignored (rule line" << rule.lineNumber << ")";
-            return EXIT_SUCCESS;
-
-        case Rules::Match::Recurse:
-            // recurse rule
-            if (is_dir)
-                return recurse(key, change, path_from, rev_from, revpool);
-            if (change->change_kind != svn_fs_path_change_delete)
-                qWarning() << "   recurse rule " << rule.rx.pattern() << "line" << rule.lineNumber
-                           << "applied to non-directory:" << qPrintable(current);
-            return EXIT_SUCCESS;
-
-        case Rules::Match::Export:
-            return exportInternal(key, change, path_from, rev_from, current, rule);
-        }
+        return exportInternal(key, change, path_from, rev_from, current, rule);
     }
 
-    if (wasDir(fs, revnum - 1, key, pool)) {
+    if (is_dir && path_from != NULL) {
+        qDebug() << current << "is a copy-with-history, auto-recursing";
+        return recurse(key, change, path_from, rev_from, changes, revpool);
+    } else if (wasDir(fs, revnum - 1, key, revpool)) {
         qDebug() << current << "was a directory; ignoring";
     } else if (change->change_kind == svn_fs_path_change_delete) {
         qDebug() << current << "is being deleted but I don't know anything about it; ignoring";
@@ -510,6 +495,13 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha
                                 const char *path_from, svn_revnum_t rev_from,
                                 const QString &current, const Rules::Match &rule)
 {
+    if (rule.action == Rules::Match::Ignore) {
+        // ignore rule
+        qDebug() << "   " << qPrintable(current) << "rev" << revnum
+                 << "-> ignored (rule" << rule << ")";
+        return EXIT_SUCCESS;
+    }
+
     QString svnprefix, repository, branch, path;
     splitPathName(rule, current, &svnprefix, &repository, &branch, &path);
 
@@ -521,7 +513,7 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha
     if (path.isEmpty() && path_from != NULL) {
         QString previous = QString::fromUtf8(path_from) + '/';
         MatchRuleList::ConstIterator prevmatch =
-            findMatchRule(matchRules, rev_from, previous, NoRecurseRule | NoIgnoreRule);
+            findMatchRule(matchRules, rev_from, previous, NoIgnoreRule);
         if (prevmatch != matchRules.constEnd()) {
             QString prevsvnprefix, prevrepository, prevbranch, prevpath;
             splitPathName(*prevmatch, previous, &prevsvnprefix, &prevrepository,
@@ -553,7 +545,7 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha
 
                 Repository *repo = repositories.value(repository, 0);
                 if (!repo) {
-                    qCritical() << "Rule" << rule.rx.pattern() << "line" << rule.lineNumber
+                    qCritical() << "Rule" << rule
                                 << "references unknown repository" << repository;
                     return EXIT_FAILURE;
                 }
@@ -567,7 +559,7 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha
     if (!txn) {
         Repository *repo = repositories.value(repository, 0);
         if (!repo) {
-            qCritical() << "Rule" << rule.rx.pattern() << "line" << rule.lineNumber
+            qCritical() << "Rule" << rule
                         << "references unknown repository" << repository;
             return EXIT_FAILURE;
         }
@@ -579,19 +571,21 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha
         transactions.insert(repository, txn);
     }
 
-    if (change->change_kind == svn_fs_path_change_delete)
+    if (change->change_kind == svn_fs_path_change_delete) {
         txn->deleteFile(path);
-    else if (!current.endsWith('/'))
+    } else if (!current.endsWith('/')) {
         dumpBlob(txn, fs_root, key, path, pool);
-    else
+    } else {
+        txn->deleteFile(path);
         recursiveDumpDir(txn, fs_root, key, path, pool);
+    }
 
     return EXIT_SUCCESS;
 }
 
 int SvnRevision::recurse(const char *path, const svn_fs_path_change_t *change,
                          const char *path_from, svn_revnum_t rev_from,
-                         apr_pool_t *pool)
+                         apr_hash_t *changes, apr_pool_t *pool)
 {
     // get the dir listing
     apr_hash_t *entries;
@@ -606,7 +600,16 @@ int SvnRevision::recurse(const char *path, const svn_fs_path_change_t *change,
 
         svn_fs_dirent_t *dirent = reinterpret_cast<svn_fs_dirent_t *>(value);
         QByteArray entry = path + QByteArray("/") + dirent->name;
-        QByteArray entryFrom = path_from + QByteArray("/") + dirent->name;
+        QByteArray entryFrom;
+        if (path_from)
+            entryFrom = path_from + QByteArray("/") + dirent->name;
+
+        // check if this entry is in the changelist for this revision already
+        if (apr_hash_get(changes, entry.constData(), APR_HASH_KEY_STRING)) {
+            qDebug() << entry << "rev" << revnum
+                     << "is in the change-list, deferring to that one";
+            continue;
+        }
 
         QString current = QString::fromUtf8(entry);
         if (dirent->kind == svn_node_dir)
@@ -615,7 +618,8 @@ int SvnRevision::recurse(const char *path, const svn_fs_path_change_t *change,
         // find the first rule that matches this pathname
         MatchRuleList::ConstIterator match = findMatchRule(matchRules, revnum, current);
         if (match != matchRules.constEnd()) {
-            if (exportInternal(entry, change, entryFrom, rev_from, current, *match) == EXIT_FAILURE)
+            if (exportInternal(entry, change, entryFrom.isNull() ? 0 : entryFrom.constData(),
+                               rev_from, current, *match) == EXIT_FAILURE)
                 return EXIT_FAILURE;
         } else {
             qCritical() << current << "did not match any rules; cannot continue";
This page took 0.127958 seconds and 4 git commands to generate.