ALM Rangers

TFS 客户端对象模型中的版本控制

Jeff Bramwell

下载代码示例

这篇文章是"使用团队基础服务器客户端对象模型,"写的成员的 Visual Studio ALM 别动队在 2012 年 8 月一期的后续行动 (msdn.microsoft.com/magazine/jj553516)。 到目前为止,我们已经介绍了团队的基础服务器 (TFS) 客户端对象模型,和现在我要介绍的版本控制 Api。

重述一遍,ALM 别动队是一组由处理缺少的功能,促进的 Visual Studio 产品组、 Microsoft 服务和微软最有价值专家 (MVP) 社会之间的协作,删除通过受体阻滞剂和发布最佳做法和指南基于现实世界的经验的专家。

如果有人问你要解释什么是 TFS,很可能你会提到第一几句内的版本控制。 虽然版本控制不会发挥重要的作用,TFS 内,您可以看到在图 1 是有更多到 TFS。 与在 TFS 中的许多功能,如访问通过 TFS 对象模型的版本控制子系统。 此辅助功能为您提供了一个扩展性模型,您可以利用您自己的自定义工具和进程内。

Team Foundation Server Features
图 1 团队的基础服务器功能

程序集和命名空间

您可以访问 TFS 对象模型中提供的功能之前,您必须首先了解所需的程序集和命名空间。 您也许还记得第一条使用 Microsoft.TeamFoundation.Client 的命名空间。 此命名空间包含的类和方法的必要连接到 TFS 配置服务器和它的位于内具有相同名称的程序集。 此命名空间是所有 TFS 对象模型有关发展的核心。

使用版本控制时,我们还必须利用 Microsoft.TeamFoundation.VersionControl.Client 的命名空间。 此命名空间包含用于与 TFS 版本控制系统进行交互所需的类。 利用此命名空间中的 Api 允许您访问的文件和文件夹,挂起的更改、 合并、 分支,等等。 此命名空间内的 VersionControlServer 类是主要的类,它提供对 TFS 版本控制储存库的访问。

一个简单的例子开始

VersionControlServer 类公开许多属性、 方法和事件与内 TFS 版本控制进行交互。 我先用一个简单的例子:检索最新的变更集 id。

与大多数的 TFS 对象模型所公开的 Api 进行交互所需的三个基本步骤如下:

  1. 连接到 TFS 配置服务器。
  2. 获取对您计划利用的 TFS 服务的引用。
  3. 使使用的各种属性、 方法和事件提供的服务。

采取略有不同的做法,而不是在 8 月文章中,介绍的示例连接到 TFS,我要连接到 TFS 使用 TeamProjectPicker 类。 TeamProjectPicker 类显示一个用于连接到 TFS 服务器的标准对话框。 此类不是只为功能完整的应用程序很有用,但也是非常方便简单实用程序的位置,您可能需要在 TFS 的多个实例之间切换。

创建 TeamProjectPicker 的一个新实例,并显示它使用 ShowDialog 方法:

private TfsTeamProjectCollection _tpc;
using (var picker = new 
  TeamProjectPicker(TeamProjectPickerMode.NoProject, false))
{
  if (picker.ShowDialog()== DialogResult.OK)
  {
    _tpc = picker.SelectedTeamProjectCollection;
  }
}

此代码将显示一个对话框,如中所示类似图 2

The TeamProjectPicker Dialog
图 2 TeamProjectPicker 对话框

单击连接将返回实例的 TfsTeamProject­表示所选的团队项目集合 (TPC) 的集合。 如果您更喜欢使用更程序化的方法 (即,没有用户交互) 连接到 TFS,请返回 8 月文章以供进一步的例子。

一旦你得到对 TfsTeamProjectCollection 的引用,它可以用于获取 VersionControlServer 服务的实例:

var vcs = _tpc.GetService<VersionControlServer>();

一旦您拥有对该服务,您可以引用服务公开的方法的使用:

var latestId = vcs.GetLatestChangesetId();

