Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix empty folder issue in Repositoy.Worktrees.Add #2099

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 105 additions & 4 deletions LibGit2Sharp.Tests/WorktreeFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;

namespace LibGit2Sharp.Tests
Expand Down Expand Up @@ -238,7 +236,7 @@ public void CanForcePruneLockedWorktree()
}

[Fact]
public void CanAddWorktree()
public void CanAddWorktree_WithUncommitedChanges()
{
var repoPath = SandboxWorktreeTestRepo();
using (var repo = new Repository(repoPath))
Expand All @@ -252,15 +250,96 @@ public void CanAddWorktree()
Assert.False(worktree.IsLocked);

Assert.Equal(3, repo.Worktrees.Count());

// Check that branch contains same number of files and folders
// NOTE: There is an open bug - [Repository.Worktrees.Add leaves now worktree empty](https://github.com/libgit2/libgit2sharp/issues/2037)
Assert.True(repo.RetrieveStatus().IsDirty);
var filesInMain = GetFilesOfRepo(repoPath);
var filesInBranch = GetFilesOfRepo(path);
Assert.NotEqual(filesInMain, filesInBranch);

repo.Reset(ResetMode.Hard);
repo.RemoveUntrackedFiles();

Assert.False(repo.RetrieveStatus().IsDirty);
filesInMain = GetFilesOfRepo(repoPath);
filesInBranch = GetFilesOfRepo(path);
Assert.Equal(filesInMain, filesInBranch);
}
}

[Fact]
public void CanAddWorktree_WithCommitedChanges()
{
var repoPath = SandboxWorktreeTestRepo();
using (var repo = new Repository(repoPath))
{
// stage all changes
Commands.Stage(repo, "*");
repo.Commit("Apply all changes", Constants.Signature, Constants.Signature);

Assert.Equal(2, repo.Worktrees.Count());

var name = "blah";
var path = Path.Combine(repo.Info.WorkingDirectory, "..", "worktrees", name);
var worktree = repo.Worktrees.Add(name, path, false);
Assert.Equal(name, worktree.Name);
Assert.False(worktree.IsLocked);

Assert.Equal(3, repo.Worktrees.Count());

// Check that branch contains same number of files and folders
// NOTE: There is an open bug - [Repository.Worktrees.Add leaves now worktree empty](https://github.com/libgit2/libgit2sharp/issues/2037)
Assert.False(repo.RetrieveStatus().IsDirty);
var filesInMain = GetFilesOfRepo(repoPath);
var filesInBranch = GetFilesOfRepo(path);
Assert.Equal(filesInMain, filesInBranch);
}
}

[Fact]
public void CanAddLockedWorktree_WithUncommitedChanges()
{
var repoPath = SandboxWorktreeTestRepo();
using (var repo = new Repository(repoPath))
{
Assert.Equal(2, repo.Worktrees.Count());

var name = "blah";
var path = Path.Combine(repo.Info.WorkingDirectory, "..", "worktrees", name);
var worktree = repo.Worktrees.Add(name, path, true);
Assert.Equal(name, worktree.Name);
Assert.True(worktree.IsLocked);

Assert.Equal(3, repo.Worktrees.Count());

// Check that branch contains same number of files and folders
// NOTE: There is an open bug - [Repository.Worktrees.Add leaves now worktree empty](https://github.com/libgit2/libgit2sharp/issues/2037)
Assert.True(repo.RetrieveStatus().IsDirty);
var filesInMain = GetFilesOfRepo(repoPath);
var filesInBranch = GetFilesOfRepo(path);
Assert.NotEqual(filesInMain, filesInBranch);

repo.Reset(ResetMode.Hard);
repo.RemoveUntrackedFiles();

Assert.False(repo.RetrieveStatus().IsDirty);
filesInMain = GetFilesOfRepo(repoPath);
filesInBranch = GetFilesOfRepo(path);
Assert.Equal(filesInMain, filesInBranch);
}
}

