Programmatically retrieve list of source folders and create one if not present - C# + VSTS 2017

928 views Asked by At

I am trying to automate some processes to make life a bit easier. We have multiple requests from the team to create a folder in TFS 2017 (they do not have permissions) and then set up the associated builds for that source control folder. The build creation part I think I have a way to do, but querying our on premise TFS 2017 server to get a list of folders under a certain path is proving tricky. So far I am having trouble even connecting to the server in the first place with this :

 var collectionUri = "http://tfs-server:8080/tfs/DefaultCollection/";
 var teamProjectName = "MYPROJECT";

 Uri uri = new Uri(collectionUri);

 var clientCredentials = new VssCredentials(new WindowsCredential(new NetworkCredential("USERNAME", "PASSWORD", "COLLECTIONNAME")));
 var connection = new VssConnection(uri, clientCredentials);
 var sourceControlServer = connection.GetClient<TfvcHttpClient>();

That throws an exception : Error converting value "System.Security.Principal.WindowsIdentity;" to type 'Microsoft.VisualStudio.Services.Identity.IdentityDescriptor'

Can someone help me to get connected to the server first please! Documentation on this is very hard to find, and I dont see any examples that actually work.

What I was going to look at next was creating the folder if it doesn't exist. No idea how to do that yet, maybe using

sourceControlServer.GetBranchAsync(teamProjectName + FolderName);

Thanks!

EDIT: Ok I got it to not error creating the connection by doing this instead :

Uri uri = new Uri("http://tfs-server:8080/tfs/DefaultCollection/");

var clientCredentials = new VssCredentials(new WindowsCredential(new NetworkCredential("USERNAME", "PASSWORD", "DOMAIN")));

var buildServer = new BuildHttpClient(uri, clientCredentials);
var sourceControlServer = new TfvcHttpClient(uri, clientCredentials);

So now to just figure out how to list and create folders from TFS and to create builds!

EDIT:

So I have got the querying working, so I can check if a folder exists under a path like this :

var teamProjectName = "USA";
Uri uri = new Uri("http://tfs-server:8080/tfs/DefaultCollection/");
var clientCredentials = new VssCredentials(new WindowsCredential(new NetworkCredential("USERNAME", "PASSWORD", "DOMAIN")));

TfvcHttpClient sourceControlServer = new TfvcHttpClient(uri, clientCredentials);

List<TfvcItem> branchItems;
using (sourceControlServer) {
      branchItems = sourceControlServer.GetItemsAsync("$/USA/Development/NewFolder", VersionControlRecursionType.OneLevel).Result;
}
            
 return branchItems.Count > 0;

That will find all the items under that folder. So if there isnt a folder, it will return 0, so I can go ahead and create that folder. So next problem, is how to create the folder. Using CreateChangesetAsync.

1

There are 1 answers

5
PatrickLu-MSFT On

Update:

To use Client API and CreateChangesetAsync method to create files in TFVC, you could refer below sample console app:

using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.WebApi;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    internal class Program
    {
        internal static async Task Main(string[] args)
        {
            var orgUrl = new Uri(args[0]);
            string serverPath = args[1];
            string localPath = args[2];
            string contentType = args[3];
            string pat = args[4];

            var changes = new List<TfvcChange>()
            {
                new TfvcChange()
                {
                    ChangeType = VersionControlChangeType.Add,
                    Item = new TfvcItem()
                    {
                        Path = serverPath,
                        ContentMetadata = new FileContentMetadata()
                        {
                            Encoding = Encoding.UTF8.WindowsCodePage,
                            ContentType = contentType,
                        }
                    },
                    NewContent = new ItemContent()
                    {
                        Content = Convert.ToBase64String(File.ReadAllBytes(localPath)),
                        ContentType = ItemContentType.Base64Encoded
                    }
                }
            };
            var changeset = new TfvcChangeset()
            {
                Changes = changes,
                Comment = $"Added {serverPath} from {localPath}"
            };

            var connection = new VssConnection(orgUrl, new VssBasicCredential(string.Empty, pat));
            var tfvcClient = connection.GetClient<TfvcHttpClient>();
            await tfvcClient.CreateChangesetAsync(changeset);
        }
    }
}

Besides, instead of using tf command line, please kindly check solution here:

C# TFS API: show project structure with folders and files, including their ChangeType (checked out, deleted,renamed) like in visual studio