65.9K
CodeProject 正在变化。 阅读更多。
Home

一个用于搜索SVN仓库的LogParser输入插件

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2011年3月24日

CC (ASA 2.5)

2分钟阅读

viewsIcon

9400

使用SharpSvn查询SVN仓库的自定义LogParser输入插件示例

摘要

以下是如何编写自定义LogParser输入插件的示例,使用SharpSvn查询SVN仓库。

下载LogParser.Svn项目。 你需要Visual Studio 2010 Express来构建它。 确保项目属性的构建选项卡中选中“注册COM互操作”。 你还需要下载最新版本的SharpSvn并更新项目中的引用。

任何对示例的引用都指的是以下命令行

LogParser.exe -rtp:-1 -i:COM -iProgID:LogParser.Svn.SvnLogParserInputContext 
-iCOMParams:startDate=2010-01-01 "Select Count(1), 
Author From http://my.svn/repo/trunk Group By Author Order By Count(1)"

首先,在Visual Studio中创建一个新的“类库”项目。 我将其命名为LogParser.Svn

接下来,我们需要创建COM接口和我们的代码将使用的enum的副本

    public enum FieldType : int
    {
        Integer = 1,
        Real = 2,
        String = 3,
        Timestamp = 4,
        Null = 5,
    };

    public interface ILogParserInputContext
    {
        void OpenInput(string from);
        int GetFieldCount();
        string GetFieldName(int index);
        FieldType GetFieldType(int index);
        bool ReadRecord();
        object GetValue(int index);
        void CloseInput(bool abort);
    }

现在我们需要一个实现上述接口的类。 让我们从OpenInput方法开始。 该方法将接收一个string,该字符串输入到传递给LogParser的查询中,代表“FROM”语句。 采用上面的命令行,它将接收一个值为“http://my.svn/repo/trunk”。

        public void OpenInput(string from)
        {
        //   System.Diagnostics.Debugger.Launch();

            _client = new SvnClient();
            _repository = from;

            SvnLogArgs args = new SvnLogArgs();

            if (_start.HasValue)
            {
                if (_end.HasValue)
                {
                    args.Range = new SvnRevisionRange(_start.Value, _end.Value);
                }
                else
                {
                    args.Range = new SvnRevisionRange(new SvnRevision(_start.Value), SvnRevision.Head);
                }
            }
            else if (_end.HasValue)
            {
                args.Range = new SvnRevisionRange(SvnRevision.Zero, new SvnRevision(_end.Value));
            }

            if (_startDate.HasValue)
            {
                if (_endDate.HasValue)
                {
                    args.Range = new SvnRevisionRange(_startDate.Value, _endDate.Value);
                }
                else
                {
                    args.Range = new SvnRevisionRange(new SvnRevision
                                     (_startDate.Value), SvnRevision.Head);
                }
            }
            else if (_endDate.HasValue)
            {
                args.Range = new SvnRevisionRange(SvnRevision.Zero, new SvnRevision(_endDate.Value));
            }

            _results = new List<object[]>();

            _client.Log(new Uri(_repository), args, delegate(object sender, SvnLogEventArgs e)
            {
                if (_splitFiles)
                {
                    foreach (SvnChangeItem i in e.ChangedPaths)
                    {
                        object[] result = new object[6];

                        result[0] = e.Author;
                        result[1] = e.LogMessage;
                        result[2] = e.Revision;
                        result[3] = e.Time;
                        result[4] = i.Path;

                        _results.Add(result);
                    }
                }
                else
                {
                    object[] result = new object[6];

                    result[0] = e.Author;
                    result[1] = e.LogMessage;
                    result[2] = e.Revision;
                    result[3] = e.Time;

                    StringBuilder paths = new StringBuilder();

                    foreach (SvnChangeItem i in e.ChangedPaths)
                    {
                        paths.AppendFormat("{0};", i.Path);
                    }

                    result[4] = paths.ToString();

                    _results.Add(result);
                }

            });
        }

首先,上面的代码创建了一个新的SvnClient对象,我们将使用它来查看日志消息。 接下来,我们创建一个SvnLogArgs对象,并设置我们想要的修订范围。 最后,我们调用SvnClient.Log。 在委托中,我们收到与我们的SvnLogArgs对象匹配的每个日志条目。 然后,我们创建一个值数组并将它们存储在List中。 理想情况下,我们应该只准备接收一个值,然后在每次调用ReadRecord时接收每个条目,但我还没有来得及这样做(但更改代码以使其以这种方式工作应该不会太难)。

接下来的几个方法非常简单明了

        public int GetFieldCount()
        {
            return 5;
        }

        public string GetFieldName(int index)
        {
            switch (index)
            {
                case 0:
                    return "Author";
                case 1:
                    return "LogMessage";
                case 2:
                    return "Revision";
                case 3:
                    return "Time";
                case 4:
                    return "ChangedPaths";
            }

            return null;
        }

        public FieldType GetFieldType(int index)
        {
            switch (index)
            {
                case 0:
                    return FieldType.String;
                case 1:
                    return FieldType.String;
                case 2:
                    return FieldType.Integer;
                case 3:
                    return FieldType.Timestamp;
                case 4:
                    return FieldType.String;
            }

            return FieldType.Null;
        }

        public bool ReadRecord()
        {
            return ++_rowNumber < _results.Count;
        }

        public object GetValue(int index)
        {
            return _results[_rowNumber][index];
        }

        public void CloseInput(bool abort)
        {
            _client.Dispose();
        }

GetFieldCount返回你的解析器可以返回的字段数量。 GetFieldName返回给定索引的字段名称。 GetFieldType返回给定索引的字段类型。 ReadRecord是你的插件应该前进到下一个记录的地方,如果找到另一个记录则返回trueGetValue返回当前记录的指定字段的值。 CloseInput在最后调用,你可以在这里进行任何需要的清理。

你还可以创建一些只写属性,这些属性可以使用-iCOMParams:prop=value在命令行上设置。 请参阅附带的代码以获取示例。

我希望这能帮助那些尝试开始使用SharpSvn或编写自己的LogParser输入插件的人。

© . All rights reserved.