[Fact]
public void CanAddLockedWorktree()
public void CanAddLockedWorktree_WithCommitedChanges()
{
var repoPath = SandboxWorktreeTestRepo();
using (var repo = new Repository(repoPath))
{
// stage all changes
Commands.Stage(repo, "*");
repo.Commit("Apply all changes", Constants.Signature, Constants.Signature);

Assert.Equal(2, repo.Worktrees.Count());

var name = "blah";
Expand All @@ -270,6 +349,13 @@ public void CanAddLockedWorktree()
Assert.True(worktree.IsLocked);

Assert.Equal(3, repo.Worktrees.Count());

// Check that branch contains same number of files and folders
// NOTE: There is an open bug - [Repository.Worktrees.Add leaves now worktree empty](https://github.com/libgit2/libgit2sharp/issues/2037)
Assert.False(repo.RetrieveStatus().IsDirty);
var filesInMain = GetFilesOfRepo(repoPath);
var filesInBranch = GetFilesOfRepo(path);
Assert.Equal(filesInMain, filesInBranch);
}
}

Expand All @@ -292,7 +378,22 @@ public void CanAddWorktreeForCommittish()
Assert.Equal(committish, repository.Head.FriendlyName);
}
Assert.Equal(3, repo.Worktrees.Count());

// Check that branch contains same number of files and folders
// NOTE: There is an open bug - [Repository.Worktrees.Add leaves now worktree empty](https://github.com/libgit2/libgit2sharp/issues/2037)
var filesInCommittish = new string[] { "numbers.txt", "super-file.txt" };
var filesInBranch = GetFilesOfRepo(path);
Assert.Equal(filesInCommittish, filesInBranch);
}
}

private static IEnumerable<string> GetFilesOfRepo(string repoPath)
{
return Directory.GetFiles(repoPath, "*", SearchOption.AllDirectories)
.Where(fileName => !fileName.StartsWith($"{repoPath}\\.git", StringComparison.InvariantCultureIgnoreCase))
.Select(fileName => fileName.Replace($"{repoPath}\\", "", StringComparison.InvariantCultureIgnoreCase))
.OrderBy(fileName => fileName, StringComparer.InvariantCultureIgnoreCase)
.ToList();
}
}
}
8 changes: 5 additions & 3 deletions LibGit2Sharp/Core/GitWorktree.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

namespace LibGit2Sharp.Core
{
Expand Down Expand Up @@ -38,7 +36,11 @@ internal class git_worktree_add_options

public IntPtr @ref = IntPtr.Zero;

public GitCheckoutOpts checkoutOpts = new GitCheckoutOpts { version = 1 };
public GitCheckoutOpts checkoutOpts = new GitCheckoutOpts
{
version = 1,
checkout_strategy = CheckoutStrategy.GIT_CHECKOUT_FORCE
};
}

[StructLayout(LayoutKind.Sequential)]
Expand Down
29 changes: 12 additions & 17 deletions LibGit2Sharp/WorktreeCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;

namespace LibGit2Sharp
{
Expand Down Expand Up @@ -48,22 +46,21 @@ public virtual Worktree this[string name]
}

/// <summary>
///
/// Creates a worktree from a committish or branch.
/// </summary>
/// <param name="committishOrBranchSpec"></param>
/// <param name="name"></param>
/// <param name="path"></param>
/// <param name="committishOrBranchSpec">A committish or branch name./param>
/// <param name="name">Name of the worktree.</param>
/// <param name="path">Location of the worktree.</param>
/// <param name="isLocked"></param>
/// <returns></returns>
public virtual Worktree Add(string committishOrBranchSpec, string name, string path, bool isLocked)
{
if(string.Equals(committishOrBranchSpec, name))
if (string.Equals(committishOrBranchSpec, name))
{
// Proxy.git_worktree_add() creates a new branch of name = name, so if we want to checkout a given branch then the 'name' cannot be the same as the target branch
return null;
}

git_worktree_add_options options = new git_worktree_add_options
var options = new git_worktree_add_options
{
version = 1,
locked = Convert.ToInt32(isLocked)
Expand All @@ -83,20 +80,18 @@ public virtual Worktree Add(string committishOrBranchSpec, string name, string p
}
}



return this[name];
return this[name];
}

/// <summary>
///
/// Creates a worktree from a committish or branch.
/// </summary>
/// <param name="name"></param>
/// <param name="path"></param>
/// <param name="isLocked"></param>
/// <param name="committishOrBranchSpec">A committish or branch name./param>
/// <param name="name">Name of the worktree.</param>
/// <param name="path">Location of the worktree.</param>
public virtual Worktree Add(string name, string path, bool isLocked)
{
git_worktree_add_options options = new git_worktree_add_options
var options = new git_worktree_add_options
{
version = 1,
locked = Convert.ToInt32(isLocked)
Expand Down