Skip to content

Commit 2e417b7

Browse files
Merge pull request #41 from AshleighAdams/deprecate-inspector-getparent
Deprecating old API in preparation for new API in 2.0.0
2 parents befacd4 + e32433c commit 2e417b7

11 files changed

+142
-64
lines changed

Directory.Build.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
<MinVerTagPrefix>v</MinVerTagPrefix>
4747
<!-- delete/set to patch the line below once almost out of v0.x.y (preferably once on a beta or rc). -->
4848
<MinVerAutoIncrement>patch</MinVerAutoIncrement>
49-
<MinVerMinimumMajorMinor>1.1</MinVerMinimumMajorMinor>
49+
<MinVerMinimumMajorMinor>1.2</MinVerMinimumMajorMinor>
5050
</PropertyGroup>
5151
<ItemGroup>
5252
<PackageReference Include="MinVer" Version="2.5.0">

src/Verlite.Core/GitRepoInspector.cs

+49-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Diagnostics;
4+
using System.Diagnostics.CodeAnalysis;
5+
using System.Linq;
46
using System.Text.RegularExpressions;
57
using System.Threading.Tasks;
68

@@ -20,23 +22,43 @@ public class GitMissingOrNotGitRepoException : RepoInspectionException
2022
/// <seealso cref="IRepoInspector"/>
2123
public sealed class GitRepoInspector : IRepoInspector
2224
{
25+
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
26+
// TODO: Remove all of these enumerated permutations of the old optional args in 2.0.0
27+
[ExcludeFromCodeCoverage]
28+
[Obsolete("Use FromPath(path, remote, log, commandRunner)", error: false)]
29+
public static Task<GitRepoInspector> FromPath(string path, ILogger? log, ICommandRunner? commandRunner)
30+
=> FromPath(path, "origin", log, commandRunner ?? new SystemCommandRunner());
31+
[ExcludeFromCodeCoverage]
32+
[Obsolete("Use FromPath(path, remote, log, commandRunner)", error: false)]
33+
public static Task<GitRepoInspector> FromPath(string path, ILogger? log)
34+
=> FromPath(path, "origin", log, new SystemCommandRunner());
35+
[ExcludeFromCodeCoverage]
36+
[Obsolete("Use FromPath(path, remote, log, commandRunner)", error: false)]
37+
public static Task<GitRepoInspector> FromPath(string path, ICommandRunner? commandRunner)
38+
=> FromPath(path, "origin", null, commandRunner?? new SystemCommandRunner());
39+
[ExcludeFromCodeCoverage]
40+
[Obsolete("Use FromPath(path, remote, log, commandRunner)", error: false)]
41+
public static Task<GitRepoInspector> FromPath(string path)
42+
=> FromPath(path, "origin", null, new SystemCommandRunner());
43+
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
44+
2345
/// <summary>
2446
/// Creates an inspector from the specified path.
2547
/// </summary>
2648
/// <param name="path">The path of the Git repository.</param>
49+
/// <param name="remote">The remote endpoint.</param>
2750
/// <param name="log">A logger for diagnostics.</param>
28-
/// <param name="commandRunner">A command runner to use. Defaults to <see cref="SystemCommandRunner"/> if null is given.</param>
51+
/// <param name="commandRunner">A command runner to use.</param>
2952
/// <exception cref="GitMissingOrNotGitRepoException">Thrown if the path is not a Git repository.</exception>
3053
/// <returns>A task containing the Git repo inspector.</returns>
31-
public static async Task<GitRepoInspector> FromPath(string path, ILogger? log = null, ICommandRunner? commandRunner = null)
54+
public static async Task<GitRepoInspector> FromPath(string path, string remote, ILogger? log, ICommandRunner commandRunner)
3255
{
33-
commandRunner ??= new SystemCommandRunner();
34-
3556
try
3657
{
3758
var (root, _) = await commandRunner.Run(path, "git", new string[] { "rev-parse", "--show-toplevel" });
3859
var ret = new GitRepoInspector(
3960
root,
61+
remote,
4062
log,
4163
commandRunner);
4264
await ret.CacheParents();
@@ -60,10 +82,12 @@ public static async Task<GitRepoInspector> FromPath(string path, ILogger? log =
6082
public string Root { get; }
6183
private Dictionary<Commit, Commit> CachedParents { get; } = new();
6284
private (int depth, bool shallow, Commit deepest)? FetchDepth { get; set; }
85+
public string Remote { get; }
6386

64-
private GitRepoInspector(string root, ILogger? log, ICommandRunner commandRunner)
87+
private GitRepoInspector(string root, string remote, ILogger? log, ICommandRunner commandRunner)
6588
{
6689
Root = root;
90+
Remote = remote;
6791
Log = log;
6892
CommandRunner = commandRunner;
6993
}
@@ -169,11 +193,9 @@ private async Task Deepen()
169193
try
170194
{
171195
if (DeepenFromCommitSupported)
172-
_ = await Git("fetch", "origin", FetchDepth.Value.deepest.Id, $"--depth={deltaDepth}");
196+
_ = await Git("fetch", Remote, FetchDepth.Value.deepest.Id, $"--depth={deltaDepth}");
173197
else
174-
_ = await Git("fetch", $"--depth={newDepth}");
175-
176-
await CacheParents();
198+
_ = await Git("fetch", Remote, $"--depth={newDepth}");
177199
}
178200
catch (CommandException ex)
179201
when (
@@ -226,9 +248,18 @@ private async Task CacheParents()
226248

227249
/// <inheritdoc/>
228250
public async Task<Commit?> GetParent(Commit commit)
251+
{
252+
var parents = await GetParents(commit);
253+
return parents
254+
.Select(p => (Commit?)p)
255+
.FirstOrDefault();
256+
}
257+
258+
/// <inheritdoc/>
259+
public async Task<IReadOnlyList<Commit>> GetParents(Commit commit)
229260
{
230261
if (CachedParents.TryGetValue(commit, out Commit ret))
231-
return ret;
262+
return new[] { ret };
232263

233264
var contents = await GetCommitObject(commit);
234265
var parent = ParseCommitObjectParent(contents);
@@ -237,7 +268,7 @@ private async Task CacheParents()
237268
CachedParents[commit] = parent.Value;
238269

239270
Log?.Verbatim($"GetParent() -> {parent}");
240-
return parent;
271+
return parent is not null ? new Commit[] { parent.Value } : Array.Empty<Commit>();
241272
}
242273

243274
private static readonly Regex RefsTagRegex = new Regex(
@@ -265,7 +296,7 @@ public async Task<TagContainer> GetTags(QueryTarget queryTarget)
265296
try
266297
{
267298
Log?.Verbatim($"GetTags(): Reading remote tags.");
268-
var (response, _) = await Git("ls-remote", "--tags");
299+
var (response, _) = await Git("ls-remote", "--tags", Remote, "*");
269300

270301
foreach (Tag tag in MatchTags(response))
271302
{
@@ -308,5 +339,11 @@ public async Task FetchTag(Tag tag, string remote)
308339
else
309340
await Git("fetch", remote, $"refs/tags/{tag.Name}:refs/tags/{tag.Name}");
310341
}
342+
343+
/// <inheritdoc/>
344+
public Task FetchTag(Tag tag)
345+
{
346+
return FetchTag(tag, Remote);
347+
}
311348
}
312349
}

src/Verlite.Core/IRepoInspector.cs

+14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Diagnostics.CodeAnalysis;
34
using System.Runtime.Serialization;
45
using System.Threading.Tasks;
@@ -74,8 +75,15 @@ public interface IRepoInspector
7475
/// </summary>
7576
/// <param name="commit">The commit.</param>
7677
/// <returns>A task containing the primary parent commit, or <c>null</c> if it has none.</returns>
78+
[Obsolete("Deprecated in favor of GetParents(). See GitHub issue #40.", error: false)]
7779
Task<Commit?> GetParent(Commit commit);
7880
/// <summary>
81+
/// Gets all parents of the specified commit.
82+
/// </summary>
83+
/// <param name="commit">The commit.</param>
84+
/// <returns>A task containing a list of parent commits.</returns>
85+
Task<IReadOnlyList<Commit>> GetParents(Commit commit);
86+
/// <summary>
7987
/// Query tags from a desired target.
8088
/// </summary>
8189
/// <param name="queryTarget">The target to query.</param>
@@ -86,6 +94,12 @@ public interface IRepoInspector
8694
/// </summary>
8795
/// <param name="tag">The tag to fetch.</param>
8896
/// <param name="remote">Which remote to fetch the tag from.</param>
97+
[Obsolete("Use FetchTag(tag)", error: false)]
8998
Task FetchTag(Tag tag, string remote);
99+
/// <summary>
100+
/// Fetches the specified tag from the remote.
101+
/// </summary>
102+
/// <param name="tag">The tag to fetch.</param>
103+
Task FetchTag(Tag tag);
90104
}
91105
}

src/Verlite.Core/PublicAPI.Shipped.txt

+9-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ static Verlite.Command.ParseCommandLine(string! cmdLine) -> System.Collections.G
1414
static Verlite.Command.Run(string! directory, string! command, string![]! args, System.Collections.Generic.IDictionary<string!, string!>? envVars = null) -> System.Threading.Tasks.Task<(string! stdout, string! stderr)>!
1515
static Verlite.Commit.operator !=(Verlite.Commit left, Verlite.Commit right) -> bool
1616
static Verlite.Commit.operator ==(Verlite.Commit left, Verlite.Commit right) -> bool
17-
static Verlite.GitRepoInspector.FromPath(string! path, Verlite.ILogger? log = null, Verlite.ICommandRunner? commandRunner = null) -> System.Threading.Tasks.Task<Verlite.GitRepoInspector!>!
17+
static Verlite.GitRepoInspector.FromPath(string! path) -> System.Threading.Tasks.Task<Verlite.GitRepoInspector!>!
18+
static Verlite.GitRepoInspector.FromPath(string! path, string! remote, Verlite.ILogger? log, Verlite.ICommandRunner! commandRunner) -> System.Threading.Tasks.Task<Verlite.GitRepoInspector!>!
19+
static Verlite.GitRepoInspector.FromPath(string! path, Verlite.ICommandRunner? commandRunner) -> System.Threading.Tasks.Task<Verlite.GitRepoInspector!>!
20+
static Verlite.GitRepoInspector.FromPath(string! path, Verlite.ILogger? log) -> System.Threading.Tasks.Task<Verlite.GitRepoInspector!>!
21+
static Verlite.GitRepoInspector.FromPath(string! path, Verlite.ILogger? log, Verlite.ICommandRunner? commandRunner) -> System.Threading.Tasks.Task<Verlite.GitRepoInspector!>!
1822
static Verlite.HeightCalculator.FromRepository(Verlite.IRepoInspector! repo, string! tagPrefix, bool queryRemoteTags, Verlite.ILogger? log = null, Verlite.ITagFilter? tagFilter = null) -> System.Threading.Tasks.Task<(int height, Verlite.TaggedVersion?)>!
1923
static Verlite.SemVer.ComparePrerelease(string! left, string! right) -> int
2024
static Verlite.SemVer.IsValidIdentifierCharacter(char input) -> bool
@@ -57,9 +61,11 @@ Verlite.GitMissingOrNotGitRepoException.GitMissingOrNotGitRepoException() -> voi
5761
Verlite.GitRepoInspector
5862
Verlite.GitRepoInspector.CanDeepen.get -> bool
5963
Verlite.GitRepoInspector.CanDeepen.set -> void
64+
Verlite.GitRepoInspector.FetchTag(Verlite.Tag tag) -> System.Threading.Tasks.Task!
6065
Verlite.GitRepoInspector.FetchTag(Verlite.Tag tag, string! remote) -> System.Threading.Tasks.Task!
6166
Verlite.GitRepoInspector.GetHead() -> System.Threading.Tasks.Task<Verlite.Commit?>!
6267
Verlite.GitRepoInspector.GetParent(Verlite.Commit commit) -> System.Threading.Tasks.Task<Verlite.Commit?>!
68+
Verlite.GitRepoInspector.GetParents(Verlite.Commit commit) -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Verlite.Commit>!>!
6369
Verlite.GitRepoInspector.GetTags(Verlite.QueryTarget queryTarget) -> System.Threading.Tasks.Task<Verlite.TagContainer!>!
6470
Verlite.GitRepoInspector.Root.get -> string!
6571
Verlite.HeightCalculator
@@ -70,9 +76,11 @@ Verlite.ILogger.Normal(string! message) -> void
7076
Verlite.ILogger.Verbatim(string! message) -> void
7177
Verlite.ILogger.Verbose(string! message) -> void
7278
Verlite.IRepoInspector
79+
Verlite.IRepoInspector.FetchTag(Verlite.Tag tag) -> System.Threading.Tasks.Task!
7380
Verlite.IRepoInspector.FetchTag(Verlite.Tag tag, string! remote) -> System.Threading.Tasks.Task!
7481
Verlite.IRepoInspector.GetHead() -> System.Threading.Tasks.Task<Verlite.Commit?>!
7582
Verlite.IRepoInspector.GetParent(Verlite.Commit commit) -> System.Threading.Tasks.Task<Verlite.Commit?>!
83+
Verlite.IRepoInspector.GetParents(Verlite.Commit commit) -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Verlite.Commit>!>!
7684
Verlite.IRepoInspector.GetTags(Verlite.QueryTarget queryTarget) -> System.Threading.Tasks.Task<Verlite.TagContainer!>!
7785
Verlite.ITagFilter
7886
Verlite.ITagFilter.PassesFilter(Verlite.TaggedVersion! taggedVersion) -> System.Threading.Tasks.Task<bool>!

src/Verlite.Core/mark-shipped.sh

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ cd "$(dirname "$0")"
55

66
shipped="$(cat PublicAPI.Shipped.txt PublicAPI.Unshipped.txt \
77
| sort --ignore-case \
8+
| awk '{$1=$1};1' \
89
| uniq)"
910

1011
echo "$shipped" > PublicAPI.Shipped.txt

tests/UnitTests/GitRepoInspectorTests.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ public async Task FetchTagFetchesRemoteTagOnly()
244244
firstTags.Should().ContainSingle();
245245
var firstTag = firstTags[0];
246246

247-
await repo.FetchTag(firstTag, "origin");
247+
await repo.FetchTag(firstTag);
248248

249249
var localTags = await repo.GetTags(QueryTarget.Local);
250250
localTags.Should().Contain(new Tag[]
@@ -347,7 +347,7 @@ public async Task FetchingTagInShallowCloneDoesNotDeepenBeyondTag()
347347
.Where(tag => tag.Name == "tag-two")
348348
.First();
349349

350-
await repo.FetchTag(desiredTag, "origin");
350+
await repo.FetchTag(desiredTag);
351351

352352
var desiredParent = await repo.GetParent(desiredTag.PointsTo);
353353
desiredParent.Should().Be(deeperTag.PointsTo);
@@ -384,7 +384,7 @@ public async Task FetchingTagInDeepCloneDoesNotMakeShallow()
384384
.Where(tag => tag.Name == "tag-two")
385385
.First();
386386

387-
await repo.FetchTag(desiredTag, "origin");
387+
await repo.FetchTag(desiredTag);
388388
repo = null; // repo modified invalidating internal cache, so remake inspector
389389
repo = await clone.MakeInspector();
390390

@@ -422,7 +422,7 @@ public async Task ShallowGitFetchFromCommitCanFallBack()
422422
var filteredHistory = mockCommandRunner.CommandHistory
423423
.Where(cmd => cmd.Contains("git fetch", StringComparison.Ordinal))
424424
.Select(cmd =>
425-
cmd.Contains("origin", StringComparison.Ordinal) ?
425+
!cmd.Contains("origin --depth", StringComparison.Ordinal) ?
426426
"normal fetch" :
427427
"legacy fetch");
428428

tests/UnitTests/HeightCalculationTests.cs

+16-16
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ public async Task HeadOnTagReturnsIt()
1818
{
1919
var repo = new MockRepoInspector(new MockRepoCommit[]
2020
{
21-
new("commit_a", "v1.0.0"),
22-
new("commit_b", "v1.0.0-alpha.1"),
21+
new("commit_a") { Tags = new[]{ "v1.0.0" } },
22+
new("commit_b") { Tags = new[]{ "v1.0.0-alpha.1" } },
2323
new("commit_c"),
2424
});
2525

@@ -80,7 +80,7 @@ public async Task NoSemVerTagReturnsNoTag()
8080
{
8181
var repo = new MockRepoInspector(new MockRepoCommit[]
8282
{
83-
new("commit_a", "v1.0.0.0"),
83+
new("commit_a") { Tags = new[]{ "v1.0.0.0" } },
8484
new("commit_b"),
8585
new("commit_c"),
8686
});
@@ -97,9 +97,9 @@ public async Task MatchingPrefixNonVersionTagsIgnored()
9797
{
9898
var repo = new MockRepoInspector(new MockRepoCommit[]
9999
{
100-
new("commit_a", "vast-tag"),
101-
new("commit_b", "very-nice-tag"),
102-
new("commit_c", "v"),
100+
new("commit_a") { Tags = new[]{ "vast-tag" } },
101+
new("commit_b") { Tags = new[]{ "very-nice-tag" } },
102+
new("commit_c") { Tags = new[]{ "v" } },
103103
});
104104

105105
var (height, tag) = await HeightCalculator.FromRepository(repo, "v", true);
@@ -113,7 +113,7 @@ public async Task MultipleTagsReturnsHighestTag()
113113
{
114114
var repo = new MockRepoInspector(new MockRepoCommit[]
115115
{
116-
new("commit_a", "v1.0.0-alpha.1", "v1.0.0", "v1.0.0-rc.1"),
116+
new("commit_a") { Tags = new[]{ "v1.0.0-alpha.1", "v1.0.0", "v1.0.0-rc.1" } },
117117
new("commit_b"),
118118
new("commit_c"),
119119
});
@@ -135,7 +135,7 @@ public async Task MultipleTagsReturnsHighestTagWhenAutoVersioning()
135135
var repo = new MockRepoInspector(new MockRepoCommit[]
136136
{
137137
new("commit_a"),
138-
new("commit_b", "v1.0.0-alpha.1", "v1.0.0-rc.2", "v1.0.0-rc.10"),
138+
new("commit_b") { Tags = new[]{ "v1.0.0-alpha.1", "v1.0.0-rc.2", "v1.0.0-rc.10" } },
139139
new("commit_c"),
140140
});
141141

@@ -158,7 +158,7 @@ public async Task QueryRemoteTagsDoesNotFetchTag()
158158
{
159159
new("commit_a"),
160160
new("commit_b"),
161-
new("commit_c", "v1.0.0-alpha.1"),
161+
new("commit_c") { Tags = new[]{ "v1.0.0-alpha.1" } },
162162
});
163163

164164
(_, _) = await HeightCalculator.FromRepository(repo, "v", true);
@@ -176,9 +176,9 @@ public async Task FindsCommitsWithPrefixesOnly(string prefix, int resultHeight,
176176
{
177177
var repo = new MockRepoInspector(new MockRepoCommit[]
178178
{
179-
new("commit_a", "abc/version/2.0.0"),
180-
new("commit_b", "version/3.0.0"),
181-
new("commit_c", "4.0.0"),
179+
new("commit_a") { Tags = new[]{ "abc/version/2.0.0" } },
180+
new("commit_b") { Tags = new[]{ "version/3.0.0" } },
181+
new("commit_c") { Tags = new[]{ "4.0.0" } },
182182
new("commit_d"),
183183
});
184184

@@ -209,8 +209,8 @@ public async Task FilterCanIgnoreTags()
209209
{
210210
var repo = new MockRepoInspector(new MockRepoCommit[]
211211
{
212-
new("commit_a", "v1.0.0"),
213-
new("commit_b", "v1.0.0-alpha.1"),
212+
new("commit_a") { Tags = new[]{ "v1.0.0" } },
213+
new("commit_b") { Tags = new[]{ "v1.0.0-alpha.1" } },
214214
new("commit_c"),
215215
});
216216

@@ -232,8 +232,8 @@ public async Task FilterDoesntIgnoreOtherTagsOnSameCommit()
232232
{
233233
var repo = new MockRepoInspector(new MockRepoCommit[]
234234
{
235-
new("commit_a", "v1.0.0", "v1.0.1"),
236-
new("commit_b", "v1.0.0-alpha.1"),
235+
new("commit_a") { Tags = new[]{ "v1.0.0", "v1.0.1" } },
236+
new("commit_b") { Tags = new[]{ "v1.0.0-alpha.1" } },
237237
new("commit_c"),
238238
});
239239

tests/UnitTests/Mocks/MockCommandRunnerWithOldRemoteGitVersion.cs

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.Linq;
34
using System.Threading.Tasks;
@@ -30,12 +31,15 @@ public MockCommandRunnerWithOldRemoteGitVersion(ICommandRunner baseRunner)
3031
else
3132
commandHistory.Add($"{command} {string.Join(' ', args)}");
3233

33-
return (command, firstArg, args) switch
34+
if (firstArg == "fetch")
3435
{
35-
("git", "fetch", _) when args.Contains("origin") =>
36-
throw new CommandException(128, "", "error: Server does not allow request for unadvertised object a1b2c3"),
37-
_ => BaseRunner.Run(directory, command, args, envVars),
38-
};
36+
if (args.Length is not 3 and not 4)
37+
throw new NotSupportedException();
38+
if (args.Length == 4 && !args[2].StartsWith("--depth", StringComparison.Ordinal))
39+
throw new CommandException(128, "", "error: Server does not allow request for unadvertised object a1b2c3");
40+
}
41+
42+
return BaseRunner.Run(directory, command, args, envVars);
3943
}
4044
}
4145
}

0 commit comments

Comments
 (0)