How to retrieve git Commit Id from a C# Application? - c#

I am looking into a CI Build Automation Task and I want to name my builds using the Git Commit Id.
I am planning to write a C# program to do this. What Libraries I can use to call Git repositories from C#? I am able to call into local repository clone and retrieve this information using git.exe(Windows) or libgit2sharp but I don't know how to do it on a remote source

From a CI perspective, you may be willing to build a specific branch.
The following piece of code demonstrates this.
using (Repository repo = Repository.Clone(url, localPath))
{
// Retrieve the branch to build
var branchToBuild = repo.Branches["vNext"];
// Updates the content of the working directory with the content of the branch
branchToBuild.Checkout();
// Perform your build magic here ;-)
Build();
// Retrieve the commit sha of the branch that has just been built
string sha = branchToBuild.Tip.Sha;
// Package your build artifacts using the sha to name the package
Package(sha);
}
Note: url can either point to:
a remote http url (http://www.example.com/repo.git)
a location on the CI server (file:///C:/My%20Documents/repo.git)
a location on the network (file://server/repos/repo.git)

I have been using LibGit2Sharp for quite some time, and it is good.
Below is a sample, which will iterate through the commits in your url.
Note: I had to do a clone, not sure if there is a better way:
string url = "http://github.com/libgit2/TestGitRepository";
using (Repository repo = Repository.Clone(url, #"C:\Users\Documents\test"))
{
foreach (var commit in repo.Commits)
{
var commitId = commit.Id;
var commitRawId = commitId.RawId;
var commitSha = commitId.Sha; //0ab936416fa3bec6f1bf3d25001d18a00ee694b8
var commitAuthorName = commit.Author.Name;
commits.Add(commit);
}
}

Related

Usage of git worktrees with libgit2sharp to clone and checkout existing repos with several branches

I want to write a C# Program that devs can use to clone several git repos with worktrees added.
So my main idea is do use libgit2sharp to clone e.g. a master, and add a worktree with the checked out "develop" branch (that already exists)
I haven't found much information of how to use the Worktree feature -
when I use a .bat I remember that there seems to be (has been?) a limitation that if I want to add a worktree I must have had that branch already locally or a branch would be created locally with the same name.
Basically something along the lines of:
cd C:\gittryout\testrepo\
git clone REPO master
cd master
//to cicumvent creating a local branch develop if it hasn't been checked out already
git checkout develop
git checkout master
git worktree add --checkout ../develop develop
which would give me
C:\gittryout\testrepo\master (with master)
C:\gittryout\testrepo\develop (with develop)
my code at the moment looks something along those lines:
public void TryToCloneWithWorktree()
{
string Username = "acorrectusername";
string Password = "acorrectpw";
string RepositoryUrl = #"path/to/git/testrepo";
var co = new CloneOptions();
co.CredentialsProvider = new CredentialsHandler(
(url, usernameFromUrl, types) =>
new UsernamePasswordCredentials()
{
Username = Username,
Password = Password
}
);
co.BranchName = "master";
string RepositoryPath = #"C:\gittryout\testrepo\master";
string WorktreePath = #"C:\gittryout\testrepo\develop";
string WorktreeSHA1 = "develop";
using (var repo = new Repository())
{
Repository.Clone(RepositoryUrl, RepositoryPath, co);
repo.Worktrees.Add(WorktreeSHA1, WorktreeSHA1, WorktreePath, false);
}
}
but after this runs, the clone is correct (with branch master), and in there resides a shortcut _git2_a40776 with target .\testing
Do I need to clone the worktree added too, or how can I achieve what the bat did in C# with libgit2sharp?
br

How to get a list of remote changes from fetch using LibGit2Sharp

I am able to successfully fetch, pull, push, etc. using LibGit2Sharp, but I would like to be able to list files that have changed, added, etc. after doing a fetch. I'm using https://github.com/libgit2/libgit2sharp/wiki/git-fetch and no errors or exceptions occur and logMessage is an empty string.
I would like to be able to show a list of changes like Visual Studio does when you perform a fetch.
How can I use LibGit2Sharp to accomplish this?
Edit:
I have read through the LibGit2Sharp Wiki and the LibGit2Sharp Hitchhiker's Guide to Git. While I have tried some of the available commands to review what results they offer, I am not sure what the equivalent git command would be for this either. It would be helpful to know and understand which command would provide this information and would be appreciated if you are familiar with Git, but not LibGit2Sharp.
Once the fetch is done, you can list the fetched commit of a given branch with
git log ..#{u}
with #{u} designating the branch you are merging from (the upstream remote tracking branch, generally origin/yourbranch)
In LibGitSharp, that is what LibGit2Sharp/BranchUpdater.cs#UpstreamBranch reference (the upstream branch)
With that, you should be able to list the commmits between your current branch HEAD and "UpstreamBranch", a bit like in issue 1161, but that issue was listing what is being pushed: let's invert the log parameters here.
var trackingBranch = repo.Head.TrackedBranch;
var log = repo.Commits.QueryBy(new CommitFilter
{ IncludeReachableFrom = trackingBranch.Tip.Id, ExcludeReachableFrom = repo.Head.Tip.Id });
var count = log.Count();//Counts the number of log entries
//iterate the commits that represent the difference between your last
//push to the remote branch and latest commits
foreach (var commit in log)
{
Console.WriteLine(commit.Message);
}

How to get all changes to a file in Git, with Lib2GitSharp

I want to be able to Get a list of all changes done to a file. I've seen this post
How to get file's contents on Git using LibGit2Sharp?, but this requires to start off with a commit. I want to start digging with the filename.
Also is this possible without getting the whole repo locally?
After a bit of research I think I found an answer.
/*Small test*/
using (Repository repo = new Repository(strLocalDeliveryPath))
{
var fileHistory = repo.Commits.QueryBy(#"Path/To/file.ini").ToList();
int i = fileHistory.Count();
}
This is in order newest to oldest, and that suits me fine. I would normally only need the latest version of the file content, but nor i have the option of digging through the history of the file.
You can see this answer for a bit more info, but yes, the functionality was added in libgit2sharp 0.22.0. Here's an example:
var fileHistory = repository.Commits.QueryBy(filePathRelativeToRepository);
foreach (var version in fileHistory)
{
// Get further details by inspecting version.Commit
}

Dynamic Workspace.Merge TFS changesets

I'm writing a TFS plugin to automate merging of changesets related to a work item whenever said work item is changed from state "Resolved" to state "Closed". The following code is what I have so far:
C#
private void Action_ResolvedToClosed()
{
//Linq query for getting changesets associated with the current work item
var changeSets = WorkItem.Links
.OfType<ExternalLink>()
.Select(link =>
VersionControlServer.ArtifactProvider.GetChangeset(new Uri(link.LinkedArtifactUri))).ToList();
if (!changeSets.Any())
{
LOG_NOCHANGESETS(WorkItem.Id);
return;
}
Workspace workspace = VersionControlServer.GetWorkspace(<My Workspace>);
var source = URI_LOCAL; // $/<Project Name>/<Working Branch>
var destination = URI_DEV; // $/<Project Name>/<Development Branch>
// Merge applicable changesets
foreach (var versionSpec in changeSets.Select(changeset => new ChangesetVersionSpec(changeset.ChangesetId)))
{
workspace.Merge(source, destination, versionSpec, versionSpec);
workspace.CheckIn(workspace.GetPendingChanges(), "**Automated Merge**");
LOG_SUCCESS(versionSpec.ChangesetId, WorkItem.Id);
}
}
Is there a way to dynamically generate the workspace variable? Odds are I won't be the one actually making changes - the goal is to automate this process for our devs.
UPDATE: I'm pretty sure what I'm looking for in this second part is GetStatus, so it can be ignored. The paragraph above is my real question.
Secondary: I feel like automating merges can't be this simple. What happens if merge conflicts arise? Does Workspace.Merge fail gracefully? Are there any other glaring issues that someone with a bit more experience with the TFS API can point out?
First, it sounds like you want to query the user's workspace cache to get the appropriate Workspace and "realize" it. If
WorkspaceInfo workspaceInfo = Workstation.Current.GetLocalWorkspaceInfo(path);
Workspace workspace = workspaceInfo.GetWorkspace(new TfsTeamProjectCollection(workspaceInfo.ServerUri);
However, as you point out, you may prefer to create a temporary workspace. This will ensure that you do not conflict with any changes the user is trying to make in their own workspace. For example:
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri("http://server:8080/tfs/DefaultCollection"));
VersionControlServer vcs = tpc.GetService<VersionControlServer>();
Workspace workspace = vcs.CreateWorkspace("MERGE-TEMP");
workspace.Map("$/Merge-Source", #"C:\Temp\Merge\Source");
workspace.Map("$/Merge-Target", #"C:\Temp\Merge\Target");
Second, if you run into merge conflicts, they will be set in the workspace. You can query the NumConflicts method of the returned GetStatus. (Though you will not be able to Checkin untli you have resolved the conflicts.

Check local directory is a working copy before updating from svn

I am working on extracting svn repository using c# programming. I have added sharpsvn dll to my project and wrote following code
string localFolder= #"C:\Users\Desktop\LocalFolder\Dev\Websites\Service";
SvnClient client = new SvnClient();
SvnUriTarget target = new SvnUriTarget(#"http://svn.user.com/svn/websites/Branches/InternalServices");
SvnInfoEventArgs info;
client.GetInfo(target, out info);
//Specify the repository root as Uri
//Console.WriteLine("Repository version: {0}", info.Revision);
Console.WriteLine("Started checking out. Please wait few minutes");
client.CheckOut(target, localFolder);
//client.Update(localFolder);
I have checked out using 'client.checkout' method and i can update using 'client.update' method.
Let say i have folder 'services' in my machine. I am checking out files/folders initially using 'client.checkout' to this folder.
Next time when i run the program it should update automatically without checkout. How can i know if the service folder has already done a checkout once and now it should update?
You can determine whether a directory is a working copy like this:
public static bool IsWorkingCopy(string path)
{
using (var client = GetSvnClient())
{
var uri = client.GetUriFromWorkingCopy(path);
return uri != null;
}
}

Categories