GitVersion icon indicating copy to clipboard operation
GitVersion copied to clipboard

[Bug] GitVersion.MsBuild restore fails with packages.config

Open candritzky opened this issue 4 years ago • 4 comments

Describe the bug When using GitVersion.MsBuild with a legacy .csproj that uses packages.config to reference NuGet packages and then running msbuild /t:restore after a clean checkout (git clean -fxd), then the restore operation fails because it cannot write GitVersionInformation.g.cs to the not-yet-existing $(IntermediateOutputPath) directory (e. g. "obj\Debug").

Here's the command line output showing the error message:

C:\Git\GitVersionMsBuildTest>msbuild /t:restore
Microsoft (R) Build Engine version 16.11.2+f32259642 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.

Building the projects in this solution one at a time. To enable parallel build, please add the "-m" switch.
Build started 27.12.2021 16:36:23.
Project "C:\Git\GitVersionMsBuildTest\GitVersionMsBuildTest.sln" on node 1 (Restore target(s)).
ValidateSolutionConfiguration:
  Building solution configuration "Debug|Any CPU".
_GetAllRestoreProjectPathItems:
  Determining projects to restore...
Project "C:\Git\GitVersionMsBuildTest\GitVersionMsBuildTest.sln" (1) is building "C:\Git\GitVersionMsBuildTest\OldStyleLibrary\OldStyleLibrary.csproj" (2:5) on node 1 (_GenerateProjectRestoreGraph target(s)).
RunGitVersion:
  "C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\net48/gitversion.exe" "C:\Git\GitVersionMsBuildTest\OldStyleLibrary" -output file -outputfile gitversion.json