这是一个简单的例子,但它不会表现出与在 TFS 中的版本控制系统进行交互的基本步骤。 然而,几个应用程序都这么简单。

"获取最新"

与版本控制有关的常见方案从库中获取的最新的源代码 — — 就"获取最新"Visual Studio 内工作时,您通常通过右键单击文件或文件夹内源控制资源管理器 (SCE) 选择获取最新版本获取最新的源代码。 为此要正常工作,您还必须选择映射的工作区。 当从服务器下载最新的源代码,选定工作区确定存储位置。

请按照这些步骤以编程方式获取最新的源代码:

  1. 连接到 TFS 配置服务器。
  2. 获取对版本控制服务的引用。
  3. 利用现有的工作区,或创建一个新的临时工作区。
  4. 将工作区映射到本地文件夹。
  5. 从工作区中下载所需的文件。

基于前面的示例中,添加所示的代码图 3

图 3 获取最新的版本控制

// Create a temporary workspace
var workspace = vcs.CreateWorkspace(Guid.NewGuid().ToString(),
  _tpc.AuthorizedIdentity.UniqueName,
  "Temporary workspace for file retrieval");
// For this workspace, map a server folder to a local folder
workspace.Map("$/Demo/TFS_VC_API", @"C:\Dev\Test");
// Create an ItemSpec to determine which files and folders are retrieved
// Retrieve everything under the server folder
var fileRequest = new GetRequest(
  new ItemSpec("$/Demo/TFS_VC_API", RecursionType.Full),
  VersionSpec.Latest);
// Get latest
var results = workspace.Get(fileRequest, 
  GetOptions.GetAll | GetOptions.Overwrite);

如果工作区中已存在,并且您想要使用它,替换行中的 1-4 图 3 以下列:

// Get a reference to an existing workspace,
// in this case, "DEMO_Workspace"
var workspace = vcs.GetWorkspace("DEMO_Workspace",
  _tpc.AuthorizedIdentity.UniqueName);

请注意如果您不知道工作区的名称,或不想指定它,您可以调用 GetWorkspace (见前面的代码示例),在只有一个本地路径中传递。 这将返回工作区映射到的本地路径。

您不需要映射工作区以编程的方式,所以您也可以删除行 5 和 6。

确定下载的文件和文件夹

正如您所料想的几个 TFS 所提供的 Api 允许您查询版本控制服务器的特定项目,以及特定版本的项目。 在前面的示例中,当创建新实例的 GetRequest,我不得不提供规范的一个实例。 项规范,短的项规范,描述了一组文件或文件夹。 这些项目可以存在于您的本地计算机或在版本控制服务器中。 在此特定示例中,我参与制造规范以返回"$ / 演示/TFS_VC_API"在服务器文件夹内的所有文件。

这里使用的项规范构造函数中的第二个参数指定 RecursionType,可以完全是无或 OneLevel。 此值确定多少个层次深 API 应该考虑查询项时。 指定 OneLevel RecursionType 将查询或从仅为最高级别 (相对于项规范) 返回的项目。 完全的值将查询或返回的项目从最顶端的水平,以及 (再次,相对于项规范) 下面的所有级别。

而项规范确定哪些项目要考虑基于名称和位置查询版本控制系统时,版本规范,短的版本规范,提供了限制基于版本的项集的能力。 版本­Spec 是一个抽象类,所以不能直接实例化。 TFS 提供了几个版本的实现­查询版本控制系统时,可以使的规范使用。 图 4 列出了各种实现的 TFS 2012 提供开箱即用的版本规范。

图 4 版本规范类型

版本规范 描述
ChangesetVersionSpec 指定基于变更集编号版本。
DateVersionSpec 指定基于日期/时间戳的版本。
LabelVersionSpec 指定一个标签所基于的版本。
LatestVersionSpec 表示存储库中的最新有效版本。
WorkspaceVersionSpec 指定工作区名称/所有者所基于的版本。

回到前面的示例创建 GetRequest,VersionSpec.Latest 列为我版本规范。 VersionSpec.Latest 是只需对 LatestVersionSpec 只是为方便提供单一实例的引用。 若要检索基于一个特定的标签代码,例如,创建 LabelVersionSpec 的实例:

