Skip to content

Commit 0168615

Browse files
committed
Fix nbgv set-version to write to the best version.json file in scope
This required reworking how version.json files are discovered to report back on where certain version.json files were. In particular, we had these requirements that were not previously being met: * We have to know where the nearest version.json file is _that specifies a `version` property_, since that's the file that `nbgv set-version` will be writing to. * We have to get a deserialized `VersionOptions` object that has _not_ been merged with its parent when `inherit: true` is set. This is so that when we rewrite the file, we only serialize the same properties that came from that file rather than 'flattening' the inheritance hierarchy by including properties brought in from the parent. Rather than special case these particular requirements, I updated the version.json search algorithm to allow the caller to specify different combinations of requirements and get locations of potentially multiple files. Fixes #1257
1 parent 1d6c087 commit 0168615

File tree

12 files changed

+232
-85
lines changed

12 files changed

+232
-85
lines changed

src/NerdBank.GitVersioning/DisabledGit/DisabledGitVersionFile.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ public DisabledGitVersionFile(GitContext context)
1414

1515
protected new DisabledGitContext Context => (DisabledGitContext)base.Context;
1616

17-
protected override VersionOptions? GetVersionCore(out string? actualDirectory)
17+
protected override VersionOptions? GetVersionCore(VersionFileRequirements requirements, out VersionFileLocations locations)
1818
{
19-
actualDirectory = null;
19+
locations = default;
2020
return null;
2121
}
2222
}

src/NerdBank.GitVersioning/LibGit2/LibGit2GitExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ internal GitWalkTracker(LibGit2Context context)
594594
{
595595
try
596596
{
597-
options = ((LibGit2VersionFile)this.context.VersionFile).GetVersion(commit, this.context.RepoRelativeProjectDirectory, this.blobVersionCache, out string? actualDirectory);
597+
options = ((LibGit2VersionFile)this.context.VersionFile).GetVersion(commit, this.context.RepoRelativeProjectDirectory, this.blobVersionCache, VersionFileRequirements.Default, out _);
598598
}
599599
catch (Exception ex)
600600
{

src/NerdBank.GitVersioning/LibGit2/LibGit2VersionFile.cs

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,14 @@ internal LibGit2VersionFile(LibGit2Context context)
3232
/// <param name="commit">The commit to read from.</param>
3333
/// <param name="repoRelativeProjectDirectory">The directory to consider when searching for the version.txt file.</param>
3434
/// <param name="blobVersionCache">An optional blob cache for storing the raw parse results of a version.txt or version.json file (before any inherit merge operations are applied).</param>
35-
/// <param name="actualDirectory">Receives the full path to the directory in which the version file was found.</param>
35+
/// <param name="requirements"><inheritdoc cref="GetVersionCore(VersionFileRequirements, out VersionFileLocations)" path="/param[@name='requirements']" /></param>
36+
/// <param name="locations"><inheritdoc cref="GetVersionCore(VersionFileRequirements, out VersionFileLocations)" path="/param[@name='locations']" /></param>
3637
/// <returns>The version information read from the file.</returns>
37-
internal VersionOptions? GetVersion(Commit commit, string repoRelativeProjectDirectory, Dictionary<ObjectId, VersionOptions?>? blobVersionCache, out string? actualDirectory)
38+
internal VersionOptions? GetVersion(Commit commit, string repoRelativeProjectDirectory, Dictionary<ObjectId, VersionOptions?>? blobVersionCache, VersionFileRequirements requirements, out VersionFileLocations locations)
3839
{
40+
repoRelativeProjectDirectory = TrimTrailingPathSeparator(repoRelativeProjectDirectory);
41+
locations = default;
42+
3943
string? searchDirectory = repoRelativeProjectDirectory ?? string.Empty;
4044
while (searchDirectory is object)
4145
{
@@ -58,8 +62,8 @@ internal LibGit2VersionFile(LibGit2Context context)
5862
if (result is object)
5963
{
6064
IBelongToARepository commitAsRepoMember = commit;
61-
actualDirectory = Path.Combine(commitAsRepoMember.Repository.Info.WorkingDirectory, searchDirectory);
62-
return result;
65+
this.ApplyLocations(result, Path.Combine(commitAsRepoMember.Repository.Info.WorkingDirectory, searchDirectory), ref locations);
66+
return VersionOptionsSatisfyRequirements(result, requirements) ? result : null;
6367
}
6468
}
6569

@@ -95,12 +99,19 @@ internal LibGit2VersionFile(LibGit2Context context)
9599
}
96100
}
97101

98-
if (result?.Inherit ?? false)
102+
this.ApplyLocations(result, Path.Combine(this.Context.WorkingTreePath, searchDirectory), ref locations);
103+
if (VersionOptionsSatisfyRequirements(result, requirements))
104+
{
105+
return result;
106+
}
107+
108+
if (result?.Inherit is true)
99109
{
100110
if (parentDirectory is object)
101111
{
102-
result = this.GetVersion(commit, parentDirectory, blobVersionCache, out actualDirectory);
103-
if (result is object)
112+
result = this.GetVersion(commit, parentDirectory, blobVersionCache, requirements, out VersionFileLocations parentLocations);
113+
this.MergeLocations(ref locations, parentLocations);
114+
if (!requirements.HasFlag(VersionFileRequirements.NonMergedResult) && result is not null)
104115
{
105116
if (versionJsonContent is null)
106117
{
@@ -115,27 +126,30 @@ internal LibGit2VersionFile(LibGit2Context context)
115126
}
116127

117128
JsonConvert.PopulateObject(versionJsonContent, result, VersionOptions.GetJsonSettings(repoRelativeBaseDirectory: searchDirectory));
118-
return result;
129+
result.Inherit = false;
119130
}
120131
}
132+
else
133+
{
134+
throw new InvalidOperationException($"\"{candidatePath}\" inherits from a parent directory version.json file but none exists.");
135+
}
121136

122-
throw new InvalidOperationException($"\"{candidatePath}\" inherits from a parent directory version.json file but none exists.");
137+
return VersionOptionsSatisfyRequirements(result, requirements) ? result : null;
123138
}
124139
else if (result is object)
125140
{
126141
IBelongToARepository commitAsRepoMember = commit;
127-
actualDirectory = Path.Combine(commitAsRepoMember.Repository.Info.WorkingDirectory, searchDirectory);
128-
return result;
142+
return VersionOptionsSatisfyRequirements(result, requirements) ? result : null;
129143
}
130144
}
131145

