Background,
I am making a TFS merge tool to service out development and Branch requirements.
Withing this tool I have a business object layer that uses the Microsoft.Teamfoundation.ExtendedClient Package.
What I have
I currently have a function that does the checkin for my pending items
The 'changes' object has all my changes in it. Included and Excluded
Workspace workspace = _vcs.GetWorkspace(_workspaceName, _workspaceOwner);
WorkItemCheckinInfo checkInInfo = new WorkItemCheckinInfo(pbi, WorkItemCheckinAction.Associate);
PendingChange[] changes = workspace.GetPendingChanges();
ChangesetID = workspace.CheckIn(changes, checkInComment, null, new WorkItemCheckinInfo[] {
checkInInfo }, null);
What I need
I need to only get his list of 'Included' Pending changes.
Some have suggested using, bu this fails as ITS only has zero rows.
//get all candidate changes and promote them to included changes
PendingChange[] candidateChanges = null;
string serverPath = workspace.GetServerItemForLocalItem(_workspaceName);
List<ItemSpec> its = new List<ItemSpec>();
its.Add(new ItemSpec(serverPath, RecursionType.Full));
workspace.GetPendingChangesWithCandidates(its.ToArray(), true, out candidateChanges);
foreach (var change in candidateChanges)
{
if (change.IsAdd)
{
//ws.PendAdd(change.LocalItem);
}
else if (change.IsDelete)
{
//ws.PendDelete(change.LocalItem);
}
}
I have also tried this but SavedCheckin = null and i get an exception.
SavedCheckin savedCheckin = workspace.LastSavedCheckin;
// Create a list of pending changes.
var pendingAdds = new List<PendingChange>(workspace.GetPendingChanges());
List<PendingChange> excludedChanges = new List<PendingChange>();
for (int i = 0; i <= changes.Length - 1; i++)
{
if (savedCheckin.IsExcluded(changes[i].ServerItem))
{
excludedChanges.Add(changes[i]);
}
Console.WriteLine(changes[i].LocalItem.ToString() + " Change " + changes[i].ChangeType)
}
So I either need to iterate through the 'changes' list and remove 'Excluded' items
or there is bound to be something im missing here.
thanks in advance
Alan
There is no TFS API to get only Included changes, Included/Excluded changes sections exist in Visual Studio/Team Explorer. Visual Studio detects changes you make outside the system.
What you need is Visual Studio Extension API -- IPendingChangesExt Interface, you could refer to the article below or open a case on Visual Studio Extension side.
https://www.mztools.com/articles/2015/MZ2015007.aspx
Related
I'm able to copy most test cases with this code (trying to copy shared steps to be part of the test case itself) but this one will not copy but I can not see any error message as to why - could anyone suggest anything else to try. See output from Immediate windows. Thanks John.
?targetTestCase.Error
null
?targetTestCase.InvalidProperties
Count = 0
?targetTestCase.IsDirty
true
?targetTestCase.State
"Ready"
?targetTestCase.Reason
"New"
foreach (ITestAction step in testSteps)
{
if (step is ITestStep)
{
ITestStep sourceStep = (ITestStep)step;
ITestStep targetStep = targetTestCase.CreateTestStep();
targetStep.Title = sourceStep.Title;
targetStep.Description = sourceStep.Description;
targetStep.ExpectedResult = sourceStep.ExpectedResult;
//Copy Attachments
if (sourceStep.Attachments.Count > 0)
{
string attachmentRootFolder = _tfsServiceUtilities.GetAttachmentsFolderPath();
string testCaseFolder = _tfsServiceUtilities.CreateDirectory(attachmentRootFolder, "TestCase_" + targetTestCase.Id);
//Unique folder path for test step
string TestStepAttachementFolder = _tfsServiceUtilities.CreateDirectory(testCaseFolder, "TestStep_" + sourceStep.Id);
using (var client = new WebClient())
{
client.UseDefaultCredentials = true;
foreach (ITestAttachment attachment in sourceStep.Attachments)
{
string attachmentPath = TestStepAttachementFolder + "\\" + attachment.Name;
client.DownloadFile(attachment.Uri, attachmentPath);
ITestAttachment newAttachment = targetTestCase.CreateAttachment(attachmentPath);
newAttachment.Comment = attachment.Comment;
targetStep.Attachments.Add(newAttachment);
}
}
}
targetTestCase.Actions.Add(targetStep);
targetTestCase.Save();
}
Since this code works for most test cases, this issue may come from the particular test case. In order to narrow down the issue, please try the following items:
Run the code on another client machine to see whether it works.
Try to modify this particular test case using the account API uses, to see whether it can be saved successfully.
Try validate the WorkItem prior to save. The validate() method will return an arraylist of invalid fields.
what I have found that the images uploaded by my application are not included in the project and that I have to include them manually image by image so what is the correct way of asp.net mvc project to let the images uploaded to be included in the project.
The following code is the one that upload the images to the folder and creates a unique name for each image. but still those images are not included in the project explorer.
public ActionResult Create(Job job, HttpPostedFileBase JobImage)
{
var value = "999999999";
var result4 = from app in db.Job where app.UniqueJobImageName.Contains(value) select app;
if(result4.FirstOrDefault() != null)
{
value = generateRandom();
}
if (ModelState.IsValid && CheckFileType(JobImage.FileName))
{
string ext = Path.GetExtension(JobImage.FileName);
var fileName = Path.GetFileName(JobImage.FileName);
job.JobImage = JobImage.FileName;
job.UniqueJobImageName = value + ext;
var path = Path.Combine(Server.MapPath("~/Images"), value + ext);
JobImage.SaveAs(path);
job.UserId = User.Identity.GetUserId();
job.jobUrl = "";
job.Month = DateTime.Now.ToString("MMMM");
job.DateAndTime = DateTime.Now;
AllJobModel all = new AllJobModel
{
JobTitle = job.JobTitle,
JobDescription = job.JobDescription,
JobImage = job.JobImage,
UniqueJobImageName = job.UniqueJobImageName,
locationName = job.locationName,
minimumSalary = job.minimumSalary.ToString(),
maximumSalary = job.maximumSalary.ToString(),
jobUrl = job.jobUrl,
PostedDate = DateTime.Now.ToString("dd/MM/yyyy"),
UserId= User.Identity.GetUserId(),
};
db.AllJobModel.Add(all);
db.SaveChanges();
db.Job.Add(job);
db.SaveChanges();
return RedirectToAction("Index","Home");
}else if (!CheckFileType(JobImage.FileName))
{
}
return View(job);
}
enter image description here
This doesn't make any sense. The uploaded images are content created by the user. They are not a deployable component of the site (or, they shouldn't be anyway). They are user-generated content, not developer resources.
If you are looking to effectively migrate your data (i.e. copy database entries and other user-generated content such as image files) from one environment to another, then that is a separate task for which you can create a separate process and/or automated script. Don't confuse it with the job of uploading a new version of your application code.
P.S. Even if what you were asking for was a sensible goal, it's impossible anyway - the executable version of your code is not the same as the code you see in Visual Studio in your project. In a modern ASP.NET application the executable code is in a different folder (even when you're running in debug mode in Visual Studio) and it has no concept or knowledge of the original project it was compiled from, or where to find it, or how to interact with it.
I've got a large number of projects all in a single repository. I want to determine the volatility of all of these projects, i.e., when there was last a commit that affected each project. I've got a list of all of the project paths, and I'm trying to find the last commit for each one. My code looks like this:
public CommitInfo GetLastCommit(string path)
{
// resolve any \..\ and pathing weirdness
path = Path.GetDirectoryName(Path.GetFullPath(path));
var relativePath = path.Substring(BaseRepoPath.Length + 1).Replace("\\", "/");
if (!CommitCache.TryGetValue(relativePath, out CommitInfo result))
{
var options = new RepositoryOptions()
{
WorkingDirectoryPath = BaseRepoPath
};
using (var repo = new Repository(BaseRepoPath, options))
{
var filter = new CommitFilter()
{
IncludeReachableFrom = BranchName
};
var commit = repo.Commits.QueryBy(relativePath, filter).First().Commit;
result = new CommitInfo
{
When = commit.Author.When.DateTime,
Who = commit.Author.Name,
Message = commit.Message,
Files = commit.Tree.Select(x => x.Name).ToList()
};
repo.Dispose();
}
CommitCache.Add(relativePath, result);
}
return result;
}
This works, but the line where the commit is actually retrieved:
var commit = repo.Commits.QueryBy(relativePath, filter).First().Commit;
Can take up to eight minutes to complete. As far as I can tell, there's nothing especially complex about those folders...a sample of them reveals maybe twenty commits. I suspect I'm doing something wrong like loading the entire repo graph when I need something more specific, but I haven't been able to figure out a better way.
Thoughts?
Your requirement is producing following git command through lib2gitsharp package.
$ git log -1 -C "relativePath"
You can limit the size of commits with the help of Take(numberOfCommits) extension in lib2gitsharp. Please have a try with putting Take(1) before your First() like following;
var commit = repo.Commits.QueryBy(relativePath, filter).Take(1).First().Commit;
Hope this helps.
I have a VSTS project that uses Git for source control. The project has multiple repositories (11 to be precise) each with multiple branches.
Given a VSTS Id I am trying to get a list of all the Commits that are associated with that Id.
I am currently coding as follows
VSTSHelper helper = new VSTSHelper(); // my helper for establishing a connection
ProjectHttpClient projectClient = helper.Connection.GetClient<ProjectHttpClient>();
GitHttpClient gitClient = helper.Connection.GetClient<GitHttpClient>();
Microsoft.TeamFoundation.Core.WebApi.TeamProject project = projectClient.GetProject(helper.Project).Result;
List<GitRepository> gitRepositoryList = gitClient.GetRepositoriesAsync(project.Id).Result;
GitQueryCommitsCriteria criteria = new GitQueryCommitsCriteria()
{
IncludeWorkItems = true
};
foreach (GitRepository repo in gitRepositoryList)
{
List<GitBranchStats> branchStatsList = gitClient.GetBranchesAsync(repo.Id).Result;
foreach (GitBranchStats branchStats in branchStatsList)
{
criteria.ItemVersion = new GitVersionDescriptor() { Version = branchStats.Name, VersionType = GitVersionType.Branch };
List<GitCommitRef> commits = gitClient.GetCommitsAsync(repo.Id, criteria).Result;
if (commits.Count > 0)
{
List<GitCommitRef> commitsWithWorkItems = commits.Where(pc => pc.WorkItems.Count > 0).ToList();
if (commitsWithWorkItems.Count > 0)
{
// WorkItemIds is a list of int
List<GitCommitRef> workItemCommits = projectCommitsWithWorkItems.Where(
pc => pc.WorkItems.Any(x => this.WorkItemIds.Contains(Convert.ToInt32(x.Id)))).ToList();
// get the changes associated with the commit here
if (workItemCommits.Count > 0)
{
foreach (GitCommitRef wiCommit in workItemCommits)
{
GitCommitChanges wiChanges = gitClient.GetChangesAsync(wiCommit.CommitId, repo.Id).Result;
}
}
}
}
}
}
The work item id that is passed to my code (e.g Id = 810) has code that was originally committed against another Work Item Id (e.g. 675) in a different branch and then moved to the given Id. The code was then edited and then committed against the new Id (810)
My code above only ever finds the original commit against item 675 - and all the code changes are shown against this Id - including those that I was expecting to see against 810. Nothing is ever returned for Id 810.
Despite lots of googling I find myself struggling big time and I presume that I am misunderstanding some big time!
Any help or pointers in the right direction would be greatly appreciated.
You can use below code to get all the commits which link to a given work item:
As the REST API GET a work item with Fully expanded, all the links information exist under relations object. Then you can get the commits by filtering the url which contains vstfs:///Git/Commit.
int id = workitemID;
var token = "PAT";
String Uri = "https://account.visualstudio.com/DefaultCollection";
var Connection1 = new VssConnection(new Uri(Uri), new VssBasicCredential(string.Empty, token));
WorkItemTrackingHttpClient workItemTrackingClient = Connection1.GetClient<WorkItemTrackingHttpClient>();
WorkItem workitem = workItemTrackingClient.GetWorkItemAsync(id, expand: WorkItemExpand.All).Result;
Console.WriteLine("Related commits contain: ");
foreach (var relation in workitem.Relations)
{
if (relation.Url.Contains("vstfs:///Git/Commit"))
{
Console.WriteLine("commit: {0}", relation.Url);
}
}
To Get the commit sha-1 value (commit ID), it's located in the last 40 characters of the relation.Url which separate with repository ID by %2f. So the url format actually is vstfs:///Git/Commit/{projectID}%2f{repositoryID}%2f{commitID}.
Such as for a relation.Url as below:
vstfs:///Git/Commit/f7855e29-6f8d-429d-8c9b-41fd4d7e70a4%2fad3acf8e-b269-48e5-81bc-354251856b51%2fb802c91e68f321676fe31eca9dda048e7032ea11"
The commit sha-1 value is b802c91e68f321676fe31eca9dda048e7032ea11.
The repository ID is ad3acf8e-b269-48e5-81bc-354251856b51.
The project ID is f7855e29-6f8d-429d-8c9b-41fd4d7e70a4.
Is there a way to download specific TFS build log? we’re using TFS 2013.
I’ve already tried to use the IBuildDetail, yet failed.
THX.
You can use the menthod “Get Build”. It returns IBuildDetail , use IBuildDetail.LogLocation property to get the log file for this build. Finally download or query it. Below is a demo code:
publicstaticvoid GetBuildLogAndReadThroughTheLog()
{
// Get all the team projects using the TFS API
var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(ConfigurationManager.AppSettings["TfsUri"]));
var versionControlService = tfs.GetService<VersionControlServer>();
var teamProject = versionControlService.GetAllTeamProjects(false)[0];
// Use the build service to get build details for a team project
var buildService = tfs.GetService<IBuildServer>();
// Get the build details
var build = buildService.QueryBuilds(teamProject.Name)[0];
// Get the location of the build Log
var buildLogLocation = build.LogLocation;
// Get the log file
var logFile = versionControlService.GetItem(buildLogLocation);
// Do you want to download the file to a local path?
TextReader tr = new StreamReader(logFile.DownloadFile());
string input = null;
while ((input = tr.ReadLine()) != null)
{
}
}
}
The entire build log can be found in the Tfs_YourTeamProjectCollection database in the Tbl_BuildInformation. You can also query and get it from DataBase
More ways for you reference: https://paulselles.wordpress.com/2013/11/15/tfs-build-log-querying-build-log-data/
UPdate
Using "StreamReader" will read the log file line by line.
using (StreamReader sr = new StreamReader(buildLogLocation)
{
while (sr.Peek() >= 0)
{
// do your work here...
}
}