diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CommandLineParser.cpp | 3 | ||||
-rw-r--r-- | src/CommandLineParser.h | 4 | ||||
-rw-r--r-- | src/main.cpp | 10 | ||||
-rw-r--r-- | src/ruleparser.cpp | 35 | ||||
-rw-r--r-- | src/ruleparser.h | 22 | ||||
-rw-r--r-- | src/svn.cpp | 72 | ||||
-rw-r--r-- | src/svn.h | 2 |
7 files changed, 108 insertions, 40 deletions
diff --git a/src/CommandLineParser.cpp b/src/CommandLineParser.cpp index 7e7658a..39f40d6 100644 --- a/src/CommandLineParser.cpp +++ b/src/CommandLineParser.cpp @@ -77,7 +77,8 @@ void CommandLineParser::Private::addDefinitions(const CommandLineOption * option for (int i=0; options[i].specification != 0; i++) { OptionDefinition definition; QString option = QString::fromLatin1(options[i].specification); - if (option.indexOf(QLatin1Char(',')) >= 0) { + // options with optional params are written as "--option required[, optional] + if (option.indexOf(QLatin1Char(',')) >= 0 && ( option.indexOf(QLatin1Char('[')) < 0 || option.indexOf(QLatin1Char(']')) < 0) ) { QStringList optionParts = option.split(QLatin1Char(','), QString::SkipEmptyParts); if (optionParts.count() != 2) { qWarning() << "option definition '" << option << "' is faulty; only one ',' allowed"; diff --git a/src/CommandLineParser.h b/src/CommandLineParser.h index 62c04bb..f5515d1 100644 --- a/src/CommandLineParser.h +++ b/src/CommandLineParser.h @@ -29,11 +29,13 @@ struct CommandLineOption { * <li>"-a, --all" </li> * <li>"--version" </li> * <li>"--type name" </li> + * <li>"--list item[,item]" </li> * <li>"-f, --format name [suffix] [foo]" </li> </ol> * Number 1 allows the user to either type -a or --all (or /A on Windows) to activate this option. * Number 2 allows the user to type --version to activate this option. * Number 3 requires the user to type a single argument after the option. - * Number 4 Allows the user to either use -f or --format, which is followed by one required argument + * Number 4 allows the user to use an option that takes a required argument and one or more optional ones + * Number 5 Allows the user to either use -f or --format, which is followed by one required argument * and optionally 2 more arguments. */ const char *specification; diff --git a/src/main.cpp b/src/main.cpp index 73d2378..7de7e45 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -69,7 +69,7 @@ QHash<QByteArray, QByteArray> loadIdentityMapFile(const QString &fileName) static const CommandLineOption options[] = { {"--identity-map FILENAME", "provide map between svn username and email"}, - {"--rules FILENAME", "the rules file that determines what goes where"}, + {"--rules FILENAME[,FILENAME]", "the rules file(s) that determines what goes where"}, {"--add-metadata", "if passed, each git commit will have svn commit info"}, {"--resume-from revision", "start importing at svn revision number"}, {"--max-rev revision", "stop importing at svn revision number"}, @@ -114,8 +114,8 @@ int main(int argc, char **argv) QCoreApplication app(argc, argv); // Load the configuration - Rules rules(args->optionArgument(QLatin1String("rules"))); - rules.load(); + RulesList rulesList(args->optionArgument(QLatin1String("rules"))); + rulesList.load(); int resume_from = args->optionArgument(QLatin1String("resume-from")).toInt(); int max_rev = args->optionArgument(QLatin1String("max-rev")).toInt(); @@ -126,7 +126,7 @@ int main(int argc, char **argv) int cutoff = resume_from ? resume_from : INT_MAX; retry: int min_rev = 1; - foreach (Rules::Repository rule, rules.repositories()) { + foreach (Rules::Repository rule, rulesList.allRepositories()) { Repository *repo = makeRepository(rule, repositories); if (!repo) return EXIT_FAILURE; @@ -172,7 +172,7 @@ int main(int argc, char **argv) Svn::initialize(); Svn svn(args->arguments().first()); - svn.setMatchRules(rules.matchRules()); + svn.setMatchRules(rulesList.allMatchRules()); svn.setRepositories(repositories); svn.setIdentityMap(loadIdentityMapFile(args->optionArgument("identity-map"))); diff --git a/src/ruleparser.cpp b/src/ruleparser.cpp index d8467ac..4ab8f08 100644 --- a/src/ruleparser.cpp +++ b/src/ruleparser.cpp @@ -22,6 +22,41 @@ #include "ruleparser.h" +RulesList::RulesList(const QString &filenames) + : m_filenames(filenames) +{ +} + +RulesList::~RulesList() {} + +void RulesList::load() +{ + foreach(const QString filename, m_filenames.split(',') ) { + qDebug() << "Loading rules from:" << filename; + Rules *rules = new Rules(filename); + m_rules.append(rules); + rules->load(); + m_allrepositories.append(rules->repositories()); + QList<Rules::Match> matchRules = rules->matchRules(); + m_allMatchRules.append( QList<Rules::Match>(matchRules)); + } +} + +const QList<Rules::Repository> RulesList::allRepositories() const +{ + return m_allrepositories; +} + +const QList<QList<Rules::Match> > RulesList::allMatchRules() const +{ + return m_allMatchRules; +} + +const QList<Rules*> RulesList::rules() const +{ + return m_rules; +} + Rules::Rules(const QString &fn) : filename(fn) { diff --git a/src/ruleparser.h b/src/ruleparser.h index e5cbaea..5d05d1c 100644 --- a/src/ruleparser.h +++ b/src/ruleparser.h @@ -80,8 +80,8 @@ public: Rules(const QString &filename); ~Rules(); - QList<Repository> repositories(); - QList<Match> matchRules(); + const QList<Repository> repositories() const; + const QList<Match> matchRules() const; void load(); QStringList readRules(const QString &filename) const; @@ -92,6 +92,24 @@ private: QList<Match> m_matchRules; }; +class RulesList +{ +public: + RulesList( const QString &filenames); + ~RulesList(); + + const QList<Rules::Repository> allRepositories() const; + const QList<QList<Rules::Match> > allMatchRules() const; + const QList<Rules*> rules() const; + void load(); + +private: + QString m_filenames; + QList<Rules*> m_rules; + QList<Rules::Repository> m_allrepositories; + QList<QList<Rules::Match> > m_allMatchRules; +}; + #ifndef QT_NO_DEBUG_STREAM class QDebug; QDebug operator<<(QDebug, const Rules::Match &); diff --git a/src/svn.cpp b/src/svn.cpp index 7298e08..c9b0f81 100644 --- a/src/svn.cpp +++ b/src/svn.cpp @@ -74,7 +74,7 @@ public: class SvnPrivate { public: - MatchRuleList matchRules; + QList<MatchRuleList> allMatchRules; RepositoryHash repositories; IdentityHash identities; @@ -113,9 +113,9 @@ Svn::~Svn() delete d; } -void Svn::setMatchRules(const MatchRuleList &matchRules) +void Svn::setMatchRules(const QList<MatchRuleList> &allMatchRules) { - d->matchRules = matchRules; + d->allMatchRules = allMatchRules; } void Svn::setRepositories(const RepositoryHash &repositories) @@ -370,7 +370,7 @@ class SvnRevision public: AprAutoPool pool; QHash<QString, Repository::Transaction *> transactions; - MatchRuleList matchRules; + QList<MatchRuleList> allMatchRules; RepositoryHash repositories; IdentityHash identities; @@ -404,19 +404,19 @@ public: int exportDispatch(const char *path, const svn_fs_path_change_t *change, const char *path_from, svn_revnum_t rev_from, apr_hash_t *changes, const QString ¤t, const Rules::Match &rule, - apr_pool_t *pool); + const MatchRuleList &matchRules, apr_pool_t *pool); 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 QString ¤t, const Rules::Match &rule, const MatchRuleList &matchRules); int recurse(const char *path, const svn_fs_path_change_t *change, - const char *path_from, svn_revnum_t rev_from, + const char *path_from, const MatchRuleList &matchRules, svn_revnum_t rev_from, apr_hash_t *changes, apr_pool_t *pool); }; int SvnPrivate::exportRevision(int revnum) { SvnRevision rev(revnum, fs, global_pool); - rev.matchRules = matchRules; + rev.allMatchRules = allMatchRules; rev.repositories = repositories; rev.identities = identities; @@ -544,20 +544,33 @@ int SvnRevision::exportEntry(const char *key, const svn_fs_path_change_t *change if (is_dir) current += '/'; - // find the first rule that matches this pathname - MatchRuleList::ConstIterator match = findMatchRule(matchRules, revnum, current); - if (match != matchRules.constEnd()) { - const Rules::Match &rule = *match; - return exportDispatch(key, change, path_from, rev_from, changes, current, rule, revpool); + //MultiRule: loop start + //Replace all returns with continue, + bool isHandled = false; + foreach ( const MatchRuleList matchRules, allMatchRules ) { + // find the first rule that matches this pathname + MatchRuleList::ConstIterator match = findMatchRule(matchRules, revnum, current); + if (match != matchRules.constEnd()) { + const Rules::Match &rule = *match; + if ( exportDispatch(key, change, path_from, rev_from, changes, current, rule, matchRules, revpool) == EXIT_FAILURE ) + return EXIT_FAILURE; + isHandled = true; + } else if (is_dir && path_from != NULL) { + qDebug() << current << "is a copy-with-history, auto-recursing"; + if ( recurse(key, change, path_from, matchRules, rev_from, changes, revpool) == EXIT_FAILURE ) + return EXIT_FAILURE; + isHandled = true; + } else if (is_dir && change->change_kind == svn_fs_path_change_delete) { + qDebug() << current << "deleted, auto-recursing"; + if ( recurse(key, change, path_from, matchRules, rev_from, changes, revpool) == EXIT_FAILURE ) + return EXIT_FAILURE; + isHandled = true; + } } - - 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 (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); - } else if (wasDir(fs, revnum - 1, key, revpool)) { + if ( isHandled ) { + return EXIT_SUCCESS; + } + 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"; @@ -565,14 +578,13 @@ int SvnRevision::exportEntry(const char *key, const svn_fs_path_change_t *change qCritical() << current << "did not match any rules; cannot continue"; return EXIT_FAILURE; } - return EXIT_SUCCESS; } int SvnRevision::exportDispatch(const char *key, const svn_fs_path_change_t *change, const char *path_from, svn_revnum_t rev_from, apr_hash_t *changes, const QString ¤t, - const Rules::Match &rule, apr_pool_t *pool) + const Rules::Match &rule, const MatchRuleList &matchRules, apr_pool_t *pool) { //if(ruledebug) // qDebug() << "rev" << revnum << qPrintable(current) << "matched rule:" << rule.lineNumber << "(" << rule.rx.pattern() << ")"; @@ -585,12 +597,12 @@ int SvnRevision::exportDispatch(const char *key, const svn_fs_path_change_t *cha case Rules::Match::Recurse: if(ruledebug) qDebug() << "rev" << revnum << qPrintable(current) << "matched rule:" << rule.info() << " " << "recursing."; - return recurse(key, change, path_from, rev_from, changes, pool); + return recurse(key, change, path_from, matchRules, rev_from, changes, pool); case Rules::Match::Export: if(ruledebug) qDebug() << "rev" << revnum << qPrintable(current) << "matched rule:" << rule.info() << " " << "exporting."; - if (exportInternal(key, change, path_from, rev_from, current, rule) == EXIT_SUCCESS) + if (exportInternal(key, change, path_from, rev_from, current, rule, matchRules) == EXIT_SUCCESS) return EXIT_SUCCESS; if (change->change_kind != svn_fs_path_change_delete) { if(ruledebug) @@ -600,7 +612,7 @@ int SvnRevision::exportDispatch(const char *key, const svn_fs_path_change_t *cha // 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 recurse(key, change, path_from, matchRules, rev_from, changes, pool); } // never reached @@ -609,7 +621,7 @@ int SvnRevision::exportDispatch(const char *key, const svn_fs_path_change_t *cha 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 QString ¤t, const Rules::Match &rule, const MatchRuleList &matchRules) { QString svnprefix, repository, branch, path; splitPathName(rule, current, &svnprefix, &repository, &branch, &path); @@ -746,7 +758,7 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha } int SvnRevision::recurse(const char *path, const svn_fs_path_change_t *change, - const char *path_from, svn_revnum_t rev_from, + const char *path_from, const MatchRuleList &matchRules, svn_revnum_t rev_from, apr_hash_t *changes, apr_pool_t *pool) { svn_fs_root_t *fs_root = this->fs_root; @@ -797,13 +809,13 @@ int SvnRevision::recurse(const char *path, const svn_fs_path_change_t *change, MatchRuleList::ConstIterator match = findMatchRule(matchRules, revnum, current); if (match != matchRules.constEnd()) { if (exportDispatch(entry, change, entryFrom.isNull() ? 0 : entryFrom.constData(), - rev_from, changes, current, *match, dirpool) == EXIT_FAILURE) + rev_from, changes, current, *match, matchRules, dirpool) == EXIT_FAILURE) 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) + matchRules, rev_from, changes, dirpool) == EXIT_FAILURE) return EXIT_FAILURE; } } @@ -33,7 +33,7 @@ public: Svn(const QString &pathToRepository); ~Svn(); - void setMatchRules(const QList<Rules::Match> &matchRules); + void setMatchRules(const QList<QList<Rules::Match> > &matchRules); void setRepositories(const QHash<QString, Repository *> &repositories); void setIdentityMap(const QHash<QByteArray, QByteArray> &identityMap); |