var fileRequest = new GetRequest(
  new ItemSpec("$/Demo/TFS_VC_API", RecursionType.Full),
  new LabelVersionSpec("MyLabel"));

签出代码

您已经知道了如何识别和从版本控制服务器中检索特定项,让我们看看如何可以签出源代码。 在 TFS 术语中,要签出项目是挂起的编辑在该项目上。 到挂起一个特定的工作区中的项的编辑,您调用 Workspace.PendEdit 方法。 PendEdit 方法具有九个重载,所有这些都需要一个路径,以及几个其他可选参数的数组。 可选参数之一是 RecursionType,其中规范工程完全如前文所述。

例如,要签出的所有 C# (.cs) 文件,使此调用:

// This example assumes we have obtained a reference
// to an existing workspace by following the previous examples
var results = workspace.PendEdit("$/Demo/TFS_VC_API/*.cs", 
  RecursionType.Full);

在此示例中,我要求 TFS 挂起编辑所有 C# 文件 (通过 *.cs 通配符) 下方的服务器文件夹"$ / 演示/TFS_VC_API"。因为我指定 RecursionType 为充分,我就会签出指定的路径下的所有文件夹中的 C# 文件。 在此示例中使用的特定方法签名将还签出文件下载到的本地路径作为由指定的工作区映射。 您可以使用此方法接受一个参数的类型 PendChangesOptions 参数的重载版本之一,并指定 PendChangesOption.Silent 压制时的挂起编辑的文件的下载。 在结果中返回的值包含下载由于对 PendEdit 的调用的项的计数。

编辑不会你可以在版本控制系统内的挂起的唯一行动。 也有挂起的方法:

  • 添加通过 PendAdd
  • 通过 PendBranch 的分支机构
  • 通过 PendDelete 删除
  • 通过 PendPropertyName 属性
  • PendRename 通过重命名
  • 通过 PendUndelete 的撤消删除

例如,以下代码等待一个新的分支,命名为 Dev,从主要的文件夹:

// This example assumes we have obtained a reference
// to an existing workspace by following the previous examples
var results = workspace.PendBranch("$/Demo/TFS_VC_API/Main",  
   "$/Demo/TFS_VC_API/Dev", VersionSpec.Latest);

我们将介绍分支和合并在以后的文章中详细使用的 Api。

签入更改

一旦向一个或多个签出的文件进行了更改,您可以检查他们回通过 Workspace.CheckIn 方法。 您呼叫的签入方法之前,然而,您必须首先获取挂起的更改的工作区的列表通过调用 Workspace.GetPendingChanges。 如果您不指定任何参数的 GetPendingChanges 方法,你再回来所有挂起的更改工作区。 否则,您可以使用的其他 11 重载之一和筛选器挂起的更改到 TFS 调用所返回的列表。

下面的示例将检查在工作区中所有挂起的更改:

// This example assumes we have obtained a reference
// to an existing workspace by following the previous examples
var pendingChanges = workspace.GetPendingChanges();
var results = workspace.CheckIn(pendingChanges, "My check in.");

代码的第一行,在工作区得到所有挂起的更改的列表。 在第二行中,检查一切回到指定注释与变更集相关联的版本控制服务器中。 在结果中返回的值包含签入的项的计数。 如果有一个或多个挂起的更改,并且结果回来为零,然后在服务器和客户端之间的挂起项中发现没有差异。

挂起的编辑不是唯一的更改签入到版本控制系统中。 您还检查:

  • 增补
  • 分支机构
  • 撤销删除/删除
  • Properties
  • 重命名

您还可以撤消挂起的更改通过调用工作­空间。撤消方法。 使用签入方法,您还必须指定的挂起的更改要撤消。 下面的示例将撤消所有挂起的更改的工作区:

var pendingChanges = workspace.GetPendingChanges();
var results = workspace.Undo(pendingChanges);

检索历史

