8000 Merge pull request #1237 from libgit2/cmn/lg2-update · libgit2/libgit2sharp@cf6a3c5 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit cf6a3c5

Browse files
author
Edward Thomson
committed
Merge pull request #1237 from libgit2/cmn/lg2-update
Update to libgit2 6aa06b6
2 parents 92eaebc + 4c605af commit cf6a3c5

File tree

10 files changed

+161
-33
lines changed

10 files changed

+161
-33
lines changed

LibGit2Sharp.Tests/MergeFixture.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,24 @@ public void ConflictingMergeReposBinary()
295295
}
296296
}
297297

298+
[Fact]
299+
public void CanFailOnFirstMergeConflict()
300+
{
301+
string path = SandboxMergeTestRepo();
302+
using (var repo = new Repository(path))
303+
{
304+
var mergeResult = repo.Merge("conflicts", Constants.Signature, new MergeOptions() { FailOnConflict = true, });
305+
Assert.Equal(MergeStatus.Conflicts, mergeResult.Status);
306+
307+
var master = repo.Branches["master"];
308+
var branch = repo.Branches["conflicts"];
309+
var mergeTreeResult = repo.ObjectDatabase.MergeCommits(master.Tip, branch.Tip, new MergeTreeOptions() { FailOnConflict = true });
310+
Assert.Equal(MergeTreeStatus.Conflicts, mergeTreeResult.Status);
311+
Assert.Empty(mergeTreeResult.Conflicts);
312+
}
313+
314+
}
315+
298316
[Theory]
299317
[InlineData(true, FastForwardStrategy.Default, fastForwardBranchInitialId, MergeStatus.FastForward)]
300318
[InlineData(true, FastForwardStrategy.FastForwardOnly, fastForwardBranchInitialId, MergeStatus.FastForward)]

LibGit2Sharp/Core/GitDiff.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,12 @@ internal delegate int diff_notify_cb(
197197
IntPtr matched_pathspec,
198198
IntPtr payload);
199199

200+
internal delegate int diff_progress_cb(
201+
IntPtr diff_so_far,
202+
IntPtr old_path,
203+
IntPtr new_path,
204+
IntPtr payload);
205+
200206
[StructLayout(LayoutKind.Sequential)]
201207
internal class GitDiffOptions : IDisposable
202208
{
@@ -208,7 +214,8 @@ internal class GitDiffOptions : IDisposable
208214
public SubmoduleIgnore IgnoreSubmodules;
209215
public GitStrArrayManaged PathSpec;
210216
public diff_notify_cb NotifyCallback;
211-
public IntPtr NotifyPayload;
217+
public diff_progress_cb ProgressCallback;
218+
public IntPtr Payload;
212219

213220
/* options controlling how to diff text is generated */
214221

LibGit2Sharp/Core/GitMergeOpts.cs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ internal struct GitMergeOpts
88
{
99
public uint Version;
1010

11-
public GitMergeTreeFlags MergeTreeFlags;
11+
public GitMergeFlag MergeTreeFlags;
1212

1313
/// <summary>
1414
/// Similarity to consider a file renamed.
@@ -27,6 +27,14 @@ internal struct GitMergeOpts
2727
/// </summary>
2828
public IntPtr SimilarityMetric;
2929

30+
/// <summary>
31+
/// Maximum number of times to merge common ancestors to build a
32+
/// virtual merge base when faced with criss-cross merges. When this
33+
/// limit is reached, the next ancestor will simply be used instead of
34+
/// attempting to merge it. The default is unlimited.
35+
/// </summary>
36+
public uint RecursionLimit;
37+
3038
/// <summary>
3139
/// Flags for automerging content.
3240
/// </summary>
@@ -35,7 +43,7 @@ internal struct GitMergeOpts
3543
/// <summary>
3644
/// File merging flags.
3745
/// </summary>
38-
public GitMergeFileFlags FileFlags;
46+
public GitMergeFileFlag FileFlags;
3947
}
4048

4149
/// <summary>
@@ -98,30 +106,43 @@ internal enum GitMergePreference
98106
}
99107

