Skip to content

Clean untracked files from working directory #253

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

Closed
wants to merge 2 commits into from
Closed
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
34 changes: 26 additions & 8 deletions LibGit2Sharp.Tests/CheckoutFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ public void CanCheckoutAnExistingBranch(string branchName)
Branch master = repo.Branches["master"];
Assert.True(master.IsCurrentRepositoryHead);

// Hard reset to ensure that working directory, index, and HEAD match
repo.Reset(ResetOptions.Hard);
// Set the working directory to the current head
ResetAndCleanWorkingDirectory(repo);

Assert.False(repo.Index.RetrieveStatus().IsDirty);

Branch branch = repo.Branches[branchName];
Expand Down Expand Up @@ -55,8 +56,9 @@ public void CanCheckoutAnExistingBranchByName(string branchName)
Branch master = repo.Branches["master"];
Assert.True(master.IsCurrentRepositoryHead);

// Hard reset to ensure that working directory, index, and HEAD match
repo.Reset(ResetOptions.Hard);
// Set the working directory to the current head
ResetAndCleanWorkingDirectory(repo);

Assert.False(repo.Index.RetrieveStatus().IsDirty);

Branch test = repo.Checkout(branchName);
Expand Down Expand Up @@ -84,8 +86,9 @@ public void CanCheckoutAnArbitraryCommit(string commitPointer)
Branch master = repo.Branches["master"];
Assert.True(master.IsCurrentRepositoryHead);

// Hard reset to ensure that working directory, index, and HEAD match
repo.Reset(ResetOptions.Hard);
// Set the working directory to the current head
ResetAndCleanWorkingDirectory(repo);

Assert.False(repo.Index.RetrieveStatus().IsDirty);

Branch detachedHead = repo.Checkout(commitPointer);
Expand Down Expand Up @@ -197,8 +200,9 @@ public void CanForcefullyCheckoutWithStagedChanges()
Branch master = repo.Branches["master"];
Assert.True(master.IsCurrentRepositoryHead);

// Hard reset to ensure that working directory, index, and HEAD match
repo.Reset(ResetOptions.Hard);
// Set the working directory to the current head
ResetAndCleanWorkingDirectory(repo);

Assert.False(repo.Index.RetrieveStatus().IsDirty);

// Add local change
Expand Down Expand Up @@ -335,5 +339,19 @@ private void PopulateBasicRepository(Repository repo)

repo.CreateBranch(otherBranchName);
}

/// <summary>
/// Reset and clean current working directory. This will ensure that the current
/// working directory matches the current Head commit.
/// </summary>
/// <param name="repo">Repository whose current working directory should be operated on.</param>
private void ResetAndCleanWorkingDirectory(Repository repo)
{
// Reset the index and the working tree.
repo.Reset(ResetOptions.Hard);

// Remove untracked files.
repo.Index.CleanWorkingDirectory();
}
}
}
18 changes: 18 additions & 0 deletions LibGit2Sharp.Tests/IndexFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,24 @@ public void ReadIndexWithBadParamsFails()
}
}

[Fact]
public void CanCleanWorkingDirectory()
{
TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(StandardTestRepoWorkingDirPath);
using (var repo = new Repository(path.RepositoryPath))
{
// Verify that there are the expected number of entries and untracked files
Assert.Equal(6, repo.Index.RetrieveStatus().Count());
Assert.Equal(1, repo.Index.RetrieveStatus().Untracked.Count());

repo.Index.CleanWorkingDirectory();

// Verify that there are the expected number of entries and 0 untracked files
Assert.Equal(5, repo.Index.RetrieveStatus().Count());
Assert.Equal(0, repo.Index.RetrieveStatus().Untracked.Count());
}
}

[Theory]
[InlineData("1/branch_file.txt", FileStatus.Unaltered, true, FileStatus.Unaltered, true, 0)]
[InlineData("README", FileStatus.Unaltered, true, FileStatus.Unaltered, true, 0)]
Expand Down
5 changes: 5 additions & 0 deletions LibGit2Sharp/Core/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@ internal static extern int git_checkout_head(
RepositorySafeHandle repo,
GitCheckoutOpts opts);

[DllImport(libgit2)]
internal static extern int git_checkout_index(
RepositorySafeHandle repo,
GitCheckoutOpts opts);

[DllImport(libgit2)]
internal static extern int git_clone(
out RepositorySafeHandle repo,
Expand Down
9 changes: 9 additions & 0 deletions LibGit2Sharp/Core/Proxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,15 @@ public static void git_checkout_head(RepositorySafeHandle repo, GitCheckoutOpts
}
}

public static void git_checkout_index(RepositorySafeHandle repo, GitCheckoutOpts opts)
{
using (ThreadAffinity())
{
int res = NativeMethods.git_checkout_index(repo, opts);
Ensure.Success(res);
}
}

#endregion

#region git_clone_
Expand Down
13 changes: 13 additions & 0 deletions LibGit2Sharp/Index.cs
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,19 @@ public virtual void Remove(IEnumerable<string> paths)
UpdatePhysicalIndex();
}

/// <summary>
/// Clean the working tree by removing files that are not under version control.
/// </summary>
public virtual void CleanWorkingDirectory()
{
GitCheckoutOpts options = new GitCheckoutOpts
{
checkout_strategy = CheckoutStrategy.GIT_CHECKOUT_REMOVE_UNTRACKED,
};

Proxy.git_checkout_index(this.repo.Handle, options);
}

private IEnumerable<KeyValuePair<string, FileStatus>> PrepareBatch(IEnumerable<string> paths)
{
Ensure.ArgumentNotNull(paths, "paths");
Expand Down