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

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
}

Related

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);
}

Libgit2sharp Get remote branches

Maybe asked before, but I cannot find the clear answer. When I need to list the branches of a repo with gitlib2sharp, do I really first need to clone to a local repo? What is the sense in that? I just want to clone a specific branch, like you do with git clone https://bla/repo.git -b branch1
Now I first need to do a local checkout, then get the branches and from there do a second round.
Am I missing something here (hope I do).
TIA for your answer!
Grtz,
Ronald
Update (to long for comment):
OK, so here's the use case. A company delivers ssrs reports, which we need to deploy through TAP. So my thoughts were to do this via Git. For each change let them create a branche, upload/alter/etc in this branche. And iterate changes in this branch till all is fine. In the iterations they should be able to (re)deploy themselves on at least T. At the final stage we merge the brnanch to master and (re)deploy master in P. In Github you can completely 'click' this flow, but of course I want to automate this and have preferably someelse push the buttons, so they don't need me for this. So what's the best programmatic choice here? When they make a branch and start deploying in T, should I create (clone) the repo, point my local repo to the specific branch, get the files (.sql and .rdl files) and execute/upload these? I was not aware that when you clone a repo, you clone all the branches with it. Thanks so far already!
If you want to do something like git clone https://bla/repo.git -b branch1 with libgtk2sharp try this one:
var exampleRepositoryUrl = "https://github.com/npgsql/npgsql.git";
var exampleDestinationFolder = "branch-hotfix-3.0.8";
var exampleBranchName = "hotfix/3.0.8";
var repositoryClonedPath = Repository.Clone(exampleRepositoryUrl,
exampleDestinationFolder,
new CloneOptions()
{
BranchName = exampleBranchName
});
using (var clonedRepo = new Repository(repositoryClonedPath))
{
// ...
}
To list names of remote branches without cloning a repo you can use something like this:
var branches = Repository.ListRemoteReferences(exampleRepositoryUrl)
.Where(elem => elem.IsLocalBranch)
.Select(elem => elem.CanonicalName
.Replace("refs/heads/", ""));
PiKos answer worked for me, but I had to set a credentials handler, e.g.:
var branches = Repository.ListRemoteReferences(exampleRepositoryUrl, MyCredentialsHandler)
.Where(elem => elem.IsLocalBranch)
.Select(elem => elem.CanonicalName
.Replace("refs/heads/", ""));
For more details on how to set a custom credentials handler, see this answer:
https://stackoverflow.com/a/55371988/5507590

C# code or library to Update virtual directory contents without breaking clients

I have a lot of regularly updating static content that is made available via HTTP through IIS as a Virtual Directory. I have a C# application that updates this static content. The static content represents a matching set.
This content changes regularly and is validated before being made available to clients. I am currently doing a Directory Copy using this code but it is a bit brute force.
The content has a manifest file with version information. I know I can update the manifest file last but I don't want to pull the rug from under clients that are already downloading older content and leave them with a dirty set of files.
What is the recommended way to do a folder replace so that existing clients don't get a mixed up version of the file set? This must be common but I cannot find any libraries or best practice guidance to do this.
I've looked things like rsync for Windows and other backup/restore style tools but they all seem like overkill and generally don't have an API.
I ended up using the Microsoft Sync Framework. It worked out reasonably well. There are still a few bugs. Here's a good intro to the framework.
This is the significant part of my implementation.
public static bool DirectorySynchronisation(string sourceFiles, string targetFiles)
{
Trace.Info("Beginning Directory Sync");
try
{
Trace.Info("... between source location: {0} and targeted location: {1}", sourceFiles, targetFiles);
//Exclude metadata from sync.
var fileSyncScopeFilter = new FileSyncScopeFilter();
fileSyncScopeFilter.FileNameExcludes.Add("metadata.abc");
// Create file system provider
var source = new FileSyncProvider(Guid.NewGuid(), sourceFiles, fileSyncScopeFilter, FileSyncOptions.None);
var target = new FileSyncProvider(Guid.NewGuid(), targetFiles);
// Ask providers to detect changes
source.DetectChanges();
target.DetectChanges();
// Sync changes
SyncOrchestrator agent = new SyncOrchestrator
{
LocalProvider = source,
RemoteProvider = target,
Direction = SyncDirectionOrder.Upload //One way only
};
agent.Synchronize();
Trace.Info("Completed Directory Sync");
return true;
}
catch (Exception exception)
{
Trace.Info("Exception thrown while syncing files");
Trace.Exception(exception);
return false;
}
}
Hope this helps someone.

Using p4 api .NET to add files to a Changelist

My overall goal is to be able to sync, check out, and check in files within a workspace. This is the main part I am confused about:
IList<FileSpec> files = new List<FileSpec>();
FileSpec file = new FileSpec(testpath, null, locpath, VersionSpec.Head);
files.Add(file);
IList<FileSpec> foundFiles = rep.GetDepotFiles(files, null);
con.Client.SyncFiles(foundFiles, null);
Changelist cl = new Changelist();
cl.Description = "newest change";
cl.ClientId = ws_client;
Changelist changelist = rep.CreateChangelist(cl);
//Added the line below
con.Client.EditFiles(new Options(EditFilesCmdFlags.None, changelist.Id, null), file);
I first create the list of depot files (foundFiles) that I get from the repository, which works fine. I then try to sync these files to the client. I then create a Changelist, but I do not know how to go about editing files and submitting the changes. I am aware of the Client.EditFiles and Changelist.Submit methods, but I am not sure how to utilize them in this situation since I do not fully understand the linkage between a client/workspace and a changelist. In short, I would like to be able to access, edit, and submit files. One main problem is that my Changelist has no files in it and I am predicting that knowing how to add files is the first step. Any help or sample code is greatly appreciated!
I know the question is 2 years old, but the p4api.net documentation is still poor, so any answer might help future users.
I believe your remaining problem is that you use versioned file spec. Your problem should be solved by following last line:
//Added the line below
con.Client.EditFiles(new P4.Options(P4.EditFilesCmdFlags.None, changelist.Id, null), P4.FileSpec.UnversionedSpecList(foundFiles).ToArray());
I don't have a lot of experience with P4API.NET, but I think what you need to do is call Client.EditFiles, and use the options parameter to specify the changelist. Not sure if you'd use a reference to the changelist object, or just the changelist number.

Programmatically add new iteration in TFS

I can manually add a new iteration to a team project in TFS by right clicking on the project and going to Team Project Settings > Areas and Iterations > Iterations tab.
Is there an example out there of how to do this programmatically using their API?
Thanks!
After some experimentation based on taylonr's link, here's what I came up with as a minimal solution for adding an iteration, in case any one else runs into this:
public void AddIteration(string projectName, string iterationName)
{
using (var tfsCollection = new TfsTeamProjectCollection(new Uri(tfsServerUrl), getTfsCredentials()))
{
tfsCollection.Authenticate();
var css = tfsCollection.GetService<ICommonStructureService>();
string rootNodePath = string.Format("\\{0}\\Iteration", projectName);
var pathRoot = css.GetNodeFromPath(rootNodePath);
css.CreateNode(iterationName, pathRoot.Uri);
}
}
Does this tutorial solve your problem?
http://blogs.microsoft.co.il/blogs/shair/archive/2009/01/30/tfs-api-part-10-add-area-iteration-programmatically.aspx
Google-Fu "tfs api add iteration"
From glancing at his code, (and using TFS) it looks like iterations are getting treated as hierarchies. That's why you see things like "Release1\Sprint2" etc... you can have them nested deep... deep down they're probably just a path and that's why he's using the add path etc

Categories