如何在TFS中以编程方式检出要编辑的项目?

42

我正在处理使用TFS 2010进行源代码控制的实用程序处理文件。

如果一个项目尚未被检出以供编辑,我会遇到异常,这是可以预见的,因为文件处于只读模式。

有哪些方法可以检出文件?

P.S. 如果适用的话,我想要一些编程方式而不是Process.Start("tf.exe", "...");

6个回答

40

这里提到的其他一些方法仅适用于某些版本的TFS或使用过时的方法。如果您收到404错误,则您正在使用的方法可能与您的服务器版本不兼容。

这种方法适用于2005、2008和2010。我不再使用TFS,所以我没有测试2013。

var workspaceInfo = Workstation.Current.GetLocalWorkspaceInfo(fileName);
using (var server = new TfsTeamProjectCollection(workspaceInfo.ServerUri))
{
    var workspace = workspaceInfo.GetWorkspace(server);    
    workspace.PendEdit(fileName);
}

我删除了我的答案,因为你的版本更简化,并且也适用于VS 2010。原来你不需要通过TfsConfigurationServer来获取所需的对象。 - RandomEngy
1
TfsTeamProjectCollectionIDisposable 接口,因此您可能希望将其包装在 using 块中。 - Carl Walsh
你是对的。我从中复制代码的源头持续保留了 TfsTeamProjectCollection,但这个做法可以改进示例的表现。 - Ben
想要为未来的访问者添加一条注释。如果您正在使用更冗长的PendEdit()函数,并且该函数带有silent参数,则需要将silent设置为false,这将使其删除只读锁定。 - njkremer

6
private const string tfsServer = @"http://tfsserver.org:8080/tfs";

public void CheckOutFromTFS(string fileName)
{
    using (TfsTeamProjectCollection pc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(tfsServer)))        
    {
        if (pc != null)
        {
            WorkspaceInfo workspaceInfo = Workstation.Current.GetLocalWorkspaceInfo(fileName);
            if (null != workspaceInfo)
            {                   
                Workspace workspace = workspaceInfo.GetWorkspace(pc);
                workspace.PendEdit(fileName);
            }
        }
    }
    FileInfo fi = new FileInfo(fileName);
}

注意:Microsoft.TeamFoundation.Client.TeamFoundationServerFactory已经过时,TeamFoundationServer类也已经过时。使用TeamFoundationProjectCollection或TfsConfigurationServer类来与2010版Team Foundation Server进行通信。 如果要与2005或2008版的Team Foundation Server进行通信,请使用TeamFoundationProjectCollection类。相应的工厂类是TfsTeamProjectCollectionFactory。

4

2

首先获取工作区

var tfs = new TeamFoundationServer("http://server:8080/tfs/collection");
var version = (VersionControlServer)tfs.GetService(typeof(VersionControlServer));
var workspace = version.GetWorkspace("WORKSPACE-NAME", version.AuthorizedUser);

使用工作区,您可以检出文件。
workspace.PendEdit(fileName);

2
var registerdCollection = RegisteredTfsConnections.GetProjectCollections().First();
var projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(registerdCollection);
var versionControl = projectCollection.GetService<VersionControlServer>();

var workspaceInfo = Workstation.Current.GetLocalWorkspaceInfo(_fileName);
var server = new TeamFoundationServer(workspaceInfo.ServerUri.ToString());
var workspace = workspaceInfo.GetWorkspace(server);

workspace.PendEdit(fileName);

0
我有两种方法可以做到这一点:简单和高级。
1). 简单:
  #region Check Out
    public bool CheckOut(string path)
    {
        using (TfsTeamProjectCollection pc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(ConstTfsServerUri)))
        {
            if (pc == null) return false;

            WorkspaceInfo workspaceInfo = Workstation.Current.GetLocalWorkspaceInfo(path);
            Workspace workspace = workspaceInfo?.GetWorkspace(pc);
            return workspace?.PendEdit(path, RecursionType.Full) == 1;
        }
    }

    public async Task<bool> CheckoutAsync(string path)
    {
        return await Task.Run(() => CheckOut(path));
    }
    #endregion

2). 高级(带有接收状态):

    private static string GetOwnerDisplayName(PendingSet[] pending)
    {
        var result = pending.FirstOrDefault(pendingSet => pendingSet.Computer != Environment.MachineName) ?? pending[0];
        return result.OwnerDisplayName;
    }
    private string CheckoutFileInternal(string[] wsFiles, string folder = null)
    {
        try
        {

            var workspaceInfo = Workstation.Current.GetLocalWorkspaceInfo(folder);
            var server = new TfsTeamProjectCollection(workspaceInfo.ServerUri);
            var workspace = workspaceInfo.GetWorkspace(server);
            var request = new GetRequest(folder, RecursionType.Full, VersionSpec.Latest);
            GetStatus status = workspace.Get(request, GetOptions.None);
            int result = workspace.PendEdit(wsFiles, RecursionType.Full, null, LockLevel.None);
            if (result == wsFiles.Length)
            {
                //TODO: write info (succeed) to log here - messageText
                return null;
            }
            var pending = server.GetService<VersionControlServer>().QueryPendingSets(wsFiles, RecursionType.None, null, null);
            var messageText = "Failed to checkout !.";
            if (pending.Any())
            {
                messageText = string.Format("{0}\nFile is locked by {1}", messageText, GetOwnerDisplayName(pending));
            }

            //TODO: write error to log here - messageText
            return messageText;
        }
        catch (Exception ex)
        {
            UIHelper.Instance.RunOnUiThread(() =>
            {
                MessageBox.Show(Application.Current.MainWindow, string.Format("Failed checking out TFS files : {0}", ex.Message), "Check-out from TFS",
                               MessageBoxButton.OK, MessageBoxImage.Error);
            });
            return null;
        }
    }

    public async Task<string> CheckoutFileInternalAsync(string[] wsFiles, string folder)
    {
        return await Task.Run(() => CheckoutFileInternal(wsFiles, folder));
    }

你可能想要在内部函数后缀上“internal”,并从公共函数中删除该后缀。 - abatishchev
以异步方式运行同步函数对我来说没有太多意义。无论如何,您可能可以直接返回任务而不是等待它,这样调用者就会等待它。 - abatishchev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接