【发布时间】:2010-12-04 11:15:18
【问题描述】:
有没有人有一个方便的 powershell 脚本根据修改日期从 TFS 获取一组文件?我想说“给我这个文件夹(或子文件夹)中在 X/Y/ZZZZ 之后修改的所有文件”并将这些文件转储到他们通常会去的文件夹之外的文件夹中。我知道足够多的 powershell 来破解并最终完成这项工作,但我希望避免这种情况。
【问题讨论】:
标签: tfs powershell powershell-2.0
有没有人有一个方便的 powershell 脚本根据修改日期从 TFS 获取一组文件?我想说“给我这个文件夹(或子文件夹)中在 X/Y/ZZZZ 之后修改的所有文件”并将这些文件转储到他们通常会去的文件夹之外的文件夹中。我知道足够多的 powershell 来破解并最终完成这项工作,但我希望避免这种情况。
【问题讨论】:
标签: tfs powershell powershell-2.0
确保您已安装 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
请注意,这会将文件复制到平面文件夹结构中。如果您想维护目录结构,则涉及更多。
【讨论】:
October 2008 Team Foundation Power Tools 已失效。你能用正确的更新它吗?
像 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,我在 MS 内外参与 TFS 已有 4.5 年,但从未见过要求此功能。如果您可以扩展您实际尝试实现的目标,我猜我们可以提出更好的方法。不要误会我的意思,我编写 Powershell 扩展正是为了处理这种奇怪的场景。但通常它完全是另一个工具的工作,例如:注释、MSBuild、数据库模式比较......
【讨论】: