6

Requirement:

Using libgit2sharp I want to pull (fetch + merge) latest from a specific git remote branch to my currently checked out local branch, without having to pass any other argument, like user credentials etc. Basically I am trying to replicate git pull origin my-remote-branch

Details:

I want to automate certain Git operations from C#. I can simply do what I want by invoking git.exe (if I know the path), like git.exe --git-dir=my-repo-directory pull origin my-remote-branch. Notice that here the only external parameters I have to supply are my-repo-directory and my-remote-branch. Git gets everything right, like the name, password, email, current working branch (even if it doesnt have remote attached) and git pull simply works. I dont have to pass any of those parameters manually. I assume Git gets them from current Git settings for the repo (from %HOME% folder?).

Is there a way to simulate that in LibGit2Sharp?

What I tried:

using (var repo = new Repository("my-repo-directory"))
{
    PullOptions pullOptions = new PullOptions()
    {
        MergeOptions = new MergeOptions()
        {
            FastForwardStrategy = FastForwardStrategy.Default
        }
    };

    MergeResult mergeResult = Commands.Pull(
        repo,
        new Signature("my name", "my email", DateTimeOffset.Now), // I dont want to provide these
        pullOptions
    );
}

Which fails since it says there is no tracking branch. I dont necessarily need a tracking remote branch. I just want to fetch latest from a specific random remote repo and perform automerge if possible.

Just to see if it works I tried:

using (var repo = new Repository("my-repo-directory"))
{
    var trackingBranch = repo.Branches["remotes/origin/my-remote-branch"];

    if (trackingBranch.IsRemote) // even though I dont want to set tracking branch like this
    {
        var branch = repo.Head;
        repo.Branches.Update(branch, b => b.TrackedBranch = trackingBranch.CanonicalName);
    }

    PullOptions pullOptions = new PullOptions()
    {
        MergeOptions = new MergeOptions()
        {
            FastForwardStrategy = FastForwardStrategy.Default
        }
    };

    MergeResult mergeResult = Commands.Pull(
        repo,
        new Signature("my name", "my email", DateTimeOffset.Now),
        pullOptions
    );
}

This fails with

request failed with status code: 401

Additional info:

I dont want to invoke git.exe directly because I cant hardcode the git exe path. Also, since I cant pass username, email etc at runtime, is there a way libgit2sharp get them by itself from the repository settings, like how git.exe does?

nawfal
  • 70,104
  • 56
  • 326
  • 368

1 Answers1

7

I assume Git gets them from current Git settings for the repo (from %HOME% folder?).

It depends entirely on what the remote "origin" is:

See here for a UsernamePasswordCredentials example.
See also LibGit2Sharp.Tests/TestHelpers/Constants.cs and other occurrences.


Regarding the pull operation, it involves a Command Fetch, which involves a refspec. As in "Git pull/fetch with refspec differences", you can pass the source:destination branch names for your pull (even if there is no tracking information).

That is what is used in LibGit2Sharp.Tests/FetchFixture.cs.

string refSpec = string.Format("refs/heads/{2}:refs/remotes/{0}/{1}", remoteName, localBranchName, remoteBranchName);
Commands.Fetch(repo, remoteName, new string[] { refSpec }, new FetchOptions {
                TagFetchMode = TagFetchMode.None,
                OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler
}, null);
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Will have a look at this later and get back to you. – nawfal Oct 24 '17 at 06:43
  • 1
    @nawfal OK. A simple "git remote -v" is a good start to know what kind of URL you are dealing with. And since your main issue is 401 (lack of valid authentication), this answer is about addressing authentication issue. – VonC Oct 24 '17 at 07:03
  • the problem is even if I manage the user credentials, what would be the API to specify the branch I want to pull from? – nawfal Oct 24 '17 at 07:39
  • 1
    @nawfal First, let's resolve the authentication issue. Then, if you have setup the tracking branch (https://stackoverflow.com/a/42660436/6309) a simple pull will be enough. – VonC Oct 24 '17 at 07:42
  • Hmm, maybe I wasnt clear enough in the question, but I don't want to set a tracking branch. If I do I am messing up with other developers' settings. This is a part of automating pull operations from various remote branches for all the devs. But I think a quick fix would be set it and then reset it to its original tracked branch. – nawfal Oct 24 '17 at 08:17
  • @nawfal Then you need to pass in the pull option the name of the remote branch you want to pull from. But remember: the question is first about authentication: as long as it is not solved, no git command involving a remote will work. – VonC Oct 24 '17 at 08:19
  • I will work on authentication and all the steps later. Just skimming through the source code I dont see the option to specify remote branch in pull options. – nawfal Oct 24 '17 at 08:22
  • @nawfal you do so by specifying a refspec: https://github.com/libgit2/libgit2sharp/blob/master/LibGit2Sharp.Tests/FetchFixture.cs#L129-L153 (https://git-scm.com/book/en/v2/Git-Internals-The-Refspec) like https://stackoverflow.com/a/7169390/6309 – VonC Oct 24 '17 at 08:28
  • @nawfal I have edited the answer to include the pull branch specification part. – VonC Oct 24 '17 at 20:22
  • I do not see a way to pass in the username/password in either Pull or Fetch. Those test cases dont but succeed and I dont see how. – nawfal Oct 25 '17 at 09:40
  • @nawfal yes you can: the parameter is the refspec you set in the fetch option: it will include the local branch name, remote name (origin) and the remote branch name from which you want to fetch. – VonC Oct 25 '17 at 09:41
  • True, `refspec` has branch details. I am talking about credential details. Where in to pass it? I keep getting `401`. – nawfal Oct 25 '17 at 09:48
  • First, what is your remote url? An https one or an SSH one? – VonC Oct 25 '17 at 09:52
  • 1
    @nawfal to set credentials with Fetch, pass a `CredentialsHandler` in your `FetchOptions`. Return either `UsernamePasswordCredentials` or `DefaultCredentials` from your handler, as appropriate. – Edward Thomson Oct 25 '17 at 10:17
  • @EdwardThomson Thank you. I have included your comment in the answer for more visibility. – VonC Oct 25 '17 at 10:58