четверг, 29 января 2015 г.

Include - Exclude file list pattern

Include - Exclude file list pattern is widely used in integration projects and in build systems. (ant, TeamCity)
One of the approaches is to use iterator over files tree like this:
// IncludeExcludeFileEnumerator(string baseDir, string includePattern, string excludePattern)
// Include pattern can include ** that means tree hierarchy
var myFiles = new IncludeExcludeFileEnumerable(@"C:\test\aaa", @"**.bmp,*.jpg", "*excl_bad*.*,*fu*");
foreach (var s in myFiles)
{
    Console.Out.WriteLine(s);
}
Code for file iterator ( IEnumerator, IEnumerable ):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;

namespace IncludeExcludeFileEnumerator
{
    public class IncludeExcludeFileEnumerator : IEnumerator<String>
    {
        private string excludeRegExPattern;
        private readonly Regex regexSeparateFilePath;
        private readonly Regex excludeRegex = null;
        private int currentPatternIndex;
        private IEnumerator<string> filesEnum;
        private IEnumerable<string> files;
        bool isNext = true;
        private readonly List<Tuple<string, string, SearchOption>> incPatternsList;


        public IncludeExcludeFileEnumerator(string baseDirectory, string includePattern, string excludePattern)
        {
            // Split comma separated string to array of include patterns
            var initIncludePatterns = includePattern.Split(',');
            regexSeparateFilePath = new Regex(@"(.*)[\\/]([^\\/]*$)", RegexOptions.Compiled);

            // Prepare include patterns
            incPatternsList = initIncludePatterns.ToList().ConvertAll(
                (incPattern) =>
                {
                    incPattern = incPattern.Trim();
                    var matches = regexSeparateFilePath.Matches(incPattern);
                    string pathPattern;
                    string filePattern;
                    if (matches.Count == 0)
                    {
                        pathPattern = "";
                        filePattern = incPattern;
                    }
                    else
                    {
                        pathPattern = matches[0].Groups[1].Value;
                        filePattern = matches[0].Groups[2].Value;
                    }
                    SearchOption searchOption = SearchOption.TopDirectoryOnly;
                    if (filePattern.Contains("**"))
                    {
                        filePattern = filePattern.Replace("**", "*");
                        searchOption = SearchOption.AllDirectories;
                    }
                    var fullPathPattern = Path.Combine(baseDirectory, pathPattern);
                    // Returns tuple {PathPattern, FilePattern, SearchOption}
                    return new Tuple<string, string, SearchOption>(fullPathPattern, filePattern, searchOption);
                });

            // Prepare regular expression for exclude case (all in one, concatinated by (| - or) separator)
            if (!String.IsNullOrWhiteSpace(excludePattern))
            {
                var excPatterns = excludePattern.Replace(".", @"\.");
                excPatterns = excPatterns.Replace("*", ".*");
                excludeRegExPattern = excPatterns.Replace(",", "|");
                excludeRegex = new Regex(excludeRegExPattern, RegexOptions.Compiled);
            }
            Reset();
        }

        public string Current
        {
            get { return filesEnum.Current; }
        }

        public void Dispose()
        {

        }

        object System.Collections.IEnumerator.Current
        {
            get { return (Object)this.Current; }
        }

        public bool MoveNext()
        {
            do
            {
                if (( filesEnum == null ) && (incPatternsList.Count < currentPatternIndex + 2))
                {
                    return false;
                }
                if ((filesEnum == null) || (isNext == false))
                {
                    var tuple = incPatternsList[++currentPatternIndex];
                    files = Directory.EnumerateFiles(tuple.Item1, tuple.Item2, tuple.Item3);
                    filesEnum = files.GetEnumerator();
                    isNext = true;
                }
                while (isNext)
                {
                    isNext = filesEnum.MoveNext();
                    if (isNext) 
                    {
                        if (excludeRegex==null) return true;
                        if (!excludeRegex.Match(filesEnum.Current).Success) return true;
                        // else continue;
                    }
                    else
                    {
                        filesEnum = null;
                    }
                }
            } while (true);
        }

        public void Reset()
        {
            currentPatternIndex = -1;
            filesEnum = null;
        }
    }

    public class IncludeExcludeFileEnumerable : IEnumerable<string>
    {
        private string baseDirectory;
        private string includePattern;
        private string excludePattern;

