2

有没有人有一个方便的 powershell 脚本,可以根据修改日期从 TFS 获取一组文件?我想说“给我这个文件夹(或子文件夹)中在 X/Y/ZZZZ 之后修改的所有文件”并将这些文件转储到他们通常会去的文件夹之外的文件夹中。我知道足够多的 powershell 来破解并最终完成这项工作,但我希望避免这种情况。

4

2 回答 2

5

确保已安装Team Foundation 2015 Power Tools。它带有一个 PowerShell 管理单元。您可以直接从其启动组运行 PowerShell 控制台文件,也可以执行 Add-PSSnapin Microsoft.TeamFoundation.PowerShell。然后 cd 到您的工作区并执行:

Get-TfsItemProperty . -r | Where {$_.CheckinDate -gt (Get-Date).AddDays(-30)} | 
    Format-Table CheckinDate,TargetServerItem -auto

CheckinDate           TargetServerItem 
-----------           ----------------
9/14/2009 1:29:23 PM  $/Foo/Trunk/Bar.sln                            
9/29/2009 5:08:26 PM  $/Foo/Trunk/Baz.sln       

将该信息转储到目录:

Get-TfsItemProperty . -r | Where {$_.CheckinDate -gt (Get-Date).AddDays(-30)} | 
    Select TargetServerItem > c:\recentlyChangedFiles.txt

要将这些文件复制到另一个目录(假设您已将它们从本地下拉到工作文件夹中):

Get-TfsItemProperty . -r | Where {$_.CheckinDate -gt (Get-Date).AddDays(-30)} | 
    CopyItem -Path $_.LocalItem -Destination C:\SomeDir -Whatif

请注意,这会将文件复制到平面文件夹结构中。如果要维护目录结构,则涉及更多。

于 2009-10-07T00:20:55.500 回答
4

像 Keith 一样使用 Get-TfsItemProperty 不仅需要用于文件副本的工作区。它是 GetExtendedItems() 的包装器,它是源代码管理资源管理器中最常见的本地信息的服务器查询。通过依赖它报告的版本信息,您假设文件本身是在过去 30 天内下载的(更一般地说:同步,在重命名和删除的情况下)。如果工作区不是最新的,您会错过一些文件/给它们提供过时的名称/等等。作为信息命令,它也非常昂贵。

一些替代示例:

# 1
Get-TfsChildItem $/FilesYouWant -R | 
    ? { $_.CheckinDate -gt (Get-Date).AddDays(-30) } | 
    % { $_.DownloadFile(join-path C:\SomeDir (split-path $_.ServerItem -leaf)) }

# 2
Get-TfsItemHistory $/FilesYouWant -R -All -Version "D$((Get-Date).AddDays(-30).ToString('d'))~" |
    Select-TfsItem |
    Select -Unique -Expand Path |
    Sort |
    Out-File c:\RecentlyChanged.txt

第一个是对 Keith 代码的直接改编,使用更便宜的查询并消除工作空间依赖性。如果您知道该目录下的大部分项目最近被修改过,这是最好的选择。

第二个选项直接查询变更集历史。通过让 Where 子句在 SQL 中而不是在客户端上计算,如果最近更改的项目的百分比较低(通常是这种情况),这可以提高一个数量级的效率。但是,如果返回大量大型变更集,它将滞后于基于项目的查询,从而使服务器的 JOIN 获取项目属性的成本很高,并迫使我们的客户端重复删除做大量工作。

[是的,我知道 -Version 需要一个字符串并不是 Powershell 式的;过失。您可以使用 new-object 创建一个 DateVersionSpec 并调用它的 ToString(),但这需要更多的工作。]

我没有展示 API 调用 + 所需任务的所有组合。不用说,您可以使用#1 生成文件列表,并使用#2 通过修改管道的后半部分来(重新)下载。您甚至可以将该复制技术与 Get-TfsItemHistory 的效率结合起来:

# 2b, with local-to-local copying
Get-TfsItemHistory $/FilesYouWant -R -All -Version "D$((Get-Date).AddDays(-30).ToString('d'))~" | 
    Select-TfsItem |
    Select -Unique -Expand Path |
    Get-TfsItemProperty | 
    Copy $_.LocalItem -Dest C:\SomeDir

确实,这会与服务器进行第二次往返,但由于初始查询,GetExtendedItems() 调用的范围将限定为我们感兴趣的精确项目集。当然,我们消除了下载时间成为瓶颈的任何机会. 当变更集的数量很小并且我提出的关于 Keith 的工作区同步的担忧无论出于何种原因都无关紧要时,这可能是所有解决方案中的最佳解决方案。

我只能说必须使用 powershell 来执行此操作似乎很荒谬。

FWIW, I've been involved with TFS from inside & outside MS for 4.5yr and never seen this feature requested. If you could expand on what goal you're actually trying to accomplish, my guess is we could suggest a better way. Don't get me wrong, I wrote the Powershell extensions precisely to handle oddball scenarios like this. But frequently it's a job for another tool entirely, eg: Annotate, MSBuild, DB schema compare...

于 2009-10-09T01:46:28.200 回答