aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CommandLineParser.cpp3
-rw-r--r--src/CommandLineParser.h4
-rw-r--r--src/main.cpp10
-rw-r--r--src/ruleparser.cpp35
-rw-r--r--src/ruleparser.h22
-rw-r--r--src/svn.cpp72
-rw-r--r--src/svn.h2
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 &current, 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 &current, const Rules::Match &rule);
+ const QString &current, 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 &current,
- 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 &current, const Rules::Match &rule)
+ const QString &current, 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;
}
}
diff --git a/src/svn.h b/src/svn.h
index 10fd22c..5fb3245 100644
--- a/src/svn.h
+++ b/src/svn.h
@@ -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);