diff options
-rw-r--r-- | src/main.cpp | 68 | ||||
-rw-r--r-- | src/repository.cpp | 262 | ||||
-rw-r--r-- | src/repository.h | 12 | ||||
-rw-r--r-- | src/svn.cpp | 179 |
4 files changed, 282 insertions, 239 deletions
diff --git a/src/main.cpp b/src/main.cpp index f2b189e..73d2378 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -127,48 +127,48 @@ int main(int argc, char **argv) retry: int min_rev = 1; foreach (Rules::Repository rule, rules.repositories()) { - Repository *repo = makeRepository(rule, repositories); - if (!repo) - return EXIT_FAILURE; + Repository *repo = makeRepository(rule, repositories); + if (!repo) + return EXIT_FAILURE; repositories.insert(rule.name, repo); - int repo_next = repo->setupIncremental(cutoff); - - /* - * cutoff < resume_from => error exit eventually - * repo_next == cutoff => probably truncated log - */ - if (cutoff < resume_from && repo_next == cutoff) - /* - * Restore the log file so we fail the next time - * svn2git is invoked with the same arguments - */ - repo->restoreLog(); - - if (cutoff < min_rev) - /* - * We've rewound before the last revision of some - * repository that we've already seen. Start over - * from the beginning. (since cutoff is decreasing, - * we're sure we'll make forward progress eventually) - */ - goto retry; - - if (min_rev < repo_next) - min_rev = repo_next; + int repo_next = repo->setupIncremental(cutoff); + + /* + * cutoff < resume_from => error exit eventually + * repo_next == cutoff => probably truncated log + */ + if (cutoff < resume_from && repo_next == cutoff) + /* + * Restore the log file so we fail the next time + * svn2git is invoked with the same arguments + */ + repo->restoreLog(); + + if (cutoff < min_rev) + /* + * We've rewound before the last revision of some + * repository that we've already seen. Start over + * from the beginning. (since cutoff is decreasing, + * we're sure we'll make forward progress eventually) + */ + goto retry; + + if (min_rev < repo_next) + min_rev = repo_next; } if (cutoff < resume_from) { - qCritical() << "Cannot resume from" << resume_from - << "as there are errors in revision" << cutoff; - return EXIT_FAILURE; + qCritical() << "Cannot resume from" << resume_from + << "as there are errors in revision" << cutoff; + return EXIT_FAILURE; } if (min_rev < resume_from) - qDebug() << "skipping revisions" << min_rev << "to" << resume_from - 1 << "as requested"; + qDebug() << "skipping revisions" << min_rev << "to" << resume_from - 1 << "as requested"; if (resume_from) - min_rev = resume_from; + min_rev = resume_from; Svn::initialize(); Svn svn(args->arguments().first()); @@ -182,9 +182,9 @@ int main(int argc, char **argv) bool errors = false; for (int i = min_rev; i <= max_rev; ++i) { if (!svn.exportRevision(i)) { - errors = true; + errors = true; break; - } + } } foreach (Repository *repo, repositories) { diff --git a/src/repository.cpp b/src/repository.cpp index 5bcd8dd..ab2a7de 100644 --- a/src/repository.cpp +++ b/src/repository.cpp @@ -43,7 +43,7 @@ public: uint datetime; int revnum; - QVector<int> merges; + QVector<int> merges; QStringList deletedFiles; QByteArray modifiedFiles; @@ -57,7 +57,7 @@ public: void setDateTime(uint dt); void setLog(const QByteArray &log); - void noteCopyFromBranch (const QString &prevbranch, int revFrom); + void noteCopyFromBranch (const QString &prevbranch, int revFrom); void deleteFile(const QString &path); QIODevice *addFile(const QString &path, int mode, qint64 length); @@ -69,7 +69,7 @@ public: void reloadBranches(); int createBranch(const QString &branch, int revnum, - const QString &branchFrom, int revFrom); + const QString &branchFrom, int revFrom); int deleteBranch(const QString &branch, int revnum); Repository::Transaction *newTransaction(const QString &branch, const QString &svnprefix, int revnum); @@ -83,7 +83,7 @@ private: { int created; QVector<int> commits; - QVector<int> marks; + QVector<int> marks; }; struct AnnotatedTag { @@ -132,19 +132,19 @@ public: { Q_DISABLE_COPY(Transaction) - Repository::Transaction *txn; - QString prefix; + Repository::Transaction *txn; + QString prefix; public: - Transaction(Repository::Transaction *t, const QString &p) : txn(t), prefix(p) {} - ~Transaction() { delete txn; } + Transaction(Repository::Transaction *t, const QString &p) : txn(t), prefix(p) {} + ~Transaction() { delete txn; } void commit() { txn->commit(); } void setAuthor(const QByteArray &author) { txn->setAuthor(author); } void setDateTime(uint dt) { txn->setDateTime(dt); } void setLog(const QByteArray &log) { txn->setLog(log); } - void noteCopyFromBranch (const QString &prevbranch, int revFrom) - { txn->noteCopyFromBranch(prevbranch, revFrom); } + void noteCopyFromBranch (const QString &prevbranch, int revFrom) + { txn->noteCopyFromBranch(prevbranch, revFrom); } void deleteFile(const QString &path) { txn->deleteFile(prefix + path); } QIODevice *addFile(const QString &path, int mode, qint64 length) @@ -157,7 +157,7 @@ public: void restoreLog() {} int createBranch(const QString &branch, int revnum, - const QString &branchFrom, int revFrom) + const QString &branchFrom, int revFrom) { return repo->createBranch(branch, revnum, branchFrom, revFrom); } int deleteBranch(const QString &branch, int revnum) @@ -165,13 +165,13 @@ public: Repository::Transaction *newTransaction(const QString &branch, const QString &svnprefix, int revnum) { - Repository::Transaction *t = repo->newTransaction(branch, svnprefix, revnum); - return new Transaction(t, prefix); + Repository::Transaction *t = repo->newTransaction(branch, svnprefix, revnum); + return new Transaction(t, prefix); } void createAnnotatedTag(const QString &name, const QString &svnprefix, int revnum, - const QByteArray &author, uint dt, - const QByteArray &log) + const QByteArray &author, uint dt, + const QByteArray &log) { repo->createAnnotatedTag(name, svnprefix, revnum, author, dt, log); } void finalizeTags() { /* loop that called this will invoke it on 'repo' too */ } }; @@ -205,11 +205,11 @@ static ProcessCache processCache; Repository *makeRepository(const Rules::Repository &rule, const QHash<QString, Repository *> &repositories) { if (rule.forwardTo.isEmpty()) - return new FastImportRepository(rule); + return new FastImportRepository(rule); Repository *r = repositories[rule.forwardTo]; if (!r) { - qCritical() << "no repository with name" << rule.forwardTo << "found at line" << rule.lineNumber; - return r; + qCritical() << "no repository with name" << rule.forwardTo << "found at line" << rule.lineNumber; + return r; } return new PrefixingRepository(r, rule.prefix); } @@ -243,11 +243,11 @@ FastImportRepository::FastImportRepository(const Rules::Repository &rule) init.setWorkingDirectory(name); init.start("git", QStringList() << "--bare" << "init"); init.waitForFinished(-1); - { - QFile marks(name + "/" + marksFileName(name)); - marks.open(QIODevice::WriteOnly); - marks.close(); - } + { + QFile marks(name + "/" + marksFileName(name)); + marks.open(QIODevice::WriteOnly); + marks.close(); + } } } } @@ -263,45 +263,45 @@ static int lastValidMark(QString name) { QFile marksfile(name + "/" + marksFileName(name)); if (!marksfile.open(QIODevice::ReadOnly)) - return 0; + return 0; int prev_mark = 0; int lineno = 0; while (!marksfile.atEnd()) { - QString line = marksfile.readLine(); - ++lineno; - if (line.isEmpty()) - continue; - - int mark = 0; - if (line[0] == ':') { - int sp = line.indexOf(' '); - if (sp != -1) { - QString m = line.mid(1, sp-1); - mark = m.toInt(); - } - } - - if (!mark) { - qCritical() << marksfile.fileName() << "line" << lineno << "marks file corrupt?"; - return 0; - } - - if (mark == prev_mark) { - qCritical() << marksfile.fileName() << "line" << lineno << "marks file has duplicates"; - return 0; - } - - if (mark < prev_mark) { - qCritical() << marksfile.fileName() << "line" << lineno << "marks file not sorted"; - return 0; - } - - if (mark > prev_mark + 1) - break; - - prev_mark = mark; + QString line = marksfile.readLine(); + ++lineno; + if (line.isEmpty()) + continue; + + int mark = 0; + if (line[0] == ':') { + int sp = line.indexOf(' '); + if (sp != -1) { + QString m = line.mid(1, sp-1); + mark = m.toInt(); + } + } + + if (!mark) { + qCritical() << marksfile.fileName() << "line" << lineno << "marks file corrupt?"; + return 0; + } + + if (mark == prev_mark) { + qCritical() << marksfile.fileName() << "line" << lineno << "marks file has duplicates"; + return 0; + } + + if (mark < prev_mark) { + qCritical() << marksfile.fileName() << "line" << lineno << "marks file not sorted"; + return 0; + } + + if (mark > prev_mark + 1) + break; + + prev_mark = mark; } return prev_mark; @@ -341,26 +341,26 @@ int FastImportRepository::setupIncremental(int &cutoff) int mark = progress.cap(3).toInt(); if (revnum >= cutoff) - goto beyond_cutoff; + goto beyond_cutoff; if (revnum < last_revnum) qWarning() << name << "revision numbers are not monotonic: " << "got" << QString::number(last_revnum) << "and then" << QString::number(revnum); - if (mark > last_valid_mark) { - qWarning() << name << "unknown commit mark found: rewinding -- did you hit Ctrl-C?"; - cutoff = revnum; - goto beyond_cutoff; - } + if (mark > last_valid_mark) { + qWarning() << name << "unknown commit mark found: rewinding -- did you hit Ctrl-C?"; + cutoff = revnum; + goto beyond_cutoff; + } last_revnum = revnum; - if (last_commit_mark < mark) - last_commit_mark = mark; + if (last_commit_mark < mark) + last_commit_mark = mark; Branch &br = branches[branch]; - if (!br.created || !mark || !br.marks.last()) + if (!br.created || !mark || br.marks.isEmpty()) br.created = revnum; br.commits.append(revnum); br.marks.append(mark); @@ -368,11 +368,11 @@ int FastImportRepository::setupIncremental(int &cutoff) retval = last_revnum + 1; if (retval == cutoff) - /* - * If a stale backup file exists already, remove it, so that - * we don't confuse ourselves in 'restoreLog()' - */ - QFile::remove(bkup); + /* + * If a stale backup file exists already, remove it, so that + * we don't confuse ourselves in 'restoreLog()' + */ + QFile::remove(bkup); return retval; @@ -392,7 +392,7 @@ void FastImportRepository::restoreLog() QString file = logFileName(name); QString bkup = file + ".old"; if (!QFile::exists(bkup)) - return; + return; QFile::remove(file); QFile::rename(bkup, file); } @@ -425,15 +425,15 @@ void FastImportRepository::reloadBranches() Branch &br = branches[branch]; if (!br.marks.count() || !br.marks.last()) - continue; + continue; QByteArray branchRef = branch.toUtf8(); if (!branchRef.startsWith("refs/")) branchRef.prepend("refs/heads/"); - fastImport.write("reset " + branchRef + - "\nfrom :" + QByteArray::number(br.marks.last()) + "\n\n" - "progress Branch " + branchRef + " reloaded\n"); + fastImport.write("reset " + branchRef + + "\nfrom :" + QByteArray::number(br.marks.last()) + "\n\n" + "progress Branch " + branchRef + " reloaded\n"); } } @@ -441,28 +441,34 @@ int FastImportRepository::markFrom(const QString &branchFrom, int branchRevNum, { Branch &brFrom = branches[branchFrom]; if (!brFrom.created) - return -1; + return -1; - if (branchRevNum == brFrom.commits.last()) - return brFrom.marks.last(); + if (brFrom.commits.isEmpty()) { + return -1; + } + if (branchRevNum == brFrom.commits.last()) { + return brFrom.marks.last(); + } QVector<int>::const_iterator it = qUpperBound(brFrom.commits, branchRevNum); - if (it == brFrom.commits.begin()) - return 0; + if (it == brFrom.commits.begin()) { + return 0; + } int closestCommit = *--it; if (!branchFromDesc.isEmpty()) { - branchFromDesc += " at r" + QByteArray::number(branchRevNum); - if (closestCommit != branchRevNum) - branchFromDesc += " => r" + QByteArray::number(closestCommit); + branchFromDesc += " at r" + QByteArray::number(branchRevNum); + if (closestCommit != branchRevNum) { + branchFromDesc += " => r" + QByteArray::number(closestCommit); + } } return brFrom.marks[it - brFrom.commits.begin()]; } int FastImportRepository::createBranch(const QString &branch, int revnum, - const QString &branchFrom, int branchRevNum) + const QString &branchFrom, int branchRevNum) { startFastImport(); if (!branches.contains(branch)) { @@ -477,7 +483,7 @@ int FastImportRepository::createBranch(const QString &branch, int revnum, qCritical() << branch << "in repository" << name << "is branching from branch" << branchFrom << "but the latter doesn't exist. Can't continue."; - return EXIT_FAILURE; + return EXIT_FAILURE; } QByteArray branchFromRef = ":" + QByteArray::number(mark); @@ -487,9 +493,11 @@ int FastImportRepository::createBranch(const QString &branch, int revnum, branchFromRef = branchFrom.toUtf8(); if (!branchFromRef.startsWith("refs/")) branchFromRef.prepend("refs/heads/"); - branchFromDesc += ", deleted/unknown"; + branchFromDesc += ", deleted/unknown"; } + qDebug() << "Creating branch:" << branch << "from" << branchFrom << "(" << branchRevNum << branchFromDesc << ")"; + return resetBranch(branch, revnum, mark, branchFromRef, branchFromDesc); } @@ -505,7 +513,7 @@ int FastImportRepository::resetBranch(const QString &branch, int revnum, int mar { QByteArray branchRef = branch.toUtf8(); if (!branchRef.startsWith("refs/")) - branchRef.prepend("refs/heads/"); + branchRef.prepend("refs/heads/"); Branch &br = branches[branch]; if (br.created && br.created != revnum && br.marks.last()) { @@ -520,9 +528,9 @@ int FastImportRepository::resetBranch(const QString &branch, int revnum, int mar br.marks.append(mark); fastImport.write("reset " + branchRef + "\nfrom " + resetTo + "\n\n" - "progress SVN r" + QByteArray::number(revnum) - + " branch " + branch.toUtf8() + " = :" + QByteArray::number(mark) - + " # " + comment + "\n\n"); + "progress SVN r" + QByteArray::number(revnum) + + " branch " + branch.toUtf8() + " = :" + QByteArray::number(mark) + + " # " + comment + "\n\n"); return EXIT_SUCCESS; } @@ -543,9 +551,11 @@ Repository::Transaction *FastImportRepository::newTransaction(const QString &bra txn->datetime = 0; txn->revnum = revnum; - if ((++commitCount % CommandLineParser::instance()->optionArgument(QLatin1String("commit-interval"), QLatin1String("10000")).toInt()) == 0) + if ((++commitCount % CommandLineParser::instance()->optionArgument(QLatin1String("commit-interval"), QLatin1String("10000")).toInt()) == 0) { // write everything to disk every 10000 commits fastImport.write("checkpoint\n"); + qDebug() << "checkpoint!, marks file trunkated"; + } outstandingTransactions++; return txn; } @@ -675,6 +685,10 @@ void FastImportRepository::Transaction::setLog(const QByteArray &l) void FastImportRepository::Transaction::noteCopyFromBranch(const QString &branchFrom, int branchRevNum) { + //if(branch == branchFrom) { + // qWarning() << "Cannot merge inside a branch"; + // return; + //} static QByteArray dummy; int mark = repository->markFrom(branchFrom, branchRevNum, dummy); Q_ASSERT(dummy.isEmpty()); @@ -683,13 +697,17 @@ void FastImportRepository::Transaction::noteCopyFromBranch(const QString &branch qWarning() << branch << "is copying from branch" << branchFrom << "but the latter doesn't exist. Continuing, assuming the files exist."; } else if (mark == 0) { - qWarning() << "Unknown revision r" << QByteArray::number(branchRevNum) - << ". Continuing, assuming the files exist."; + qWarning() << "Unknown revision r" << QByteArray::number(branchRevNum) + << ". Continuing, assuming the files exist."; } else { - qWarning() << "repository " + repository->name + " branch " + branch + " has some files copied from " + branchFrom + "@" + QByteArray::number(branchRevNum); + qWarning() << "repository " + repository->name + " branch " + branch + " has some files copied from " + branchFrom + "@" + QByteArray::number(branchRevNum); - if (!merges.contains(mark)) - merges.append(mark); + if (!merges.contains(mark)) { + merges.append(mark); + qDebug() << "adding" << branchFrom + "@" + QByteArray::number(branchRevNum) << ":" << mark << "as a merge point"; + } else { + qDebug() << "merge point already recorded"; + } } } @@ -750,12 +768,12 @@ void FastImportRepository::Transaction::commit() int parentmark = 0; Branch &br = repository->branches[branch]; - if (br.created) { - parentmark = br.marks.last(); + if (br.created && !br.marks.isEmpty()) { + parentmark = br.marks.last(); } else { - qWarning() << "Branch" << branch << "in repository" << repository->name << "doesn't exist at revision" - << revnum << "-- did you resume from the wrong revision?"; - br.created = revnum; + qWarning() << "Branch" << branch << "in repository" << repository->name << "doesn't exist at revision" + << revnum << "-- did you resume from the wrong revision?"; + br.created = revnum; } br.commits.append(revnum); br.marks.append(mark); @@ -780,23 +798,25 @@ void FastImportRepository::Transaction::commit() QByteArray desc = ""; int i = !!parentmark; // if parentmark != 0, there's at least one parent foreach (int merge, merges) { - if (merge == parentmark) - continue; - - if (++i > 16) { - // FIXME: options: - // (1) ignore the 16 parent limit - // (2) don't emit more than 16 parents - // (3) create another commit on branch to soak up additional parents - // we've chosen option (2) for now, since only artificial commits - // created by cvs2svn seem to have this issue - qWarning() << "too many merge parents"; - break; - } - - QByteArray m = " :" + QByteArray::number(merge); - desc += m; - repository->fastImport.write("merge" + m + "\n"); + if (merge == parentmark) { + qDebug() << "Skipping marking" << merge << "as a merge point as it matches the parent"; + continue; + } + + if (++i > 16) { + // FIXME: options: + // (1) ignore the 16 parent limit + // (2) don't emit more than 16 parents + // (3) create another commit on branch to soak up additional parents + // we've chosen option (2) for now, since only artificial commits + // created by cvs2svn seem to have this issue + qWarning() << "too many merge parents"; + break; + } + + QByteArray m = " :" + QByteArray::number(merge); + desc += m; + repository->fastImport.write("merge" + m + "\n"); } // write the file deletions @@ -811,8 +831,8 @@ void FastImportRepository::Transaction::commit() repository->fastImport.write("\nprogress SVN r" + QByteArray::number(revnum) + " branch " + branch + " = :" + QByteArray::number(mark) - + (desc.isEmpty() ? "" : " # merge from") + desc - + "\n\n"); + + (desc.isEmpty() ? "" : " # merge from") + desc + + "\n\n"); printf(" %d modifications from SVN %s to %s/%s", deletedFiles.count() + modifiedFiles.count(), svnprefix.data(), qPrintable(repository->name), branch.data()); diff --git a/src/repository.h b/src/repository.h index e07d184..a4532ab 100644 --- a/src/repository.h +++ b/src/repository.h @@ -31,16 +31,16 @@ public: { Q_DISABLE_COPY(Transaction) protected: - Transaction() {} + Transaction() {} public: - virtual ~Transaction() {} + virtual ~Transaction() {} virtual void commit() = 0; virtual void setAuthor(const QByteArray &author) = 0; virtual void setDateTime(uint dt) = 0; virtual void setLog(const QByteArray &log) = 0; - virtual void noteCopyFromBranch (const QString &prevbranch, int revFrom) = 0; + virtual void noteCopyFromBranch (const QString &prevbranch, int revFrom) = 0; virtual void deleteFile(const QString &path) = 0; virtual QIODevice *addFile(const QString &path, int mode, qint64 length) = 0; @@ -50,13 +50,13 @@ public: virtual ~Repository() {} virtual int createBranch(const QString &branch, int revnum, - const QString &branchFrom, int revFrom) = 0; + const QString &branchFrom, int revFrom) = 0; virtual int deleteBranch(const QString &branch, int revnum) = 0; virtual Transaction *newTransaction(const QString &branch, const QString &svnprefix, int revnum) = 0; virtual void createAnnotatedTag(const QString &name, const QString &svnprefix, int revnum, - const QByteArray &author, uint dt, - const QByteArray &log) = 0; + const QByteArray &author, uint dt, + const QByteArray &log) = 0; virtual void finalizeTags() = 0; }; diff --git a/src/svn.cpp b/src/svn.cpp index 594a750..55b8b50 100644 --- a/src/svn.cpp +++ b/src/svn.cpp @@ -382,10 +382,12 @@ public: QByteArray authorident; QByteArray log; uint epoch; + bool ruledebug; SvnRevision(int revision, svn_fs_t *f, apr_pool_t *parent_pool) : pool(parent_pool), fs(f), fs_root(0), revnum(revision) { + ruledebug = CommandLineParser::instance()->contains( QLatin1String("debug-rules")); } int open() @@ -531,16 +533,16 @@ int SvnRevision::exportEntry(const char *key, const svn_fs_path_change_t *change qCritical() << " " << key << "was reset, panic!"; return EXIT_FAILURE; } else { - // if change_kind == delete, it shouldn't come into this arm of the 'is_dir' test + // if change_kind == delete, it shouldn't come into this arm of the 'is_dir' test qCritical() << " " << key << "has unhandled change kind " << change->change_kind << ", panic!"; return EXIT_FAILURE; } } else if (change->change_kind == svn_fs_path_change_delete) { - is_dir = wasDir(fs, revnum - 1, key, revpool); + is_dir = wasDir(fs, revnum - 1, key, revpool); } if (is_dir) - current += '/'; + current += '/'; // find the first rule that matches this pathname MatchRuleList::ConstIterator match = findMatchRule(matchRules, revnum, current); @@ -553,8 +555,8 @@ int SvnRevision::exportEntry(const char *key, const svn_fs_path_change_t *change qDebug() << current << "is a copy-with-history, auto-recursing"; return recurse(key, change, path_from, rev_from, changes, revpool); } else if (is_dir && change->change_kind == svn_fs_path_change_delete) { - qDebug() << current << "deleted, auto-recursing"; - return recurse(key, change, path_from, rev_from, changes, revpool); + qDebug() << current << "deleted, 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) { @@ -572,27 +574,33 @@ int SvnRevision::exportDispatch(const char *key, const svn_fs_path_change_t *cha apr_hash_t *changes, const QString ¤t, const Rules::Match &rule, apr_pool_t *pool) { - if(CommandLineParser::instance()->contains( QLatin1String("debug-rules"))) - qDebug() << " " << qPrintable(current) << "matched rule:" << rule.lineNumber << "(" << rule.rx.pattern() << ")"; + //if(ruledebug) + // qDebug() << "rev" << revnum << qPrintable(current) << "matched rule:" << rule.lineNumber << "(" << rule.rx.pattern() << ")"; switch (rule.action) { case Rules::Match::Ignore: - // ignore rule - //qDebug() << " " << qPrintable(current) << "rev" << revnum - // << "-> ignored (rule" << rule << ")"; + //if(ruledebug) + // qDebug() << " " << "ignoring."; return EXIT_SUCCESS; case Rules::Match::Recurse: + if(ruledebug) + qDebug() << "rev" << revnum << qPrintable(current) << "matched rule:" << rule.lineNumber << "(" << rule.rx.pattern() << ")" << " " << "recursing."; return recurse(key, change, path_from, rev_from, changes, pool); case Rules::Match::Export: + if(ruledebug) + qDebug() << "rev" << revnum << qPrintable(current) << "matched rule:" << rule.lineNumber << "(" << rule.rx.pattern() << ")" << " " << "exporting."; if (exportInternal(key, change, path_from, rev_from, current, rule) == EXIT_SUCCESS) - return EXIT_SUCCESS; - if (change->change_kind != svn_fs_path_change_delete) - return EXIT_FAILURE; - // we know that the default action inside recurse is to recurse further or to ignore, - // either of which is reasonably safe for deletion - qWarning() << "deleting unknown path" << current << "; auto-recursing"; - return recurse(key, change, path_from, rev_from, changes, pool); + return EXIT_SUCCESS; + if (change->change_kind != svn_fs_path_change_delete) { + if(ruledebug) + qDebug() << "rev" << revnum << qPrintable(current) << "matched rule:" << rule.lineNumber << "(" << rule.rx.pattern() << ")" << " " << "Unable to export non path removal."; + return EXIT_FAILURE; + } + // we know that the default action inside recurse is to recurse further or to ignore, + // either of which is reasonably safe for deletion + qWarning() << "deleting unknown path" << current << "; auto-recursing"; + return recurse(key, change, path_from, rev_from, changes, pool); } // never reached @@ -608,10 +616,10 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha Repository *repo = repositories.value(repository, 0); if (!repo) { - if (change->change_kind != svn_fs_path_change_delete) - qCritical() << "Rule" << rule - << "references unknown repository" << repository; - return EXIT_FAILURE; + if (change->change_kind != svn_fs_path_change_delete) + qCritical() << "Rule" << rule + << "references unknown repository" << repository; + return EXIT_FAILURE; } printf("."); @@ -620,69 +628,72 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha // << qPrintable(repository) << qPrintable(branch) << qPrintable(path); if (change->change_kind == svn_fs_path_change_delete && current == svnprefix) { - qDebug() << "repository" << repository << "branch" << branch << "deleted"; - return repo->deleteBranch(branch, revnum); + if(ruledebug) + qDebug() << "repository" << repository << "branch" << branch << "deleted"; + return repo->deleteBranch(branch, revnum); } QString previous; QString prevsvnprefix, prevrepository, prevbranch, prevpath; if (path_from != NULL) { - previous = QString::fromUtf8(path_from) + '/'; + previous = QString::fromUtf8(path_from) + '/'; MatchRuleList::ConstIterator prevmatch = findMatchRule(matchRules, rev_from, previous, NoIgnoreRule); - if (prevmatch != matchRules.constEnd()) + if (prevmatch != matchRules.constEnd()) { splitPathName(*prevmatch, previous, &prevsvnprefix, &prevrepository, &prevbranch, &prevpath); - else - path_from = NULL; + } else { + qWarning() << "SVN reports a \"copy from\" but no matching rules found! Ignoring copy, treating as a modification"; + path_from = NULL; + } } // current == svnprefix => we're dealing with the contents of the whole branch here if (path_from != NULL && current == svnprefix) { - if (previous != prevsvnprefix) { - // source is not the whole of its branch - qDebug() << qPrintable(current) << "is a partial branch of repository" - << qPrintable(prevrepository) << "branch" - << qPrintable(prevbranch) << "subdir" - << qPrintable(prevpath); - } else if (prevrepository != repository) { - qWarning() << qPrintable(current) << "rev" << revnum - << "is a cross-repository copy (from repository" - << qPrintable(prevrepository) << "branch" - << qPrintable(prevbranch) << "path" - << qPrintable(prevpath) << "rev" << rev_from << ")"; - } else if (path != prevpath) { - 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 (prevbranch == branch) { - // same branch and same repository - qDebug() << qPrintable(current) << "rev" << revnum - << "is reseating branch" << qPrintable(branch) - << "to an earlier revision" - << qPrintable(previous) << "rev" << rev_from; - } else { - // same repository but not same branch - // this means this is a plain branch - qDebug() << qPrintable(repository) << ": branch" - << qPrintable(branch) << "is branching from" - << qPrintable(prevbranch); - } - - if (repo->createBranch(branch, revnum, prevbranch, rev_from) == EXIT_FAILURE) - return EXIT_FAILURE; - if (rule.annotate) { - // create an annotated tag - fetchRevProps(); - repo->createAnnotatedTag(branch, svnprefix, revnum, authorident, - epoch, log); - } - return EXIT_SUCCESS; - } + if (previous != prevsvnprefix) { + // source is not the whole of its branch + qDebug() << qPrintable(current) << "is a partial branch of repository" + << qPrintable(prevrepository) << "branch" + << qPrintable(prevbranch) << "subdir" + << qPrintable(prevpath); + } else if (prevrepository != repository) { + qWarning() << qPrintable(current) << "rev" << revnum + << "is a cross-repository copy (from repository" + << qPrintable(prevrepository) << "branch" + << qPrintable(prevbranch) << "path" + << qPrintable(prevpath) << "rev" << rev_from << ")"; + } else if (path != prevpath) { + 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 (prevbranch == branch) { + // same branch and same repository + qDebug() << qPrintable(current) << "rev" << revnum + << "is reseating branch" << qPrintable(branch) + << "to an earlier revision" + << qPrintable(previous) << "rev" << rev_from; + } else { + // same repository but not same branch + // this means this is a plain branch + qDebug() << qPrintable(repository) << ": branch" + << qPrintable(branch) << "is branching from" + << qPrintable(prevbranch); + } + + if (repo->createBranch(branch, revnum, prevbranch, rev_from) == EXIT_FAILURE) + return EXIT_FAILURE; + if (rule.annotate) { + // create an annotated tag + fetchRevProps(); + repo->createAnnotatedTag(branch, svnprefix, revnum, authorident, + epoch, log); + } + return EXIT_SUCCESS; + } } Repository::Transaction *txn = transactions.value(repository + branch, 0); if (!txn) { @@ -699,16 +710,28 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha // changes across directory re-organizations and wholesale branch // imports. // - if (path_from != NULL && prevrepository == repository) - txn->noteCopyFromBranch (prevbranch, rev_from); + if (path_from != NULL && prevrepository == repository) { + if(ruledebug) + qDebug() << "copy from branch" << prevbranch << "rev" << rev_from; + txn->noteCopyFromBranch (prevbranch, rev_from); + } - if (change->change_kind == svn_fs_path_change_replace && path_from == NULL) + if (change->change_kind == svn_fs_path_change_replace && path_from == NULL) { + if(ruledebug) + qDebug() << "replaced with empty path"; txn->deleteFile(path); + } if (change->change_kind == svn_fs_path_change_delete) { + if(ruledebug) + qDebug() << "delete"; txn->deleteFile(path); } else if (!current.endsWith('/')) { + if(ruledebug) + qDebug() << "add/change file (" << key << "->" << path << ")"; dumpBlob(txn, fs_root, key, path, pool); } else { + if(ruledebug) + qDebug() << "add/change dir (" << key << "->" << path << ")"; txn->deleteFile(path); recursiveDumpDir(txn, fs_root, key, path, pool); } @@ -722,7 +745,7 @@ int SvnRevision::recurse(const char *path, const svn_fs_path_change_t *change, { svn_fs_root_t *fs_root = this->fs_root; if (change->change_kind == svn_fs_path_change_delete) - SVN_ERR(svn_fs_revision_root(&fs_root, fs, revnum - 1, pool)); + SVN_ERR(svn_fs_revision_root(&fs_root, fs, revnum - 1, pool)); // get the dir listing apr_hash_t *entries; @@ -765,10 +788,10 @@ int SvnRevision::recurse(const char *path, const svn_fs_path_change_t *change, return EXIT_FAILURE; } else { qDebug() << current << "rev" << revnum - << "did not match any rules; auto-recursing"; - if (recurse(entry, change, entryFrom.isNull() ? 0 : entryFrom.constData(), - rev_from, changes, dirpool) == EXIT_FAILURE) - return EXIT_FAILURE; + << "did not match any rules; auto-recursing"; + if (recurse(entry, change, entryFrom.isNull() ? 0 : entryFrom.constData(), + rev_from, changes, dirpool) == EXIT_FAILURE) + return EXIT_FAILURE; } } |