aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorModestas Vainius <modestas@vainius.eu>2011-04-24 22:46:23 +0300
committerModestas Vainius <modestas@vainius.eu>2011-04-24 22:46:23 +0300
commitc630dd763cf6ec096489bea551ca959540969c94 (patch)
tree64cfc7d592950bb22167892760aa74e322066042
parent197979b6a641b8b5fa4856c700b1235491c73a41 (diff)
downloadsvn2git-c630dd763cf6ec096489bea551ca959540969c94.tar
svn2git-c630dd763cf6ec096489bea551ca959540969c94.tar.gz
svn2git-c630dd763cf6ec096489bea551ca959540969c94.tar.bz2
svn2git-c630dd763cf6ec096489bea551ca959540969c94.tar.xz
svn2git-c630dd763cf6ec096489bea551ca959540969c94.zip
Support substitutions for repository/branch names.
This patch adds support for 's///' style substitutions for the repository/branch names in the match rulesets. Useful when e.g. eliminating characters not supported in git branch names. Syntax: match /... repository some_repo substitute repository s/pattern/replacement/ branch some_branch substitute branch s/pattern/replacement/ end match
-rw-r--r--src/ruleparser.cpp60
-rw-r--r--src/ruleparser.h11
-rw-r--r--src/svn.cpp6
3 files changed, 77 insertions, 0 deletions
diff --git a/src/ruleparser.cpp b/src/ruleparser.cpp
index eb309bf..8cd71a6 100644
--- a/src/ruleparser.cpp
+++ b/src/ruleparser.cpp
@@ -77,6 +77,48 @@ const QList<Rules::Match> Rules::matchRules() const
return m_matchRules;
}
+Rules::Match::Substitution Rules::parseSubstitution(const QString &string)
+{
+ if (string.at(0) != 's' || string.length() < 5)
+ return Match::Substitution();
+
+ const QChar sep = string.at(1);
+
+ if (string.at(string.length() - 1) != sep)
+ return Match::Substitution();
+
+ int i = 2, end = 0;
+ Match::Substitution subst;
+
+ // Separator might have been escaped with a backslash
+ while (i > end) {
+ int backslashCount = 0;
+ if ((end = string.indexOf(sep, i)) > -1) {
+ for (i = end - 1; i >= 2; i--) {
+ if (string.at(i) == '\\')
+ backslashCount++;
+ else
+ break;
+ }
+ } else {
+ return Match::Substitution(); // error
+ }
+
+ if (backslashCount % 2 != 0) {
+ // Separator was escaped. Search for another one
+ i = end + 1;
+ }
+ }
+
+ // Found the end of the pattern
+ subst.pattern = QRegExp(string.mid(2, end - 2));
+ if (!subst.pattern.isValid())
+ return Match::Substitution(); // error
+ subst.replacement = string.mid(end + 1, string.length() - 1 - end - 1);
+
+ return subst;
+}
+
void Rules::load()
{
load(filename);
@@ -93,7 +135,9 @@ void Rules::load(const QString &filename)
QRegExp matchLine("match\\s+(.*)", Qt::CaseInsensitive);
QRegExp matchActionLine("action\\s+(\\w+)", Qt::CaseInsensitive);
QRegExp matchRepoLine("repository\\s+(\\S+)", Qt::CaseInsensitive);
+ QRegExp matchRepoSubstLine("substitute repository\\s+(.+)$", Qt::CaseInsensitive);
QRegExp matchBranchLine("branch\\s+(\\S+)", Qt::CaseInsensitive);
+ QRegExp matchBranchSubstLine("substitute branch\\s+(.+)$", Qt::CaseInsensitive);
QRegExp matchRevLine("(min|max) revision (\\d+)", Qt::CaseInsensitive);
QRegExp matchAnnotateLine("annotated\\s+(\\S+)", Qt::CaseInsensitive);
QRegExp matchPrefixLine("prefix\\s+(\\S+)", Qt::CaseInsensitive);
@@ -175,6 +219,22 @@ void Rules::load(const QString &filename)
} else if (matchBranchLine.exactMatch(line)) {
match.branch = matchBranchLine.cap(1);
continue;
+ } else if (matchRepoSubstLine.exactMatch(line)) {
+ Match::Substitution subst = parseSubstitution(matchRepoSubstLine.cap(1));
+ if (!subst.isValid()) {
+ qFatal("Malformed substitution in rules file: line %d: %s",
+ lineNumber, qPrintable(origLine));
+ }
+ match.repo_substs += subst;
+ continue;
+ } else if (matchBranchSubstLine.exactMatch(line)) {
+ Match::Substitution subst = parseSubstitution(matchBranchSubstLine.cap(1));
+ if (!subst.isValid()) {
+ qFatal("Malformed substitution in rules file: line %d: %s",
+ lineNumber, qPrintable(origLine));
+ }
+ match.branch_substs += subst;
+ continue;
} else if (matchRevLine.exactMatch(line)) {
if (matchRevLine.cap(1) == "min")
match.minRevision = matchRevLine.cap(2).toInt();
diff --git a/src/ruleparser.h b/src/ruleparser.h
index 9d21937..26dfa72 100644
--- a/src/ruleparser.h
+++ b/src/ruleparser.h
@@ -57,9 +57,19 @@ public:
struct Match : Rule
{
+ struct Substitution {
+ QRegExp pattern;
+ QString replacement;
+
+ bool isValid() { return !pattern.isEmpty(); }
+ QString& apply(QString &string) { return string.replace(pattern, replacement); }
+ };
+
QRegExp rx;
QString repository;
+ QList<Substitution> repo_substs;
QString branch;
+ QList<Substitution> branch_substs;
QString prefix;
int minRevision;
int maxRevision;
@@ -83,6 +93,7 @@ public:
const QList<Repository> repositories() const;
const QList<Match> matchRules() const;
+ Match::Substitution parseSubstitution(const QString &string);
void load();
private:
diff --git a/src/svn.cpp b/src/svn.cpp
index 09495be..c103728 100644
--- a/src/svn.cpp
+++ b/src/svn.cpp
@@ -214,11 +214,17 @@ static void splitPathName(const Rules::Match &rule, const QString &pathName, QSt
if (repository_p) {
*repository_p = svnprefix;
repository_p->replace(rule.rx, rule.repository);
+ foreach (Rules::Match::Substitution subst, rule.repo_substs) {
+ subst.apply(*repository_p);
+ }
}
if (branch_p) {
*branch_p = svnprefix;
branch_p->replace(rule.rx, rule.branch);
+ foreach (Rules::Match::Substitution subst, rule.branch_substs) {
+ subst.apply(*branch_p);
+ }
}
if (path_p) {