100108
[Flags]
101-
internal enum GitMergeTreeFlags
109+
internal enum GitMergeFlag
102110
{
103111
/// <summary>
104112
/// No options.
105113
/// </summary>
106-
GIT_MERGE_TREE_NORMAL = 0,
114+
GIT_MERGE_NORMAL = 0,
107115

108116
/// <summary>
109117
/// Detect renames that occur between the common ancestor and the "ours"
110118
/// side or the common ancestor and the "theirs" side. This will enable
111119
/// the ability to merge between a modified and renamed file.
112120
/// </summary>
113-
GIT_MERGE_TREE_FIND_RENAMES = (1 << 0),
121+
GIT_MERGE_FIND_RENAMES = (1 << 0),
114122

115123
/// <summary>
116124
/// If a conflict occurs, exit immediately instead of attempting to
117125
/// continue resolving conflicts. The merge operation will fail with
118126
/// GIT_EMERGECONFLICT and no index will be returned.
119127
///</summary>
120-
GIT_MERGE_TREE_FAIL_ON_CONFLICT = (1 << 1),
128+
GIT_MERGE_FAIL_ON_CONFLICT = (1 << 1),
129+
130+
/// <summary>
131+
/// Do not write the REUC extension on the generated index
132+
/// </summary>
133+
GIT_MERGE_SKIP_REUC = (1 << 2),
134+
135+
/// <summary>
136+
/// If the commits being merged have multiple merge bases, do not build
137+
/// a recursive merge base (by merging the multiple merge bases),
138+
/// instead simply use the first base. This flag provides a similar
139+
/// merge base to `git-merge-resolve`.
140+
/// </summary>
141+
GIT_MERGE_NO_RECURSIVE = (1 << 3),
121142
}
122143