C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\GitVersion.MsBuild.targets(110,9): error : DirectoryNotFoundException: Could not find a part of the path 'C:\Git\GitVersionMsBuildTest\OldStyleLibrary\obj\Debug\GitVersionInformation.g.cs'. [C:\Git\GitVersionMsBuildTest\OldStyleLibrary\OldStyleLibrary.csproj]
C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\GitVersion.MsBuild.targets(110,9): error :    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) [C:\Git\GitVersionMsBuildTest\OldStyleLibrary\OldStyleLibrary.csproj]
C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\GitVersion.MsBuild.targets(110,9): error :    at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, B
oolean checkHost) [C:\Git\GitVersionMsBuildTest\OldStyleLibrary\OldStyleLibrary.csproj]
C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\GitVersion.MsBuild.targets(110,9): error :    at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost) [C:\Git\GitVersionMsBuildTest\OldStyleLibrar
y\OldStyleLibrary.csproj]
C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\GitVersion.MsBuild.targets(110,9): error :    at System.IO.StreamWriter.CreateFile(String path, Boolean append, Boolean checkHost) [C:\Git\GitVersionMsBuildTest\OldStyleLibrary\OldStyleLibrary.csproj]
C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\GitVersion.MsBuild.targets(110,9): error :    at System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encoding, Int32 bufferSize, Boolean checkHost) [C:\Git\GitVersionMsBuildTest\OldStyleLibrary\OldStyleLibrary.csproj]
C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\GitVersion.MsBuild.targets(110,9): error :    at System.IO.File.InternalWriteAllText(String path, String contents, Encoding encoding, Boolean checkHost) [C:\Git\GitVersionMsBuildTest\OldStyleLibrary\OldStyleLibrary.csproj]
C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\GitVersion.MsBuild.targets(110,9): error :    at System.IO.File.WriteAllText(String path, String contents, Encoding encoding) [C:\Git\GitVersionMsBuildTest\OldStyleLibrary\OldStyleLibrary.csproj]
C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\GitVersion.MsBuild.targets(110,9): error :    at GitVersion.FileSystem.WriteAllText(String file, String fileContents) in D:\a\GitVersion\GitVersion\src\GitVersion.Core\Core\FileSystem.cs:line 22 [C:\Git\GitVersionMsBuildTest\OldStyleLibrary\OldStyleLibrary.csproj]
C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\GitVersion.MsBuild.targets(110,9): error :    at GitVersion.VersionConverters.GitVersionInfo.GitVersionInfoGenerator.Execute(VersionVariables variables, GitVersionInfoContext context) in D:\a\GitVersion\GitVersion\src\GitVersion.Core\VersionConverters\GitVersionInfo\GitVersionInfoGenerator.cs:line
44 [C:\Git\GitVersionMsBuildTest\OldStyleLibrary\OldStyleLibrary.csproj]
C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\GitVersion.MsBuild.targets(110,9): error :    at GitVersion.GitVersionOutputTool.GenerateGitVersionInformation(VersionVariables variables, FileWriteInfo fileWriteInfo) in D:\a\GitVersion\GitVersion\src\GitVersion.Core\Core\GitVersionOutputTool.cs:line 84 [C:\Git\GitVersionMsBuildTest\OldStyleLibrar
y\OldStyleLibrary.csproj]
C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\GitVersion.MsBuild.targets(110,9): error :    at GitVersion.MsBuild.GitVersionTaskExecutor.GenerateGitVersionInformation(GenerateGitVersionInformation task) in D:\a\GitVersion\GitVersion\src\GitVersion.MsBuild\GitVersionTaskExecutor.cs:line 60 [C:\Git\GitVersionMsBuildTest\OldStyleLibrary\OldStyleL
ibrary.csproj]
C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\GitVersion.MsBuild.targets(110,9): error :    at GitVersion.MsBuild.GitVersionTasks.<>c__DisplayClass2_0.<GenerateGitVersionInformation>b__0(IGitVersionTaskExecutor executor) in D:\a\GitVersion\GitVersion\src\GitVersion.MsBuild\GitVersionTasks.cs:line 17 [C:\Git\GitVersionMsBuildTest\OldStyleLibrar
y\OldStyleLibrary.csproj]
C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\GitVersion.MsBuild.targets(110,9): error :    at GitVersion.MsBuild.GitVersionTasks.ExecuteGitVersionTask[T](T task, Action`1 action) in D:\a\GitVersion\GitVersion\src\GitVersion.MsBuild\GitVersionTasks.cs:line 30 [C:\Git\GitVersionMsBuildTest\OldStyleLibrary\OldStyleLibrary.csproj]
C:\Users\...\AppData\Roaming\NuGet\packages\GitVersion.MsBuild.5.8.1\tools\GitVersion.MsBuild.targets(110,9): error :  [C:\Git\GitVersionMsBuildTest\OldStyleLibrary\OldStyleLibrary.csproj]
Done Building Project "C:\Git\GitVersionMsBuildTest\OldStyleLibrary\OldStyleLibrary.csproj" (_GenerateProjectRestoreGraph target(s)) -- FAILED.

Done Building Project "C:\Git\GitVersionMsBuildTest\GitVersionMsBuildTest.sln" (Restore target(s)) -- FAILED.


Build FAILED.

Expected Behavior

msbuild /t:restore on a clean checkout should succeed with packages.config style references in the same way as it already does with PackageReference style references.

Actual Behavior

msbuild /t:restore on a clean checkout with packages.config style references fails.

Possible Fix

The reason seems to be that the GitVersionTargetsBefore MSBuild property contains the _GenerateRestoreProjectSpec target (see GitVersion.MsBuild.props). As a result, GitVersion is executed during msbuild /t:restore before the _GenerateRestoreProjectSpec target is executed. At this time the $(IntermediateOutputPath) directory (e. g. obj\Debug) hasn't been created yet. gitversion.exe now tries to write file GitVersionInformation.g.cs to this non-existing directory.

This might be fixed by implicitly ensuring that the target directory exists before (or when) calling GitVersionOutputTool.GenerateGitVersionInformation, e. g. right before WriteAllText is called.

Alternatively this might be fixed by removing the _GenerateRestoreProjectSpec target from GitVersionTargetsBefore.

Steps to Reproduce

  1. Create a new, empty solution
  2. Add a new .NET Framework project (.csproj), e. g. a library, using the legacy .csproj format.
  3. Add a NuGet package reference to "GitVersion.MsBuild" using packages.config format.
  4. Ensure that the obj\Debug folder does not exist.
  5. Run msbuild /t:restore

Alternatively use the following minimal repro:

  1. git clone https://github.com/candritzky/GitVersionMsBuildTest.git
  2. cd GitVersionMsBuildTest
  3. msbuild /t:restore

Context

We have a legacy solution with a lot of non-trivial legacy, non-SDK-style .csproj projects. All of these projects are referencing NuGet package GitVersion.MsBuild. To make things worse we are using "paket" tooling (paket.dependencies, paket.references) to reference NuGet packages For legacy .csproj format this is similar to using packages.config (as opposed to using PackageReferences).

Now we have to migrate these .csproj files to modern SDK-style projects, step by step. This means until we're done we'll have a single solution with a mixture of legacy non-SDK-style ("franken-proj") and modern SDK-style projects. In order to restore the NuGet packages for the modern SDK-style projects we need to run msbuild /t:restore (or nuget restore or dotnet build or dotnet restore respectively) on the solution. This fails in GitVersion.MsBuild for the legacy projects for the reason described above.

Your Environment

Visual Studio 2019 targeting .NET Framework 4.7.2

  • Version Used: 5.8.1
  • Operating System and version: Windows 10 20H2 (OS Build 19042.1288)
  • Link to your project: https://github.com/candritzky/GitVersionMsBuildTest.git

candritzky avatar Dec 27 '21 16:12 candritzky

We're running into the same issue as well. Our project runs on .Net Framework 4.8.

nthornton2010 avatar Mar 16 '22 21:03 nthornton2010

This might be fixed by implicitly ensuring that the target directory exists before (or when) calling GitVersionOutputTool.GenerateGitVersionInformation, e. g. right before WriteAllText is called.

This sounds like a reasonable fix. Are you up for writing a PR with such a fix, @candritzky?

asbjornu avatar Mar 18 '22 13:03 asbjornu

@asbjornu Sorry, I can't. My own repro doesn't work anymore. When I call msbuild /t:restore it just says

Restore:
  Nothing to do. None of the projects specified contain packages to restore.

When I run NuGet restore the package is restored correctly. When I run MSBuild afterwards, the build succeeds.

I can't reproduce the issue anymore. Tried both with a .NET Framework 4.7.2 and 4.8 library project.

Maybe the tooling (now MSBuild 16.11.2+f32259642, NuGet 6.1.0, .NET SDK 6.0.201) has somehow evolved so that the issue does no longer occur (even though I'm still using GitVersion.MsBuild 5.8.1).

@nthornton2010 Have you tried using the latest Visual Studio and NuGet versions?

candritzky avatar Mar 25 '22 17:03 candritzky

@candritzky we updated both msbuild and nuget to their latest versions prior to my comment. We got around the issue by converting the offending project to use PackageReferences instead of packages.config.

nthornton2010 avatar Mar 26 '22 14:03 nthornton2010

This issue has been automatically marked as stale because it has not had recent activity. After 30 days from now, it will be closed if no further activity occurs.

github-actions[bot] avatar Apr 05 '23 11:04 github-actions[bot]