7

I'm interested in getting the contents of a shelveset at the command prompt. Now, you would think that a cmdlet such as Get-TfsShelveset, available in the TFS Power Tools, would do this. You might also think that "tf.exe shelvesets" would do this.

However, unless I've missed something, I'm appalled to report that neither of these is the case. Instead, each command requires you to give it a shelveset name, and then simply regurgitates a single line item for that shelveset, along with some metadata about the shelveset such as creationdate, displayname, etc. But as far as I can tell, no way to tell what's actually in the shelf.

This is especially heinous for Get-TfsShelveset, which has the ability to include an array of file descriptors along with the Shelveset object it returns. I even tried to get clever, thinking that I could harvest the file names from using -WhatIf with Restore-TfsShelveset, but sadly Restore-TfsShelveset doesn't implement -WhatIf.

Please, someone tell me I'm wrong about this!

bwerks
  • 8,651
  • 14
  • 68
  • 100

6 Answers6

11
tf status /shelveset:name

will list out the content of the named shelveset (you can also supplier an owner: see tf help status).

With the TFS PowerToy's PowerShell snapin:

Get-TfsPendingChange -Shelveset name

for the same information.

Richard
  • 106,783
  • 21
  • 203
  • 265
5

It is possible to construct a small command-line application that uses the TFS SDK, which returns the list of files contained in a given shelveset.
The sample below assumes knowledge of the Shelveset name & it's owner:

using System;
using System.IO;
using System.Collections.ObjectModel;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.VersionControl.Client;

namespace ShelvesetDetails
{
    class Program
    {
        static void Main(string[] args)
        {
            Uri tfsUri = (args.Length < 1) ? new Uri("TFS_URI") : new Uri(args[0]);

            TfsConfigurationServer configurationServer = TfsConfigurationServerFactory.GetConfigurationServer(tfsUri);

            ReadOnlyCollection<CatalogNode> collectionNodes = configurationServer.CatalogNode.QueryChildren(
                new[] { CatalogResourceTypes.ProjectCollection },
                false, CatalogQueryOptions.None);

            CatalogNode collectionNode = collectionNodes[0];

            Guid collectionId = new Guid(collectionNode.Resource.Properties["InstanceId"]);
            TfsTeamProjectCollection teamProjectCollection = configurationServer.GetTeamProjectCollection(collectionId);

            var vcServer = teamProjectCollection.GetService<VersionControlServer>();

            Shelveset[] shelves = vcServer.QueryShelvesets(
                "SHELVESET_NAME", "SHELVESET_OWNER");
            Shelveset shelveset = shelves[0];

            PendingSet[] sets = vcServer.QueryShelvedChanges(shelveset);
            foreach (PendingSet set in sets)
            {
                PendingChange[] changes = set.PendingChanges;
                foreach (PendingChange change in changes)
                {
                    Console.WriteLine(change.FileName);
                }
            }
        }
    }
}

Invoking this console app & catching the outcome during execution of the powershell should be possible.

pantelif
  • 8,524
  • 2
  • 33
  • 48
  • I think I might be able to turn this into a cmdlet using the technique described in this article: http://akutz.wordpress.com/2010/11/03/get-msi/. Will report back. – bwerks Jul 18 '11 at 21:17
  • Marking this as the answer to give proper credit to my solution, given below. – bwerks Jul 19 '11 at 17:37
3

Try:

tfpt review /shelveset:shelvesetName;userName

You may also need to add on the server option so something like:

tfpt review /shelveset:Code Review;jim /sever:company-source

I think this is what you are looking for.

Mike Veigel
  • 3,795
  • 2
  • 20
  • 28
  • Ah nuts. It's so close! It actually is what I'm looking for, but it pops up a UI window instead of printing out anything that can be consumed in a pipeline by powershell. – bwerks Jul 02 '11 at 06:57
  • Yeah- this is the only way to get that type of a list from the command line that I am aware of :/ – Mike Veigel Jul 04 '11 at 16:48
  • This pops out a GUI dialog-box. My need is to get the file-list as text. – Radim Cernej Apr 08 '14 at 21:49
2

This is what I ended up with, based on pentelif's code and the technique in the article at http://akutz.wordpress.com/2010/11/03/get-msi/ linked in my comment.

