From c630dd763cf6ec096489bea551ca959540969c94 Mon Sep 17 00:00:00 2001 From: Modestas Vainius Date: Sun, 24 Apr 2011 22:46:23 +0300 Subject: 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 --- src/ruleparser.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ruleparser.h | 11 ++++++++++ src/svn.cpp | 6 ++++++ 3 files changed, 77 insertions(+) (limited to 'src') 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::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 repo_substs; QString branch; + QList branch_substs; QString prefix; int minRevision; int maxRevision; @@ -83,6 +93,7 @@ public: const QList repositories() const; const QList 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) { -- cgit v1.2.1