【问题标题】:How to get specific version of folder from tfs without creating a workspace?如何在不创建工作区的情况下从 tfs 获取特定版本的文件夹?
【发布时间】:2012-05-13 01:00:41
【问题描述】:

我想在特定时间(变更集)获取项目的源代码。所以我需要下载整个文件夹。我想在不同的时间做这件事,处理不同的工作空间不是很方便。

我知道TFS Get Specific Version into separate folder(带有工作区)和Need command to get a file from TFS without a workspace(一个文件)。

在不创建新工作区的情况下,是否有针对整个文件夹的解决方案?

编辑 我发现公认的答案过于雄心勃勃。我需要一些更简单的东西。

假设:

  • 我可以从计算机上的 Visual Studio 访问 TFS
  • 我想从文件夹中获取ChangeSetNumber Changeset DesiredFolder 在 TFS 项目中 tProj

我从 Visual Studio 命令提示符中的目标文件夹运行以下批处理

set workspace_name=TemporaryWorkspace%username%
set changeset= ChangeSetNumber                
tf workspace -new %workspace_name% -noprompt
tf workfold -map $/tProj . -workspace:%workspace_name%
tf get $/tProj/DesiredFolder -version:C%changeset% -recursive -noprompt
tf workfold -unmap . -workspace:%workspace_name%
tf workspace -delete %workspace_name% -noprompt

启动下载的解决方案时需要确认删除源代码控制关联。

【问题讨论】:

  • 你能解释/详细说明“为不同的时间做这件事”吗?
  • @Nockawa:也许应该有不同的变更集。我只需要研究它的行为方式是否以及为什么与以前不同。
  • 您能解释一下为什么使用工作区进行操作不方便吗?如果您设置了工作区并且想要将整个项目同步到变更集 150,您可以使用一个命令来执行此操作:“tf get /version:150”。
  • @TaylorLafrinere:我有与当前开发分支同步的工作区,以及以前版本的分支。不,我需要一些临时的,最好是独立于 tfs 的东西来研究旧版本的行为。任务完成后我删除。如果我不喜欢其他东西,我会下载到另一个文件夹。不应该有通往 Tfs 的反向路径。但也许我没有正确理解工作空间范式。

标签: command-line tfs tfs-sdk visual-studio-macros


【解决方案1】:

我将此语法用于临时工作区:

tf workspace -new %JOB_NAME%;%user% -noprompt -server:http://%host%:8080/tfs/%project% -login:%user%,%password%
tf workfold -map $/Release/MilestoneX.X . -workspace:%JOB_NAME% -server:http://%host%:8080/tfs/%project% -login:%user%,%password%
tf get . -version:L%TFS_LABEL% -recursive -noprompt -login:%user%,%password%
tf workfold -unmap . -workspace:%JOB_NAME% -login:%user%,%password%
tf workspace -delete %JOB_NAME%;%user% -noprompt -server:http://%host%:8080/tfs/%project% -login:%user%,%password%