        public IncludeExcludeFileEnumerable(string baseDirectory, string includePattern, string excludePattern)
        {
            this.baseDirectory = baseDirectory;
            this.includePattern = includePattern;
            this.excludePattern = excludePattern;
        }

        public IEnumerator<string> GetEnumerator()
        {
            return new IncludeExcludeFileEnumerator(baseDirectory, includePattern, excludePattern);
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return (IEnumerator)this.GetEnumerator();
        }
    }
}

пятница, 17 февраля 2012 г.

TFS recover TFS Collection DB command

TFSConfig Recover /ConfigurationDB:tfsserver\SQLR2;Tfs_Configuration /CollectionDB:tfsserver\SQLR2;Tfs_collectionName

regex last \ in path replace with file prefix


            private string GenFileName(string SourceFile)
            {
                // last slash(\) replace with slash and file prifix (\TMP_)
                return Regex.Replace(SourceFile, @"\\(?=[^\\]*$)", @"\TMP_");
            }

четверг, 26 января 2012 г.

TFS TEE Changeset Diff Command Line Script


#!/bin/bash
# 1 - changeset number
clear

changeset=$1
changeset_m1=$((changeset-1))

echo "============================="
echo "changeset:"$changeset
echo "changeset-1:"$changeset_m1
echo "============================="

# 'tf -profile:max@max-desktop '$changeset
tf changeset -profile:max@max-desktop $changeset

regex=".*edit.*"
regexpath="\\$.*"

changesetcmd="tf changeset -profile:max@max-desktop "$changeset

echo "CMD:"$changesetcmd

echo "********************"

isItems="false"
tf changeset -profile:max@max-desktop $changeset | while read line
do
    if [ "$line" = "" ]; then
isItems="false"
    fi
    if [ "$isItems" = "true" ]; then

echo $line
if [[ $line =~ $regex ]]; then

[[ $line =~ $regexpath ]]
path="${BASH_REMATCH[0]}"
#echo "PATH:${BASH_REMATCH[0]}"
#echo "EDIT:"$line
echo "DIFF----"$path"---->"
tf diff "$path;C$changeset" "$path;C$changeset_m1" -workspace:max-desktop -profile:max@max-desktop
echo "<-DIFF"

fi

    fi  
    if [ "$line" = "Items:" ]; then
isItems="true"
    fi
done
echo "********************"
echo "finish"

пятница, 20 января 2012 г.

TFS Service Development: Set ChangedBy field for workitem


Case: You are developing service, that should change some WorkItems in Team Foundation Server.
Service should set field ChangedBy properly.


var collection1 = new TfsTeamProjectCollection(new Uri("http://tfs:8080/tfs/collection"));
collection1.EnsureAuthenticated();

var ims = collection1.GetService<IIdentityManagementService>();
var id = ims.ReadIdentity(IdentitySearchFactor.AccountName, "domain\\username"MembershipQuery.None, ReadIdentityOptions.None);

var collection = new TfsTeamProjectCollection(new Uri("http://tfs:8080/tfs/collection"), id.Descriptor);

-- OR --

WorkItem wi;
...
// Change Work Item
...
// Set ChangedBy Field
wi[CoreField.ChangedBy] = userName;
wi.Save();

понедельник, 5 декабря 2011 г.

WPF LinkButton



Add style to resources of the UserControl, where the (link)button is situated:

    <Style x:Key="LinkButton"
       TargetType="Button"
       BasedOn="{StaticResource ResourceKey={x:Type Button}}">
            <Setter Property="Width" Value="Auto"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <ContentPresenter Content="{TemplateBinding Content}"
                                  ContentTemplate="{TemplateBinding  ContentTemplate}"
                                  VerticalAlignment="Center">
                            <ContentPresenter.Resources>
                                <Style TargetType="{x:Type TextBlock}">
                                    <Setter Property="TextDecorations" Value="Underline" />
                                </Style>
                            </ContentPresenter.Resources>
                        </ContentPresenter>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Foreground" Value="Blue" />
            <Setter Property="Cursor" Value="Hand" />
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="true">
                    <Setter Property="Foreground" Value="Red" />
                </Trigger>
            </Style.Triggers>
        </Style>

Set style in code:

var button = new Button() {Style = (Style)(this.Resources["LinkButton"])};

Or in XAML:

Style={StaticResources LinkButton}