在团队资源管理器内的共同任务查看一个或多个文件或文件夹的历史记录。 您可能会发现需要以编程方式也这样做。 正如你所料想的但有一个 API 用于查询历史记录。 事实上,我要讨论的方法是从 VersionControlServer 实例 (为代表的在前面的示例中的变量 vcs) 可用。 该方法是 VersionControlServer.QueryHistory,并且它有八个重载。 此方法提供了许多不同的方式,根据的类型和值传递给方法调用的参数查询版本控制服务器的功能。

图 5 显示 Form1.cs 文件的历史记录视图可能是什么样子在常设专家委员会内。

History for Form1.cs
图 5 Form1.cs 的历史记录

您可以复制此功能以编程方式使用中所示的代码图 6

图 6 检索项历史记录

 

var vcs = _tpc.GetService<VersionControlServer>();
var results = vcs.QueryHistory(
"$/Demo/TFS_VC_API/Form1.cs", // The item (file) to query history for
VersionSpec.Latest,           // We want to query the latest version
0,                            // We're not interested in the Deletion ID
RecursionType.Full,           // Recurse all folders
null,                         // Specify null to query for all users
new ChangesetVersionSpec(1),  // Starting version is the 1st changeset        
                              // in TFS
VersionSpec.Latest,           // Ending version is the latest version
                              // in TFS
int.MaxValue,                 // Maximum number of entries to return
true,                         // Include changes
false);                     // Slot mode
if (results != null)
{
  foreach (var changeset in (IEnumerable<Changeset>)results)
  {
    if (changeset.Changes.Length > 0)
    {
      foreach (var change in changeset.Changes)
      {
        ResultsTextBox.Text +=
          string.Format("  {0}\t{1}\t{2}\t{3}\t{4}\t{5}\r\n",
          change.Item.ChangesetId,
          change.ChangeType,
          changeset.CommitterDisplayName,
          change.Item.CheckinDate,
          change.Item.ServerItem,
          changeset.Comment);
      }
    }
  }
}

在 13 号线上特别注意参数图 6。 我指定参数 includeChanges 为 true 值。 如果你指定了 false,然后具体变化的版本历史记录不会包含在返回的结果和图 6 示例不会显示详细信息。 您仍可以显示基本变更集历史记录而无需返回更改,但有些细节将不可用。

运行图 6 示例生成中所示的结果图 7

History from API
图 7 历史从 API

还有很多其他的调用 QueryHistory API 的变化。 思考如何为您可以使用此方法,只是玩弄在 SCE 中的历史记录功能。 您也可以查询更多历史。 例如,有其他与查询相关的方法,如由 VersionControlServer 提供:

  • QueryBranchObjectOwnership
  • QueryBranchObjects
  • QueryLabels
  • QueryMergeRelationships
  • QueryMerges
  • QueryMergesExtended
  • QueryMergesWithDetails
  • QueryPendingSets
  • QueryRootBranchObjects
  • QueryShelvedChanges
  • QueryShelvesets
  • QueryWorkspaces

有很多的信息可从版本控制服务器,和各种查询方法为您提供一个窗口到该信息。

后续步骤

别动队只已开始触摸上由 TFS 对象模型公开的版本控制功能。 在本文中所涵盖的功能可以有用且功能强大,但无数的功能公开的 TFS 版本控制服务器,我们还没有涉及。 这些功能的一些示例包括分支和合并,搁置集、 标签和版本控制事件。 这个系列的文章中,我们希望公开许多这些 Api,并为您提供您需要更好地利用了 TFS 对象模型的知识。 更多敬请。

Jeff Bramwell 是美国农场信贷服务的企业体系结构的主任。他拥有超过 20 年的软件开发经验,并始终致力于遵循最推崇的开始简单的和你的工作方式从那里。在他的博客是 devmatter.blogspot.com。您可以按照他在 Twitter 上 twitter.com/jbramwell

衷心感谢以下技术专家对本文的审阅:布赖恩 · 布莱克曼、 迈克 Fourie 和威利-彼得 · 肖布