diff --git a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs
index c7fac7430c..8cac0b5a6e 100644
--- a/src/Paket.Core/PaketConfigFiles/ProjectFile.fs
+++ b/src/Paket.Core/PaketConfigFiles/ProjectFile.fs
@@ -2039,32 +2039,31 @@ type ProjectFile with
let getCompileItem (projectFile, compileNode) =
let projectFolder = projectFile.FileName |> Path.GetFullPath |> Path.GetDirectoryName
- let sourceFile =
- let file =
- match compileNode |> getAttribute "Include" with
- | Some file -> file
- | None ->
- match compileNode |> getAttribute "Update" with
- | Some file -> file
- | None -> failwithf "The Compile entry is in unknown format and doesn't contain a Update or Include attribute."
-
- file
- |> normalizePath
- |> fun relPath -> Path.Combine(projectFolder, relPath)
-
- let destPath =
- compileNode
- |> getDescendants "Link"
- |> function
- | [] -> createRelativePath (projectFolder + string Path.DirectorySeparatorChar) sourceFile
- | linkNode :: _ -> linkNode.InnerText
- |> normalizePath
- |> Path.GetDirectoryName
- {
- SourceFile = sourceFile
- DestinationPath = destPath
- BaseDir = projectFolder
- }
+ match compileNode |> getAttribute "Include" |> Option.orElseWith (fun () -> compileNode |> getAttribute "Update") with
+ | None ->
+ // Entries such as without an Include or Update attribute
+ // don't reference a source file, so they can't produce a compile item. Skip them
+ // instead of failing the whole pack/build (see GitHub issue #4222).
+ None
+ | Some file ->
+ let sourceFile =
+ file
+ |> normalizePath
+ |> fun relPath -> Path.Combine(projectFolder, relPath)
+
+ let destPath =
+ compileNode
+ |> getDescendants "Link"
+ |> function
+ | [] -> createRelativePath (projectFolder + string Path.DirectorySeparatorChar) sourceFile
+ | linkNode :: _ -> linkNode.InnerText
+ |> normalizePath
+ |> Path.GetDirectoryName
+ Some {
+ SourceFile = sourceFile
+ DestinationPath = destPath
+ BaseDir = projectFolder
+ }
let getRealItems compileItem =
let sourceFolder = Path.GetDirectoryName(compileItem.SourceFile)
@@ -2080,7 +2079,7 @@ type ProjectFile with
this.GetProjects includeReferencedProjects cache
|> this.ProjectsWithoutTemplates
|> Seq.collect getCompileRefs
- |> Seq.map getCompileItem
+ |> Seq.choose getCompileItem
|> Seq.collect getRealItems
diff --git a/tests/Paket.Tests/Paket.Tests.fsproj b/tests/Paket.Tests/Paket.Tests.fsproj
index 832e4e2a91..a2dd610165 100644
--- a/tests/Paket.Tests/Paket.Tests.fsproj
+++ b/tests/Paket.Tests/Paket.Tests.fsproj
@@ -130,6 +130,7 @@
+
diff --git a/tests/Paket.Tests/ProjectFile/OutputSpecs.fs b/tests/Paket.Tests/ProjectFile/OutputSpecs.fs
index 88b95a32ed..fec37effca 100644
--- a/tests/Paket.Tests/ProjectFile/OutputSpecs.fs
+++ b/tests/Paket.Tests/ProjectFile/OutputSpecs.fs
@@ -176,6 +176,15 @@ let ``should maintain order when updating project file items`` () =
]
CollectionAssert.AreEqual(expected, actual)
+[]
+let ``should not fail on Compile Remove entry without Include or Update attribute`` () =
+ ensureDir ()
+ let projFile = ProjectFile.TryLoad("./ProjectFile/TestData/CompileRemoveOnly.csprojtest").Value
+ let cache = PackProcessCache.empty
+ projFile.GetCompileItems false cache
+ |> Seq.toList
+ |> shouldEqual []
+
[]
let ``should remove missing files that exist in the project`` () =
ensureDir ()
diff --git a/tests/Paket.Tests/ProjectFile/TestData/CompileRemoveOnly.csprojtest b/tests/Paket.Tests/ProjectFile/TestData/CompileRemoveOnly.csprojtest
new file mode 100644
index 0000000000..56535c851e
--- /dev/null
+++ b/tests/Paket.Tests/ProjectFile/TestData/CompileRemoveOnly.csprojtest
@@ -0,0 +1,11 @@
+
+
+
+ TestPaket
+ netstandard1.4
+
+
+
+
+
+