From f8ed2101da602b39e6b914382baa4fd6872b7ea9 Mon Sep 17 00:00:00 2001 From: Colin Guthrie Date: Thu, 29 May 2014 00:47:39 +0100 Subject: Support repository renaming. This allows us to svn mv the cauldron/PKG/current folder to a new name and have this copied over to git. It does not yet handle the case where subsequent commits to previous distros for the old name are magically moved over to the new name for the repo (which I think is the correct behaviour as noted on the sysadm mailing list) so some kind of rename mapping will have to be kept (if I ever implement resuming support, then this map will have to be dumped to a file and restored again about restart) Another problem is that the tags are apparently all squashed up due to the svn mv commit, but this should be handled via a simple return... after dealing with the repo rename (although some changes may get lost :( if this is not a straight copy (i.e. svn cp + changes in the same txn) --- src/svn.cpp | 80 +++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 21 deletions(-) diff --git a/src/svn.cpp b/src/svn.cpp index 72f73cd..6bb0d2b 100644 --- a/src/svn.cpp +++ b/src/svn.cpp @@ -436,6 +436,7 @@ public: const char *path_from, svn_revnum_t rev_from, apr_hash_t *changes, const QString ¤t, const Rules::Match &rule, const MatchRuleList &matchRules, apr_pool_t *pool); + Repository* autoCreateRepo(const svn_fs_path_change_t *change, const Rules::Match &rule, const QString &repository, const QString &branch); 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, const MatchRuleList &matchRules); @@ -679,6 +680,31 @@ int SvnRevision::exportDispatch(const char *key, const svn_fs_path_change_t *cha return EXIT_FAILURE; } +Repository* SvnRevision::autoCreateRepo(const svn_fs_path_change_t *change, const Rules::Match &rule, const QString &repository, const QString &branch) +{ + Repository *repo = NULL; + if (change->change_kind == svn_fs_path_change_delete) { + qCritical() << "Rule" << rule + << "references unknown repository" << repository; + + return NULL; + } + + // Attempt to auto create the repo + qWarning() << "Auto-creating repository" << repository << "with branch" + << branch << "at revision" << revnum << "due to rule match"; + + repo = new Repository(repository, branch, revnum); + if (!repo) + return NULL; + repositories->insert(repository, repo); + + printf("."); + fflush(stdout); + + return repo; +} + int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *change, const char *path_from, svn_revnum_t rev_from, const QString ¤t, const Rules::Match &rule, const MatchRuleList &matchRules) @@ -688,34 +714,17 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha splitPathName(rule, current, &svnprefix, &repository, &branch, &path); Repository *repo = repositories->value(repository, 0); - if (!repo) { - if (change->change_kind != svn_fs_path_change_delete) { - // Attempt to auto create the repo - qWarning() << "Auto-creating repository" << repository << "with branch" - << branch << "at revision" << revnum << "due to rule match"; - - repo = new Repository(repository, branch, revnum); - if (!repo) - return EXIT_FAILURE; - repositories->insert(repository, repo); - - //repo->setupIncremental(INT_MAX); - } +// qDebug() << " " << qPrintable(current) << "rev" << revnum << "->" +// << qPrintable(repository) << qPrintable(branch) << qPrintable(path); + if (change->change_kind == svn_fs_path_change_delete && current == svnprefix && path.isEmpty()) { if (!repo) { qCritical() << "Rule" << rule << "references unknown repository" << repository; return EXIT_FAILURE; } - } - printf("."); - fflush(stdout); -// qDebug() << " " << qPrintable(current) << "rev" << revnum << "->" -// << qPrintable(repository) << qPrintable(branch) << qPrintable(path); - - if (change->change_kind == svn_fs_path_change_delete && current == svnprefix && path.isEmpty()) { if(ruledebug) qDebug() << "repository" << repository << "branch" << branch << "deleted"; @@ -724,7 +733,7 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha return repo->deleteBranch(branch, revnum); } - QString newreponame = repository + "-r" + QString::number(revnum); + QString newreponame = repository + "-r" + QString::number(revnum-1); if (!repo->rename(newreponame)) return EXIT_FAILURE; repositories->remove(repository); @@ -755,6 +764,9 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha // current == svnprefix => we're dealing with the contents of the whole branch here if (path_from != NULL && current == svnprefix && path.isEmpty()) { if (previous != prevsvnprefix) { + if (!repo && !(repo = autoCreateRepo(change, rule, repository, branch))) + return EXIT_FAILURE; + // source is not the whole of its branch qDebug() << qPrintable(current) << "is a partial branch of repository" << qPrintable(prevrepository) << "branch" @@ -766,13 +778,35 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha << qPrintable(prevrepository) << "branch" << qPrintable(prevbranch) << "path" << qPrintable(prevpath) << "rev" << rev_from << ")"; + + // Have we been copied from elsewhere? + QString renamed = prevrepository + "-r" + QString::number(rev_from); + if (!repo && "master" == prevbranch && QDir(renamed).exists()) { + qWarning() << "Found potential repository rename from" << renamed; + repo = repositories->value(renamed, 0); + if (!repo) { + qCritical() << "Cannot find repository" << renamed; + return EXIT_FAILURE; + } + + if (!repo->rename(repository)) + return EXIT_FAILURE; + repositories->remove(renamed); + repositories->insert(repository, repo); + } } else if (path != prevpath) { + if (!repo && !(repo = autoCreateRepo(change, rule, repository, branch))) + return EXIT_FAILURE; + qDebug() << qPrintable(current) << "is a branch copy which renames base directory of all contents" << qPrintable(prevpath) << "to" << qPrintable(path); // FIXME: Handle with fast-import 'file rename' facility // ??? Might need special handling when path == / or prevpath == / } else { + if (!repo && !(repo = autoCreateRepo(change, rule, repository, branch))) + return EXIT_FAILURE; + if (prevbranch == branch) { // same branch and same repository qDebug() << qPrintable(current) << "rev" << revnum @@ -813,6 +847,10 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha return EXIT_SUCCESS; } } + + if (!repo && !(repo = autoCreateRepo(change, rule, repository, branch))) + return EXIT_FAILURE; + Repository::Transaction *txn = transactions.value(repository + branch, 0); if (!txn) { txn = repo->newTransaction(branch, svnprefix, revnum); -- cgit v1.2.1