【讨论】:

    【解决方案2】:

    我发现您可以通过 TFS 公开的 HTTP api 执行此操作。 URL 的“签名”如下:

    http(s)://{server}:{port}/tfs/{collectionName}/{teamProjectName}/_api/_versioncontrol/itemContentZipped?version={versionSpec}&path={escapedPathToFolder}
    

    所以,如果你在 DefaultCollection 中有一个名为“MyProject”的项目,并且想要获取名为“MyFeature”的文件夹的内容:

    http://MyTfsServer:8080/tfs/DefaultCollection/MyProject/_api/_versioncontrol/itemContentZipped?version=C1001&path=%24%2FMyProject%2FMyFeature
    

    我认为“版本”可以是 TFS API 文档中记录的任何版本规范。我的示例是请求更改集 1001 的版本。我使用 .NET API 来获取特定版本,这非常简单,但速度很慢,因为它一次只能获取一个文件。我试图弄清楚是否通过 .NET API 公开了相同的功能,因为以这种方式下载文件比一次获取单个文件要快得多。

    我在Microsoft.TeamFoundation.VersionControl.Client.Item. 上将其作为扩展方法实现,这将返回一个包含 zip 文件的流。我曾将此用作自定义 MSBuild 任务的一部分,然后将此流的内容保存到文件位置。

    public static class TfsExtensions
    {
    
        const String ItemContentZippedFormat = "/_api/_versioncontrol/itemContentZipped?version={0}&path={1}&__v=3";
    
        public static Stream DownloadVersion(this Item folder, VersionSpec version)
        {
            if (folder.ItemType != ItemType.Folder)
                throw new ArgumentException("Item must be a folder", "folder");
    
    
            var vcs = folder.VersionControlServer;
    
            var collectionName = vcs.TeamProjectCollection.CatalogNode.Resource.DisplayName;
    
            var baseUri = folder.VersionControlServer.TeamFoundationServer.Uri;
            if (!baseUri.LocalPath.EndsWith(collectionName, StringComparison.OrdinalIgnoreCase))
                baseUri = new Uri(baseUri, baseUri.LocalPath + "/" + collectionName);
    
    
            var apiPath = String.Format(ItemContentZippedFormat, version.DisplayString, WebUtility.UrlEncode(folder.ServerItem));
            var downloadUri = new Uri(baseUri, baseUri.LocalPath + apiPath);
    
            var req = WebRequest.Create(downloadUri);
            req.Credentials = CredentialCache.DefaultCredentials;
            var response = req.GetResponse();
            return response.GetResponseStream();
        }
    }
    

    【讨论】:

    • 您是使用 WebClient 还是其他方式与 tfs 服务器通信?您会添加示例代码吗?
    • @IvanH 我使用 System.Net.WebRequest 来获取内容。包括一个例子。
    • 请注意,如果您配置了下载代理,则使用这种机制不会利用下载代理。否则,这确实是一个非常好的机制。
    • “.zip 从网址下载”方法在此处产生以下结果:对于 $\Main 文件夹,它下载一个 Main.zip 文件夹,其中包含一个完全空的 Main 文件夹;对于$\Main\SomeFile.ext,它给出了错误No matching items found in $/Main/SomeFile.ext at the specified version, or you do not have permission to access them
    【解决方案3】:

    我认为你应该创建一个临时工作区来检索你想要的内容,然后删除工作区并保留本地项目。

    TFS 中的工作区是服务器上内容的本地视图,对于给定的工作区,您可以选择要在本地检索的文件夹以及存储文件夹/文件的位置。

    与 SourceSafe 不同,您不仅仅局限于一个工作区,您可以在给定的计算机上拥有任意数量的工作区。

    所以我建议你为你想做的操作创建一个专门的工作区,当你判断它合适的时候就去掉它。

    使用TF.exe workspace 命令从Shell 创建/删除工作区。然后TF.exe get 检索文件。

    【讨论】:

    • 我会给它一个机会。但我想有一些东西作为视图,但对于一个文件夹。
    【解决方案4】:

    您可以使用tf view 获取特定文件,而无需创建工作区。

    Retrieves a specific version of a file to a temporary folder on your computer and displays it.
    
    tf vc view [/collection:TeamProjectCollectionUrl]
           [/console] [/recursive] [/output:localfile]
           [/shelveset:shelvesetname[;owner]] [/noprompt] itemspec
           [/version:versionspec] [/login:username,[password]]
    
    Versionspec:
    Date/Time         D"any .Net Framework-supported format"
                      or any of the date formats of the local machine
    Changeset number  Cnnnnnn
    Label             Llabelname
    Latest version    T
    Workspace         Wworkspacename;workspaceowner
    

    【讨论】:

    • 此方法仅适用于单个文件,不适用于目录。在这里运行命令将生成一个巨大的文件(名为 C:\path\to\localdirectory),其中包含文件夹中连接在一起的每个文件。
    • @JamesQMurphy,谢谢!我不敢相信这是怎么回事。我最终通过结合使用dirview 的powershell 函数解决了这个问题。你可以在这个gist看到它。
    猜你喜欢
    • 1970-01-01
    • 2016-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-05
    相关资源
    最近更新 更多