TFS TFS 二次开发-基线文件管理器 想法及一些代码

elvis_0123@sina.com · 2014年09月09日 · 4 次阅读

CMMI 在做基线文件管理的时候,常常是需要记录一部分基线文件的版本。并且这个基线文件记录也需要进行版本控制。TFS 在做这件事的时候一般来说会选用标签(Lable)来做一系列文件的版本记录。但是我发现 TFS 并不能选取某几个文件进行版本记录(实际上是可以的,但是很麻烦,需要建立 Lable 后再修改)。

于是,我们可以将项目文件以树形结构读出,然后选取需要做基线控制的几个文件.将其版本和路径保存到文件中,并且只为这几个文件建立 Lable。这个文件可以放入到 TFS 中做版本控制,今后也可以读出再做修改,重新打上 Lable。

想完成如上的想法,这就要涉及到 TFS 的二次开发了。

主要涉及到

TFS 的登录

[attach] 2441[/attach]

源码文件的读取

[attach] 2442[/attach]

标签的创建

[attach] 2443[/attach]

版本文件的保存

[attach] 2444[/attach]

接下来的文章就为大家通过这个例子,简单讲解下这几个功能。

TFS 二次开发 - 基线文件管理器(2)-TFS 登录

首先需要做一个 TFS 的登录。

以前的文章是使用的 DomainProjectPicker

最新的 VS 里面使用的是 TeamProjectPicker

首先可以在 WinForm 程序上写一个 Button,然后写入如下代码

[code] Uri tfsUri = new Uri("your TFS");

TfsTeamProjectCollection server = new TfsTeamProjectCollection(tfsUri);

TeamProjectPicker tpp = new TeamProjectPicker(TeamProjectPickerMode.SingleProject, false);

tpp.ShowDialog();

if (tpp.SelectedTeamProjectCollection != null) { server = tpp.SelectedTeamProjectCollection; }

else { MessageBox.Show("请选择项目"); return; } [/code]

这样,server 里面就存储了选取的 TFS 的内容了。

这里 TeamProjectPickerMode 有三个枚举,分别对应着如下的菜单,大家可以根据想达到的效果去选择。

[code] public enum TeamProjectPickerMode

{

NoProject = 0,

SingleProject = 1,

MultiProject = 2,

} [/code]

NoProject [attach] 2445[/attach]

SingleProject [attach] 2446[/attach]

MultiProject [attach] 2447[/attach]

完成选择后可以将其放入 ProjectInfo 中

[code] ProjectInfo[] pi;

pi = tpp.SelectedProjects;

string ProjectURL = pi[0].Name;[/code]

TFS 二次开发 - 基线文件管理器(3)- 源码文件的读取

TFS 登录成功后,就可以开始读取源码目录树了。

一般来说,我不建议将整个树全部读取出来,因为这里不光存有项目文件,还有项目源码。如果全部读取出会是非常大的一棵树。因此我建议只读出根目录,每一次点击打开一级子目录。这样找到自己需要选取的文件即可。

上一节中,我们已经登录完成。

[code]//获取选择的项目名称,这里是单项目,一次取 pi[0] 的名称

pi = tpp.SelectedProjects;

ProjectURL = pi[0].Name;

VersionControlServer version = server.GetService(typeof(VersionControlServer)) as VersionControlServer;

//此处获取项目第一级文件目录

ItemSet items = version.GetItems(@"$\" + ProjectURL, RecursionType.OneLevel); [/code]

接下来构建项目的第一级目录树。获取的 item 是一个包括父节点的目录,因此要去除后再添加

[code]//先清空树

treeView1.Nodes.Clear();

//获取父节点

Item SubItem = items.Items[0];

string MainSub = SubItem.ServerItem;

foreach (Item item in items.Items)

{

//去除父节点

if (MainSub == item.ServerItem) {

}

else

{

TreeNode tnadd = new TreeNode(item.ServerItem);

tnadd.Name = item.ServerItem;

treeView1.Nodes.Add(item.ServerItem, item.ServerItem);

}

} [/code]

执行后的效果如下。项目下有两级目录。 [attach] 2448[/attach]

接下来做树的点击事件。通过递归,向点击的节点添加子节点。

[code]

///

/// 选择结点后的处理事件

///

///

///

private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)

{

if (e.Action != TreeViewAction.Unknown)

{

version = server.GetService(typeof(VersionControlServer)) as VersionControlServer;

ItemSet items = version.GetItems(e.Node.Text, RecursionType.OneLevel);

foreach (Item item in items.Items)

{

if (e.Node.Text == item.ServerItem)

{

}

else

{

//这里用 name 来存储 changeset 的版本 ID,text 存显示路径

e.Node.Nodes.Add(item.ServerItem, item.ServerItem, item.ChangesetId);

}

e.Node.Expand();

}

}

}[/code]

最终的效果如下。 [attach] 2449[/attach]

