From 0dd2ffab437fddca56d679b7a1ead2b465e381cd Mon Sep 17 00:00:00 2001 From: Jameson Miller Date: Fri, 15 Mar 2013 13:50:02 -0400 Subject: [PATCH] Teach BranchUpdater to set merge branch directly --- LibGit2Sharp.Tests/BranchFixture.cs | 32 +++++++++ LibGit2Sharp/BranchUpdater.cs | 103 ++++++++++++++++++++++++---- 2 files changed, 122 insertions(+), 13 deletions(-) diff --git a/LibGit2Sharp.Tests/BranchFixture.cs b/LibGit2Sharp.Tests/BranchFixture.cs index 8091d781d..830574888 100644 --- a/LibGit2Sharp.Tests/BranchFixture.cs +++ b/LibGit2Sharp.Tests/BranchFixture.cs @@ -470,6 +470,38 @@ public void CanSetUpstreamBranch() } } + [Fact] + public void CanSetUpstreamMergeBranch() + { + const string testBranchName = "branchToSetUpstreamInfoFor"; + const string mergeBranchName = "refs/heads/master"; + const string upstreamBranchName = "refs/remotes/origin/master"; + const string upstreamRemoteName = "origin"; + + TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(StandardTestRepoPath); + + using (var repo = new Repository(path.RepositoryPath)) + { + Branch branch = repo.CreateBranch(testBranchName); + Assert.False(branch.IsTracking); + + Branch upstreamBranch = repo.Branches[upstreamBranchName]; + Branch updatedBranch = repo.Branches.Update(branch, + b => b.UpstreamRemote = upstreamRemoteName, + b => b.UpstreamMergeBranch = mergeBranchName); + + // Verify the immutability of the branch. + Assert.False(branch.IsTracking); + + Remote upstreamRemote = repo.Network.Remotes[upstreamRemoteName]; + Assert.NotNull(upstreamRemote); + + Assert.True(updatedBranch.IsTracking); + Assert.Equal(upstreamBranch, updatedBranch.TrackedBranch); + Assert.Equal(upstreamRemote, updatedBranch.Remote); + } + } + [Fact] public void CanSetLocalUpstreamBranch() { diff --git a/LibGit2Sharp/BranchUpdater.cs b/LibGit2Sharp/BranchUpdater.cs index fd834b90e..a1bb7b945 100644 --- a/LibGit2Sharp/BranchUpdater.cs +++ b/LibGit2Sharp/BranchUpdater.cs @@ -33,6 +33,13 @@ internal BranchUpdater(Repository repo, Branch branch) /// /// Passing null or string.Empty will unset the upstream. /// + /// + /// The upstream branch name is with respect to the current repository. + /// So, passing "refs/remotes/origin/master" will set the current branch + /// to track "refs/heads/master" on the origin. Passing in + /// "refs/heads/master" will result in the branch tracking the local + /// master branch. + /// /// public virtual string Upstream { @@ -48,17 +55,56 @@ public virtual string Upstream } } + /// + /// Set the upstream merge branch directly for this branch. + /// + /// To track the "master" branch on the "origin" remote, set the + /// UpstreamRemote property to "origin" and the UpstreamMergeBranch + /// property to "refs/heads/master". + /// + /// + public virtual string UpstreamMergeBranch + { + set + { + SetUpstreamMergeBranch(value); + } + } + + /// + /// Set the upstream remote for this branch. + /// + /// To track the "master" branch on the "origin" remote, set the + /// UpstreamRemote property to "origin" and the UpstreamMergeBranch + /// property to "refs/heads/master". + /// + /// + public virtual string UpstreamRemote + { + set + { + SetUpstreamRemote(value); + } + } + private void UnsetUpstream() { - repo.Config.Unset(string.Format("branch.{0}.remote", branch.Name)); - repo.Config.Unset(string.Format("branch.{0}.merge", branch.Name)); + SetUpstreamRemote(string.Empty); + SetUpstreamMergeBranch(string.Empty); } /// /// Set the upstream information for the current branch. - /// - /// The upstream branch to track. - private void SetUpstream(string upStreamBranchName) + /// + /// The upstream branch name is with respect to the current repository. + /// So, passing "refs/remotes/origin/master" will set the current branch + /// to track "refs/heads/master" on the origin. Passing in + /// "refs/heads/master" will result in the branch tracking the local + /// master branch. + /// + /// + /// The remote branch to track (e.g. refs/remotes/origin/master). + private void SetUpstream(string upstreamBranchName) { if (branch.IsRemote) { @@ -68,21 +114,52 @@ private void SetUpstream(string upStreamBranchName) string remoteName; string branchName; - GetUpstreamInformation(upStreamBranchName, out remoteName, out branchName); + GetUpstreamInformation(upstreamBranchName, out remoteName, out branchName); - SetUpstreamTo(remoteName, branchName); + SetUpstreamRemote(remoteName); + SetUpstreamMergeBranch(branchName); } - private void SetUpstreamTo(string remoteName, string branchName) + /// + /// Set the upstream merge branch for the local branch. + /// + /// The merge branch in the upstream remote's namespace. + private void SetUpstreamMergeBranch(string mergeBranchName) { - if (!remoteName.Equals(".", StringComparison.Ordinal)) + string configKey = string.Format("branch.{0}.merge", branch.Name); + + if (string.IsNullOrEmpty(mergeBranchName)) { - // Verify that remote exists. - repo.Network.Remotes.RemoteForName(remoteName); + repo.Config.Unset(configKey); } + else + { + repo.Config.Set(configKey, mergeBranchName); + } + } - repo.Config.Set(string.Format("branch.{0}.remote", branch.Name), remoteName); - repo.Config.Set(string.Format("branch.{0}.merge", branch.Name), branchName); + /// + /// Set the upstream remote for the local branch. + /// + /// The name of the remote to set as the upstream branch. + private void SetUpstreamRemote(string remoteName) + { + string configKey = string.Format("branch.{0}.remote", branch.Name); + + if (string.IsNullOrEmpty(remoteName)) + { + repo.Config.Unset(configKey); + } + else + { + if (!remoteName.Equals(".", StringComparison.Ordinal)) + { + // Verify that remote exists. + repo.Network.Remotes.RemoteForName(remoteName); + } + + repo.Config.Set(configKey, remoteName); + } } ///