Get a set of files that have changed since a certain date

Does anyone have a handy powershell script that gets a set of files from TFS based on modification date ? I would like to say, "Give me all the files in this folder (or subfolder) that changed after X / Y / ZZZZ" and upload those files to a folder other than the folder they usually go to. I know enough strength to hack and do it in the end, but I hope to avoid it.

+2


source to share


2 answers


Make sure Team Foundation 2015 Power Tools is installed . It comes with PowerShell snapin. You can run the PowerShell console file directly from your launch group, or you can run the Add-PSSnapin Microsoft.TeamFoundation.PowerShell command. Then cd into your workspace and do:

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       

      

To upload this information to a directory:

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

      



To copy these files to a different directory (this assumes you pulled them locally to your working folder):

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

      

Note that this copies files into a flat folder structure. If you want to keep the dir structure, this is a little more important.

+5


source


Using a Get-TfsItemProperty like Keith doesn't just require workspace for file copies. It is a wrapper for GetExtendedItems (), a server-side request for local information most commonly seen in Source Control Explorer. Based on the version information it reports, you are assuming that the files themselves have been downloaded (more generally: synced, in the event of renames or deletions) in the last 30 days. If the workspace is not up to date, you will miss some files / give them obsolete names / etc. It is also quite expensive, as well as informational commands.

Some alternative examples:

# 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

      

The first is a simple adaptation of the Keith code that uses a cheaper query and removes the workspace dependency. This is the best option if you know that a high% of items under this distribution have been changed recently.

The second parameter directly requests the change history. By providing a Where clause that is evaluated in SQL rather than on the client, this can be an order of magnitude more efficient if a small number of items have changed recently (as is often the case). However, it will lag behind item-based queries if many large changesets are returned, causing the JOIN server to grab the object's properties costly and force the client-side duplicates to be removed to get the big work done.

[Yes, I know that having a -Version requires a not very Powershell-esque line; my fault. You can create a DateVersionSpec with a new object and call ToString () on it, but that works even more.]



I have not shown every combination of API call + desired task. Says you can use # 1 to create a list of files and # 2 to (re) download by changing the last half of the pipeline. You can even combine this copying technique with the efficiency of 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

      

It's true that round two does for the server, but thanks to the initial request, the GetExtendedItems () call will bind to the exact set of items we're interested in. And, of course, we remove any possibility of loading times becoming a bottleneck. This is probably the best solution for everyone when the number of changesets is small and the issues I brought up about Keith workspace synchronization are irrelevant for whatever reason.

Can I just say that this might seem absurd to the user.

FWIW, I have participated in TFS from inside and outside MS for 4.5yr and have never seen this feature. If you could expand on the goal that you are actually trying to accomplish, I guess we could suggest a better way. Don't get me wrong, I wrote Powershell extensions to handle scenarios like this. But often this is a job for another tool entirely, for example: Annotate, MSBuild, DB schema ...

+4


source







All Articles