X-Git-Url: http://andersk.mit.edu/gitweb/svn-all-fast-export.git/blobdiff_plain/295db4b22a8ec04897f11aef2b54110522b22ff2..5871af719f7ede0db0e661a34a6f485dc4488e3b:/src/svn.cpp diff --git a/src/svn.cpp b/src/svn.cpp index b283ba0..de3a977 100644 --- a/src/svn.cpp +++ b/src/svn.cpp @@ -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 ¤t, @@ -175,8 +175,6 @@ findMatchRule(const MatchRuleList &matchRules, int revnum, const QString ¤ 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; } @@ -286,13 +284,10 @@ static int recursiveDumpDir(Repository::Transaction *txn, svn_fs_root_t *fs_root svn_fs_dirent_t *dirent = reinterpret_cast(value); QByteArray entryName = pathname + '/' + dirent->name; - QString entryFinalName; - if (finalPathName.isEmpty()) - entryFinalName = dirent->name; - else - entryFinalName = finalPathName + '/' + dirent->name; + QString entryFinalName = finalPathName + dirent->name; if (dirent->kind == svn_node_dir) { + entryFinalName += '/'; if (recursiveDumpDir(txn, fs_root, entryName, entryFinalName, dirpool) == EXIT_FAILURE) return EXIT_FAILURE; } else if (dirent->kind == svn_node_file) { @@ -356,12 +351,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 ¤t, 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 +401,7 @@ int SvnRevision::prepareTransactions() const char *key = reinterpret_cast(vkey); svn_fs_path_change_t *change = reinterpret_cast(value); - if (exportEntry(key, change) == EXIT_FAILURE) + if (exportEntry(key, change, changes) == EXIT_FAILURE) return EXIT_FAILURE; } @@ -444,7 +440,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); @@ -473,28 +470,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, revpool)) { + 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 +492,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 ¤t, 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 +510,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,12 +542,13 @@ 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; } repo->createBranch(branch, revnum, prevbranch, rev_from); + return EXIT_SUCCESS; } } } @@ -567,7 +557,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 +569,23 @@ 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 { + QString pathNoSlash = path; + pathNoSlash.chop(1); + txn->deleteFile(pathNoSlash); 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(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,10 +618,12 @@ 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"; + qCritical() << current << "rev" << revnum + << "did not match any rules; cannot continue"; return EXIT_FAILURE; } }