123144
[Flags]
124-
internal enum GitMergeFileFlags
145+
internal enum GitMergeFileFlag
125146
{
126147
/// <summary>
127148
/// Defaults

LibGit2Sharp/Core/Proxy.cs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,11 +1101,19 @@ public static void git_index_clear(Index index)
11011101

11021102
#region git_merge_
11031103

1104-
public static IndexSafeHandle git_merge_commits(RepositorySafeHandle repo, GitObjectSafeHandle ourCommit, GitObjectSafeHandle theirCommit, GitMergeOpts opts)
1104+
public static IndexSafeHandle git_merge_commits(RepositorySafeHandle repo, GitObjectSafeHandle ourCommit, GitObjectSafeHandle theirCommit, GitMergeOpts opts, out bool earlyStop)
11051105
{
11061106
IndexSafeHandle index;
11071107
int res = NativeMethods.git_merge_commits(out index, repo, ourCommit, theirCommit, ref opts);
1108-
Ensure.ZeroResult(res);
1108+
if (res == (int)GitErrorCode.MergeConflict)
1109+
{
1110+
earlyStop = true;
1111+
}
1112+
else
1113+
{
1114+
earlyStop = false;
1115+
Ensure.ZeroResult(res);
1116+
}
11091117

11101118
return index;
11111119
}
@@ -1189,7 +1197,7 @@ public static ObjectId git_annotated_commit_id(GitAnnotatedCommitHandle mergeHea
11891197
return NativeMethods.git_annotated_commit_id(mergeHead).MarshalAsObjectId();
11901198
}
11911199

1192-
public static void git_merge(RepositorySafeHandle repo, GitAnnotatedCommitHandle[] heads, GitMergeOpts mergeOptions, GitCheckoutOpts checkoutOptions)
1200+
public static void git_merge(RepositorySafeHandle repo, GitAnnotatedCommitHandle[] heads, GitMergeOpts mergeOptions, GitCheckoutOpts checkoutOptions, out bool earlyStop)
11931201
{
11941202
IntPtr[] their_heads = heads.Select(head => head.DangerousGetHandle()).ToArray();
11951203

@@ -1199,7 +1207,15 @@ public static void git_merge(RepositorySafeHandle repo, GitAnnotatedCommitHandle
11991207
ref mergeOptions,
12001208
ref checkoutOptions);
12011209

1202-
Ensure.ZeroResult(res);
1210+
if (res == (int)GitErrorCode.MergeConflict)
1211+
{
1212+
earlyStop = true;
1213+
}
1214+
else
1215+
{
1216+
earlyStop = false;
1217+
Ensure.ZeroResult(res);
1218+
}
12031219
}
12041220

12051221
public static void git_merge_analysis(

LibGit2Sharp/CurrentOperation.cs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,39 +21,49 @@ public enum CurrentOperation
2121
/// </summary>
2222
Revert = 2,
2323

24+
/// <summary>
25+
/// A sequencer revert is in progress.
26+
/// </summary>
27+
RevertSequence = 3,
28+
2429
/// <summary>
2530
/// A cherry-pick is in progress.
2631
/// </summary>
27-
CherryPick = 3,
32+
CherryPick = 4,
33+
34+
/// <summary>
35+
/// A sequencer cherry-pick is in progress.
36+
/// </summary>
37+
CherryPickSequence = 5,
2838

2939
/// <summary>
3040
/// A bisect is in progress.
3141
/// </summary>
32-
Bisect = 4,
42+
Bisect = 6,
3343

3444
/// <summary>
3545
/// A rebase is in progress.
3646
/// </summary>
37-
Rebase = 5,
47+
Rebase = 7,
3848

3949
/// <summary>
4050
/// A rebase --interactive is in progress.
4151
/// </summary>
42-
RebaseInteractive = 6,
52+
RebaseInteractive = 8,
4353

4454
/// <summary>
4555
/// A rebase --merge is in progress.
4656
/// </summary>
47-
RebaseMerge = 7,
57+
RebaseMerge = 9,
4858

4959
/// <summary>
5060
/// A mailbox application (am) is in progress.
5161
/// </summary>
52-
ApplyMailbox = 8,
62+
ApplyMailbox = 10,
5363

5464
/// <summary>
5565
/// A mailbox application (am) or rebase is in progress.
5666
/// </summary>
57-
ApplyMailboxOrRebase = 9,
67+
ApplyMailboxOrRebase = 11,
5868
}
5969
}

LibGit2Sharp/LibGit2Sharp.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3-
<Import Project="..\packages\LibGit2Sharp.NativeBinaries.1.0.106\build\LibGit2Sharp.NativeBinaries.props" Condition="Exists('..\packages\LibGit2Sharp.NativeBinaries.1.0.106\build\LibGit2Sharp.NativeBinaries.props')" />
3+
<Import Project="..\packages\LibGit2Sharp.NativeBinaries.1.0.119\build\LibGit2Sharp.NativeBinaries.props" Condition="Exists('..\packages\LibGit2Sharp.NativeBinaries.1.0.119\build\LibGit2Sharp.NativeBinaries.props')" />
44
<PropertyGroup>
55
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
66
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -405,7 +405,7 @@
405405
<PropertyGroup>
406406
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
407407
</PropertyGroup>
408-
<Error Condition="!Exists('..\packages\LibGit2Sharp.NativeBinaries.1.0.106\build\LibGit2Sharp.NativeBinaries.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\LibGit2Sharp.NativeBinaries.1.0.106\build\LibGit2Sharp.NativeBinaries.props'))" />
408+
<Error Condition="!Exists('..\packages\LibGit2Sharp.NativeBinaries.1.0.119\build\LibGit2Sharp.NativeBinaries.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\LibGit2Sharp.NativeBinaries.1.0.119\build\LibGit2Sharp.NativeBinaries.props'))" />
409409
</Target>
410410
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
411411
Other similar extension points exist, see Microsoft.Common.targets.
< 10000 /div>