function Get-TfsShelvesetItems
{
    [CmdletBinding()]
    param
    (
        [string] $ShelvesetName = $(throw "-ShelvesetName must be specified."),
        [string] $ShelvesetOwner = "$env:USERDOMAIN\$env:USERNAME",
        [string] $ServerUri = $(throw "-ServerUri must be specified."),
        [string] $Collection = $(throw "-Collection must be specified.")
    )

    $getShelvesetItemsClassDefinition = @'
    public IEnumerable<PendingChange> GetShelvesetItems(string shelvesetName, string shelvesetOwner, string tfsUriString, string tfsCollectionName)
    {
        Uri tfsUri = new Uri(tfsUriString);
        TfsConfigurationServer configurationServer = TfsConfigurationServerFactory.GetConfigurationServer(tfsUri);
        ReadOnlyCollection<CatalogNode> collectionNodes = configurationServer.CatalogNode.QueryChildren( new[] { CatalogResourceTypes.ProjectCollection }, false, CatalogQueryOptions.None);
        CatalogNode collectionNode = collectionNodes.Where(node => node.Resource.DisplayName == tfsCollectionName).SingleOrDefault();
        Guid collectionId = new Guid(collectionNode.Resource.Properties["InstanceId"]);
        TfsTeamProjectCollection teamProjectCollection = configurationServer.GetTeamProjectCollection(collectionId);
        var vcServer = teamProjectCollection.GetService<VersionControlServer>();
        var changes = new List<PendingChange>();
        foreach (Shelveset shelveset in vcServer.QueryShelvesets(shelvesetName, shelvesetOwner))
        {
            foreach (PendingSet set in vcServer.QueryShelvedChanges(shelveset))
            {
                foreach ( PendingChange change in set.PendingChanges )
                {
                    changes.Add(change);
                }
            }
        }
        return changes.Count == 0 ? null : changes;
    }
'@;

    $getShelvesetItemsType = Add-Type `
        -MemberDefinition $getShelvesetItemsClassDefinition `
        -Name "ShelvesetItemsAPI" `
        -Namespace "PowerShellTfs" `
        -Language CSharpVersion3 `
        -UsingNamespace System.IO, `
                        System.Linq, `
                        System.Collections.ObjectModel, `
                        System.Collections.Generic, `
                        Microsoft.TeamFoundation.Client, `
                        Microsoft.TeamFoundation.Framework.Client, `
                        Microsoft.TeamFoundation.Framework.Common, `
                        Microsoft.TeamFoundation.VersionControl.Client `
        -ReferencedAssemblies "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0\Microsoft.TeamFoundation.Client.dll", `
                                "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0\Microsoft.TeamFoundation.Common.dll", `
                                "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0\Microsoft.TeamFoundation.VersionControl.Client.dll" `
        -PassThru;

    # Initialize an instance of the class.
    $getShelvesetItems = New-Object -TypeName "PowerShellTfs.ShelvesetItemsAPI";

    # Emit the pending changes to the pipeline.
    $getShelvesetItems.GetShelvesetItems($ShelvesetName, $ShelvesetOwner, $ServerUri, $Collection);
}
bwerks
  • 8,651
  • 14
  • 68
  • 100
  • Due to time constraints, this code has not yet been documented, and error handling is minimal, etc etc standard MSDN Magazine boilerplate disclaimers etc etc :) – bwerks Jul 19 '11 at 17:44
1

Spent a few days trying to do this as well, this always popped up on google so here is what I found to help future generations:

To get the contents of the shelveset (at least with Team Explorer Everywhere),
use the command: tf difference /shelveset:<Shelveset name>

That will print out the contents of the shelveset and give filenames in the form :
<Changetype>: <server file path>; C<base change number>
Shelved Change: <server file path again>;<shelveset name>

So if your file is contents/test.txt
in the shelveset shelve1 (with base revision 1), you will see :
edit: $/contents/file.txt;C1
Shelved Change: $/contents/file.txt;shelve1

After that, using the tf print command
(or view if not using TEE) on $/contents/file.txt;shelve1 should get you the contents :

tf print $/contents/file.txt;shelve1

Shows you what is in the file.txt in shelveset shelve1

TheCodeArtist
  • 21,479
  • 4
  • 69
  • 130
Greg W.
  • 51
  • 2
0

If you want get shelveset changes from server by using tfs command

Using power shell:

Get-TfsPendingChange -Server http://example.com/org -Shelveset shelvsetName

Using vs commands:

c:\projects>tf shelvesets BuddyTest_23

more info about this please see here https://learn.microsoft.com/en-us/azure/devops/repos/tfvc/shelvesets-command?view=azure-devops