TFS 二次开发 - 基线文件管理器(4)- 标签的创建

上一节已经完成了源码文件的读取,如果要将已经选择的文件保存为一个标签(Lable)。在 VS 我们只能对一个目录做标签,非常的不方便。如果用下面的方法,将选择的文件路径保存为一个 List 在打标签,就非常的灵活了。

保存为 List 的方法很简单,需要递归将已经选择的书中的文件保存一下。

这里为了显示方便,我先将其存入一个 Listbox 中,

[code] listBox1.Items.Clear();

for (int i = 0; i < treeView1.Nodes.Count; i++)

{

TreeNode node = treeView1.Nodes[i];

SetTreeViewList(node);

}[/code]

递归选取树中选择的节点并放入到 Listbox 中

[code] public void SetTreeViewList(TreeNode nodes) { //防止节点没有子节点被忽略 if (nodes.Checked) { listBox1.Items.Add(nodes.Text); } //有子节点 foreach (TreeNode newNode in nodes.Nodes) { if (newNode.Nodes.Count > 0) { SetTreeViewList(newNode); } //判断孩子节点 else { if (newNode.Checked) { //显示路径及版本 listBox1.Items.Add(newNode.Text); }

} }

}

[/code]

下面是将文件路径保存为标签。

[code] //确定文件数 int FileNum = listBox1.Items.Count; //这个 path 好似没用,不影响,所以写死了 string path = "$/test2-agile"; var versionControlLabel = new VersionControlLabel(version, "标签名称", version.AuthorizedUser, path, "标签注释"); //建立数组,每一个文件需要一个 var labelItemSpec = new LabelItemSpec[FileNum]; for (int i = 0; i < FileNum; i++) { string FileURL = TFSCommon.GetFileURL(listBox1.Items[i].ToString()); //判断是否为文件,因为有可能选的是路径,所以写了一个判断是否为文件的方法 if (! TFSCommon.IsFile(FileURL)) { MessageBox.Show("请选择文件"); return; } //RecursionType 设置递归类型 var itemSpec = new ItemSpec(FileURL, RecursionType.Full); labelItemSpec[i] = new LabelItemSpec(itemSpec, VersionSpec.Latest, false); } //创建 lable //LabelChildOption 其中三个选项,Fail = 失败, Replace = 替换, Merge = 合并 var lb = version.CreateLabel(versionControlLabel, labelItemSpec, LabelChildOption.Replace); MessageBox.Show(lb[0].Status.ToString());

[/code]

这里可以看到,标签的名称和注释可以自己写,比较灵活。在保存 Lable 的时候有三个选项。分别是失败、替换、合并。

当遇到同名标签的时候,如果选择失败会提示。如果选择替换会将原有标签替换为这次保存的文件。如果是合并,会将两次的标签合并。

我也来学一学,感谢 elvis.

TFS 的 label 的确用起来不太顺手。欢迎 elvis 分享 TFS 二次开发的文章。

TFS 二次开发 - 基线文件管理器(5)- 源码文件的读取

在上一节中,我们在保存标签之前,已经将勾选的文件路径保存到了 Listbox 中,这里只需要将保存的数据输出去为 txt 文档就可以做版本控制了。

版本文件比较复杂的是如何读取,也就是如何通过文件路径再次读取出一棵树。

这里我主要写一些思路和代码

1 存取的文件我们要将其读出后,存入一个 List 中。 2 通过文件路径,返回此文件的父级路径。

如 $/test2-agile/BuildProcessTemplates/LabDefaultTemplate.xaml

应该获取的路径为

$/test2-agile/BuildProcessTemplates/LabDefaultTemplate.xaml

$/test2-agile/BuildProcessTemplates

$/test2-agile 3 开始构建树。这个可以参考《TFS 二次开发 - 基线文件管理器(3)- 源码文件的读取》中构建项目的第一级目录树。 4 在此数中添加以获取的文件路径,并勾选已经选择的文件。

这种好处就是,无需读取所有树文件,只添加选择的文件的目录树。如果需要添加文件的时候,只需要重新勾选保存即可。

这次主要介绍的功能是 TFS 的登录、读取目录操作以及 Lable 操作。这里我能想到的还可以加上操作工作区的功能,如果可以的话,就可以直接签入签出了。

希望对大家有帮助。谢谢

其实这么看来是挺好用的。而且灵活度非常的大。等我把源码整理下发上来。

我个人觉得 TFS label 在使用的时候遇到的不便就是没有很好的管理界面(查询、删除、修改、锁定) 微软在 label 管理上的确需要加强点。

确实,仅有一个简单的管理界面,查询删除修改到是都有,木有锁定。 或许微软只是觉得这是个源码恢复以前版本的方法,没再多想。 其实有了二次开发,灵活度就大多了。可以做很多事情

好厉害的样子 顶一下

有没有完整的源代码呢,想下载下来学习下

学习到啦,求整理后的代码,谢谢!

需要 登录 后方可回复。