Services
SolutionSettings.Commit.cs
// Copyright 2008-2009 The AnkhSVN Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections.Generic;
using System.Text;
using Ankh.VS;
using SharpSvn;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;
namespace Ankh.Settings
{
[GlobalService(typeof(IProjectCommitSettings))]
partial clast SolutionSettings : IProjectCommitSettings
{
public Uri GetIssueTrackerUri(string issueId)
{
if (issueId == null)
throw new ArgumentNullException("issueId");
if (string.IsNullOrEmpty(issueId))
return null;
RefreshIfDirty();
SettingsCache cache = _cache;
if (cache == null || cache.BugTrackUrl == null)
return null;
string url = cache.BugTrackUrl.Replace("%BUGID%", Uri.EscapeDataString(issueId));
if (url.StartsWith("^/"))
{
Uri repositoryRoot = RepositoryRoot;
if (repositoryRoot == null)
return null;
url = repositoryRoot.AbsoluteUri + url.Substring(2);
}
Uri result;
if (Uri.TryCreate(url, UriKind.Absolute, out result))
return result;
return null;
}
public Uri GetRevisionUri(string revisionText)
{
if (revisionText == null)
throw new ArgumentNullException("revisionText");
if (string.IsNullOrEmpty(revisionText))
return null;
RefreshIfDirty();
SettingsCache cache = _cache;
if (cache == null || cache.RevisionUrl == null)
return null;
string url = cache.RevisionUrl.Replace("%REVISION%", Uri.EscapeDataString(revisionText));
if (url.StartsWith("^/"))
{
Uri repositoryRoot = RepositoryRoot;
if (repositoryRoot == null)
return null;
url = repositoryRoot.AbsoluteUri + url.Substring(2);
}
Uri result;
if (Uri.TryCreate(url, UriKind.Absolute, out result))
return result;
return null;
}
public string RawIssueTrackerUri
{
get
{
RefreshIfDirty();
return _cache.BugTrackUrl;
}
}
public bool WarnIfNoIssue
{
get
{
RefreshIfDirty();
return _cache.BugTrackWarnIfNoIssue.HasValue && _cache.BugTrackWarnIfNoIssue.Value;
}
}
public string RawIssueTrackerMessage
{
get
{
RefreshIfDirty();
return _cache.BugTrackMessage;
}
}
public bool AppendIssueTrackerMessage
{
get
{
RefreshIfDirty();
return !_cache.BugTrackAppend.HasValue || _cache.BugTrackAppend.Value;
}
}
public string IssueLabel
{
get
{
RefreshIfDirty();
return _cache.BugTrackLabel;
}
}
public bool ShowIssueBox
{
get
{
RefreshIfDirty();
if (!string.IsNullOrEmpty(_cache.BugTrackMessage))
return true;
return false;
}
}
public bool NummericIssueIds
{
get
{
RefreshIfDirty();
return !_cache.BugTrackNumber.HasValue || _cache.BugTrackNumber.Value;
}
}
public ReadOnlyCollection RawLogIssueRegexes
{
get
{
RefreshIfDirty();
if (_cache.LogRegexes != null)
return _cache.LogRegexes;
List rl = new List();
if(!string.IsNullOrEmpty(_cache.BugTrackLogRegexes))
foreach (String s in _cache.BugTrackLogRegexes.Split('\n'))
{
rl.Add(s.TrimEnd('\r').Trim());
}
return _cache.LogRegexes = rl.AsReadOnly();
}
}
public IEnumerable GetIssues(string logmessage)
{
ReadOnlyCollection items = RawLogIssueRegexes;
SettingsCache sc = _cache;
if (sc.BrokenRegex)
return new TextMarker[0];
if (sc.AllInOneRe == null && sc.LogPrepareRe == null && items != null)
try
{
switch (items.Count)
{
case 1:
sc.AllInOneRe = new Regex(items[0], RegexOptions.CultureInvariant | RegexOptions.Multiline);
break;
case 2:
sc.LogPrepareRe = new Regex(items[0], RegexOptions.ExplicitCapture | RegexOptions.CultureInvariant | RegexOptions.Multiline);
sc.LogSplitRe = new Regex(items[1], RegexOptions.CultureInvariant | RegexOptions.Multiline);
break;
default:
sc.BrokenRegex = true;
break;
}
}
catch (ArgumentException)
{
sc.BrokenRegex = true;
}
if (sc.AllInOneRe != null)
return PerformAllInOne(sc, logmessage);
else if (sc.LogPrepareRe != null && sc.LogSplitRe != null)
return PerformSplit(sc, logmessage);
sc.BrokenRegex = true;
return new TextMarker[0];
}
const string defaultRevisionRegex = @"\b(r\d+)|(rev(ision)?(s|\(s\))?\s+\d+(\s*(,|and)\s*\d+)*)\b";
public IEnumerable GetRevisions(string text)
{
SettingsCache sc = _cache;
if (sc.RevisionRe == null && !string.IsNullOrEmpty(sc.RevisionRegex))
try
{
sc.RevisionRe = new Regex(sc.RevisionRegex.Trim(), RegexOptions.CultureInvariant | RegexOptions.Multiline);
}
catch (ArgumentException)
{}
if (sc.RevisionRe == null)
sc.RevisionRe = new Regex(defaultRevisionRegex, RegexOptions.CultureInvariant | RegexOptions.Multiline | RegexOptions.Compiled);
return PerformRevisionScan(sc, text);
}
private IEnumerable PerformAllInOne(SettingsCache sc, string logmessage)
{
foreach (Match m in sc.AllInOneRe.Matches(logmessage))
{
if (!m.Success)
continue;
bool first = true;
foreach (Group g in m.Groups)
{
if (first)
first = false;
else
foreach (Capture c in g.Captures)
yield return new TextMarker(c.Index, c.Length, c.Value);
}
}
}
private IEnumerable PerformSplit(SettingsCache cache, string logmessage)
{
foreach (Match m in cache.LogPrepareRe.Matches(logmessage))
{
if (!m.Success)
continue;
foreach (Capture c in m.Captures)
{
string text = logmessage.Substring(c.Index, c.Length);
foreach (Match sm in cache.LogSplitRe.Matches(c.Value))
{
if (!sm.Success)
continue;
foreach (Capture sc in sm.Captures)
{
yield return new TextMarker(c.Index + sc.Index, sc.Length, sc.Value);
}
}
}
}
}
static Regex _revRe;
private IEnumerable PerformRevisionScan(SettingsCache cache, string logmessage)
{
if (_revRe == null)
_revRe = new Regex(@"\d+", RegexOptions.Multiline | RegexOptions.CultureInvariant);
foreach (Match m in cache.RevisionRe.Matches(logmessage))
{
if (!m.Success)
continue;
foreach (Capture c in m.Captures)
{
string text = logmessage.Substring(c.Index, c.Length);
foreach (Match sm in _revRe.Matches(c.Value))
{
if (!sm.Success)
continue;
foreach (Capture sc in sm.Captures)
{
yield return new TextMarker(c.Index + sc.Index, sc.Length, sc.Value);
}
}
}
}
}
///
/// Gets the log summary.
///
/// The message.
///
public string GetLogSummary(string message)
{
if (string.IsNullOrEmpty(message))
return "";
RefreshIfDirty();
SettingsCache sc = _cache;
if (sc.LogSummary == null)
return message;
else if (_cache.LogSummaryRe == null)
{
try
{
_cache.LogSummaryRe = new Regex(_cache.LogSummary, RegexOptions.Multiline | RegexOptions.CultureInvariant);
}
catch (ArgumentException)
{
sc.LogSummary = null;
return message;
}
}
Match m = _cache.LogSummaryRe.Match(message);
if (m.Success && m.Groups.Count > 0 && m.Groups[1].Length > 0)
return m.Groups[1].Value;
return message;
}
///
/// Builds a log message from the specified message and issueId
///
/// The message.
/// The issue id.
///
public string BuildLogMessage(string message, string issueId)
{
if (!ShowIssueBox || string.IsNullOrEmpty(issueId))
return message;
issueId = issueId.Trim();
if (string.IsNullOrEmpty(issueId))
return message;
StringBuilder sb = new StringBuilder();
if(!AppendIssueTrackerMessage)
{
sb.Append(RawIssueTrackerMessage.Replace("%BUGID%", issueId));
if (!RawIssueTrackerMessage.EndsWith("\n"))
sb.AppendLine();
}
sb.Append(message);
if (!message.EndsWith("\n"))
sb.AppendLine();
if (AppendIssueTrackerMessage)
sb.AppendLine(RawIssueTrackerMessage.Replace("%BUGID%", issueId).TrimEnd());
return sb.ToString();
}
}
}