LibGit2Sharp/MergeOptionsBase.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,19 @@ protected MergeOptionsBase()
2222
/// </summary>
2323
public bool FindRenames { get; set; }
2424

25+
/// <summary>
26+
/// If set, do not create or return conflict entries, but stop and return
27+
/// an error result after finding the first conflict.
28+
/// </summary>
29+
public bool FailOnConflict { get; set; }
30+
31+
/// <summary>
32+
/// Do not write the Resolve Undo Cache extension on the generated index. This can
33+
/// be useful when no merge resolution will be presented to the user (e.g. a server-side
34+
/// merge attempt).
35+
/// </summary>
36+
public bool SkipReuc { get; set; }
37+
2538
/// <summary>
2639
/// Similarity to consider a file renamed.
2740
/// </summary>

LibGit2Sharp/ObjectDatabase.cs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,13 @@ public virtual bool CanMergeWithoutConflict(Commit one, Commit another)
522522
Ensure.ArgumentNotNull(one, "one");
523523
Ensure.ArgumentNotNull(another, "another");
524524

525-
var result = repo.ObjectDatabase.MergeCommits(one, another, null);
525+
var opts = new MergeTreeOptions()
526+
{
527+
SkipReuc = true,
528+
FailOnConflict = true,
529+
};
530+
531+
var result = repo.ObjectDatabase.MergeCommits(one, another, opts);
526532
return (result.Status == MergeTreeStatus.Succeeded);
527533
}
528534