132146
searchDirectory = parentDirectory;
133147
}
134148

135-
actualDirectory = null;
149+
locations = default;
136150
return null;
137151
}
138152

139153
/// <inheritdoc/>
140-
protected override VersionOptions? GetVersionCore(out string? actualDirectory) => this.GetVersion(this.Context.Commit!, this.Context.RepoRelativeProjectDirectory, null, out actualDirectory);
154+
protected override VersionOptions? GetVersionCore(VersionFileRequirements requirements, out VersionFileLocations locations) => this.GetVersion(this.Context.Commit!, this.Context.RepoRelativeProjectDirectory, null, requirements, out locations);
141155
}

src/NerdBank.GitVersioning/Managed/GitExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ internal GitWalkTracker(ManagedGitContext context)
329329
{
330330
try
331331
{
332-
options = ((ManagedVersionFile)this.context.VersionFile).GetVersion(commit, this.context.RepoRelativeProjectDirectory, this.blobVersionCache, out string? actualDirectory);
332+
options = ((ManagedVersionFile)this.context.VersionFile).GetVersion(commit, this.context.RepoRelativeProjectDirectory, this.blobVersionCache, VersionFileRequirements.Default, out _);
333333
}
334334
catch (Exception ex)
335335
{

src/NerdBank.GitVersioning/Managed/ManagedVersionFile.cs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,22 @@ public ManagedVersionFile(GitContext context)
3636

3737
protected new ManagedGitContext Context => (ManagedGitContext)base.Context;
3838

39+
protected override bool VersionSearchRootToBranch => true;
40+
3941
/// <summary>
4042
/// Reads the version.json file and returns the <see cref="VersionOptions"/> deserialized from it.
4143
/// </summary>
4244
/// <param name="commit">The commit to read from.</param>
4345
/// <param name="repoRelativeProjectDirectory">The directory to consider when searching for the version.txt file.</param>
4446
/// <param name="blobVersionCache">An optional blob cache for storing the raw parse results of a version.txt or version.json file (before any inherit merge operations are applied).</param>
45-
/// <param name="actualDirectory">Receives the full path to the directory in which the version file was found.</param>
47+
/// <param name="requirements"><inheritdoc cref="GetVersionCore(VersionFileRequirements, out VersionFileLocations)" path="/param[@name='requirements']" /></param>
48+
/// <param name="locations"><inheritdoc cref="GetVersionCore(VersionFileRequirements, out VersionFileLocations)" path="/param[@name='locations']" /></param>
4649
/// <returns>The version information read from the file.</returns>
47-
internal VersionOptions? GetVersion(GitCommit commit, string repoRelativeProjectDirectory, Dictionary<GitObjectId, VersionOptions?>? blobVersionCache, out string? actualDirectory)
50+
internal VersionOptions? GetVersion(GitCommit commit, string repoRelativeProjectDirectory, Dictionary<GitObjectId, VersionOptions?>? blobVersionCache, VersionFileRequirements requirements, out VersionFileLocations locations)
4851
{
52+
repoRelativeProjectDirectory = TrimTrailingPathSeparator(repoRelativeProjectDirectory);
53+
locations = default;
54+
4955
var directories = new Stack<string>();
5056

5157
string? currentDirectory = repoRelativeProjectDirectory;
@@ -61,8 +67,6 @@ public ManagedVersionFile(GitContext context)
6167
string? parentDirectory = null;
6268

6369
VersionOptions? finalResult = null;
64-
actualDirectory = null;
65-
6670
while (tree != GitObjectId.Empty)
6771
{
6872
GitObjectId versionTxtBlob = this.Context.Repository.GetTreeEntry(tree, TxtFileNameBytes);
@@ -81,7 +85,7 @@ public ManagedVersionFile(GitContext context)
8185
if (result is object)
8286
{
8387
finalResult = result;
84-
actualDirectory = Path.Combine(this.Context.WorkingTreePath, searchDirectory);
88+
this.ApplyLocations(result, Path.Combine(this.Context.WorkingTreePath, searchDirectory), ref locations);
8589
}
8690
}
8791

@@ -116,12 +120,13 @@ public ManagedVersionFile(GitContext context)
116120
}
117121
}
118122

119-
if (result?.Inherit ?? false)
123+
if (result?.Inherit is true)
120124
{
121125
if (parentDirectory is object)
122126
{
123-
result = this.GetVersion(commit, parentDirectory, blobVersionCache, out string? resultingDirectory);
124-
if (result is object)
127+
result = this.GetVersion(commit, parentDirectory, blobVersionCache, requirements, out VersionFileLocations parentLocations);
128+
this.MergeLocations(ref locations, parentLocations);
129+
if (!requirements.HasFlag(VersionFileRequirements.NonMergedResult) && result is not null)
125130
{
126131
if (versionJsonContent is null)
127132
{
@@ -136,7 +141,7 @@ public ManagedVersionFile(GitContext context)
136141
}
137142

138143
JsonConvert.PopulateObject(versionJsonContent, result, VersionOptions.GetJsonSettings(repoRelativeBaseDirectory: searchDirectory));
139-
finalResult = result;
144+
result.Inherit = false;
140145
}
141146
else
142147
{
@@ -153,8 +158,8 @@ public ManagedVersionFile(GitContext context)
153158

154159
if (result is object)
155160
{
156-
actualDirectory = Path.Combine(this.Context.WorkingTreePath, searchDirectory);
157161
finalResult = result;
162+
this.ApplyLocations(result, Path.Combine(this.Context.WorkingTreePath, searchDirectory), ref locations);
158163
}
159164
}
160165

@@ -174,9 +179,10 @@ public ManagedVersionFile(GitContext context)
174179
}
175180
}
176181

177-
return finalResult;
182+
return VersionOptionsSatisfyRequirements(finalResult, requirements) ? finalResult : null;
178183
}
179184

180185
/// <inheritdoc/>
181-
protected override VersionOptions? GetVersionCore(out string? actualDirectory) => this.GetVersion(this.Context.Commit!.Value, this.Context.RepoRelativeProjectDirectory, null, out actualDirectory);
186+
protected override VersionOptions? GetVersionCore(VersionFileRequirements requirements, out VersionFileLocations locations)
187+
=> this.GetVersion(this.Context.Commit!.Value, this.Context.RepoRelativeProjectDirectory, null, requirements, out locations);
182188
}

src/NerdBank.GitVersioning/NoGit/NoGitVersionFile.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ public NoGitVersionFile(GitContext context)
1313
}
1414

1515
/// <inheritdoc/>
16-
protected override VersionOptions GetVersionCore(out string actualDirectory) => throw Assumes.NotReachable();
16+
protected override VersionOptions GetVersionCore(VersionFileRequirements requirements, out VersionFileLocations locations) => throw Assumes.NotReachable();
1717
}

0 commit comments

Comments
 (0)