@@ -603,22 +609,41 @@ public virtual MergeTreeResult MergeCommits(Commit ours, Commit theirs, MergeTre
603609

604610
options = options ?? new MergeTreeOptions();
605611

612+
// We throw away the index after looking at the conflicts, so we'll never need the REUC
613+
// entries to be there
614+
GitMergeFlag mergeFlags = GitMergeFlag.GIT_MERGE_NORMAL | GitMergeFlag.GIT_MERGE_SKIP_REUC;
615+
if (options.FindRenames)
616+
{
617+
mergeFlags |= GitMergeFlag.GIT_MERGE_FIND_RENAMES;
618+
}
619+
if (options.FailOnConflict)
620+
{
621+
mergeFlags |= GitMergeFlag.GIT_MERGE_FAIL_ON_CONFLICT;
622+
}
623+
624+
606625
var mergeOptions = new GitMergeOpts
607626
{
608627
Version = 1,
609628
MergeFileFavorFlags = options.MergeFileFavor,
610-
MergeTreeFlags = options.FindRenames ? GitMergeTreeFlags.GIT_MERGE_TREE_FIND_RENAMES
611-
: GitMergeTreeFlags.GIT_MERGE_TREE_NORMAL,
629+
MergeTreeFlags = mergeFlags,
612630
RenameThreshold = (uint)options.RenameThreshold,
613631
TargetLimit = (uint)options.TargetLimit,
614632
};
615633

634+
bool earlyStop;
616635
using (var oneHandle = Proxy.git_object_lookup(repo.Handle, ours.Id, GitObjectType.Commit))
617636
using (var twoHandle = Proxy.git_object_lookup(repo.Handle, theirs.Id, GitObjectType.Commit))
618-
using (var indexHandle = Proxy.git_merge_commits(repo.Handle, oneHandle, twoHandle, mergeOptions))
637+
using (var indexHandle = Proxy.git_merge_commits(repo.Handle, oneHandle, twoHandle, mergeOptions, out earlyStop))
619638
{
620639
MergeTreeResult mergeResult;
621640

641+
// Stopped due to FailOnConflict so there's no index or conflict list
642+
if (earlyStop)
643+
{
644+
return new MergeTreeResult(new Conflict[] { });
645+
}
646+
622647
if (Proxy.git_index_has_conflicts(indexHandle))
623648
{
624649
List<Conflict> conflicts = new List<Conflict>();

LibGit2Sharp/Repository.cs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,8 +1329,8 @@ public RevertResult Revert(Commit commit, Signature reverter, RevertOptions opti
13291329
{
13301330
Version = 1,
13311331
MergeFileFavorFlags = options.MergeFileFavor,
1332-
MergeTreeFlags = options.FindRenames ? GitMergeTreeFlags.GIT_MERGE_TREE_FIND_RENAMES :
1333-
GitMergeTreeFlags.GIT_MERGE_TREE_NORMAL,
1332+
MergeTreeFlags = options.FindRenames ? GitMergeFlag.GIT_MERGE_FIND_RENAMES :
1333+
GitMergeFlag.GIT_MERGE_NORMAL,
13341334
RenameThreshold = (uint)options.RenameThreshold,
13351335
TargetLimit = (uint)options.TargetLimit,
13361336
};
@@ -1413,8 +1413,8 @@ public CherryPickResult CherryPick(Commit commit, Signature committer, CherryPic
14131413
{
14141414
Version = 1,
14151415
MergeFileFavorFlags = options.MergeFileFavor,
1416-
MergeTreeFlags = options.FindRenames ? GitMergeTreeFlags.GIT_MERGE_TREE_FIND_RENAMES :
1417-
GitMergeTreeFlags.GIT_MERGE_TREE_NORMAL,
1416+
MergeTreeFlags = options.FindRenames ? GitMergeFlag.GIT_MERGE_FIND_RENAMES :
1417+
GitMergeFlag.GIT_MERGE_NORMAL,
14181418
RenameThreshold = (uint)options.RenameThreshold,
14191419
TargetLimit = (uint)options.TargetLimit,
14201420
};
@@ -1553,21 +1553,39 @@ private MergeResult Merge(GitAnnotatedCommitHandle[] annotatedCommits, Signature
15531553
private MergeResult NormalMerge(GitAnnotatedCommitHandle[] annotatedCommits, Signature merger, MergeOptions options)
15541554
{
15551555
MergeResult mergeResult;
1556+
GitMergeFlag treeFlags = options.FindRenames ? GitMergeFlag.GIT_MERGE_FIND_RENAMES
1557+
: GitMergeFlag.GIT_MERGE_NORMAL;
1558+
1559+
if (options.FailOnConflict)
1560+
{
1561+
treeFlags |= GitMergeFlag.GIT_MERGE_FAIL_ON_CONFLICT;
1562+
}
1563+
1564+
if (options.SkipReuc)
1565+
{
1566+
treeFlags |= GitMergeFlag.GIT_MERGE_SKIP_REUC;
1567+
}
1568+
15561569
var mergeOptions = new GitMergeOpts
15571570
{
15581571
Version = 1,
15591572
MergeFileFavorFlags = options.MergeFileFavor,
1560-
MergeTreeFlags = options.FindRenames ? GitMergeTreeFlags.GIT_MERGE_TREE_FIND_RENAMES
1561-
: GitMergeTreeFlags.GIT_MERGE_TREE_NORMAL,
1573+
MergeTreeFlags = treeFlags,
15621574
RenameThreshold = (uint)options.RenameThreshold,
15631575
TargetLimit = (uint)options.TargetLimit,
15641576
};
15651577

1578+
bool earlyStop;
15661579
using (GitCheckoutOptsWrapper checkoutOptionsWrapper = new GitCheckoutOptsWrapper(options))
15671580
{
15681581
var checkoutOpts = checkoutOptionsWrapper.Options;
15691582

1570-
Proxy.git_merge(Handle, annotatedCommits, mergeOptions, checkoutOpts);
1583+
Proxy.git_merge(Handle, annotatedCommits, mergeOptions, checkoutOpts, out earlyStop);
1584+
}
1585+
1586+
if (earlyStop)
1587+
{
1588+
return new MergeResult(MergeStatus.Conflicts);
15711589
}
15721590

15731591
if (Index.IsFullyMerged)

0 commit comments

Comments
 (0)
0