Tuesday, July 7, 2020

PowerShell/Nuget: create a NuSpec file Containing all Files in a Folder

For a project, I needed a Nuget package that contained all files in a given folder hierarchy. This meant that the Nuget packaged included assemblies (DLLs) and other files that were to be considered content. A luck would have it, my last blog post contained an example of how, given a folder name passed as a parameter, to traverse every file a sub-folder: PowerShell: Traverse all Folders and Files for a given Path.

Files are specified in a Nuspec file using the falling rather mundane XML format where a <files> element contains one ore more <file> elements. Wild cards are supported as are attributes to include and exclude specific files. The release notes found at NuGet 1.5 Release Notes contains the following documentation:


The PowerShell script for traversing a folder hierarchy and creating on <file> element per-detected fie is as follows:

Param (
    [string] $folderName = $PSScriptRoot
)

class NuSpecFiles {
    [System.Text.StringBuilder] $filesXml = [System.Text.StringBuilder]::new()

    [string] $rootFolder

    [void] Append([string] $parentFolder, [string] $filename) {
        [string] $target = $filename

        if (-not ([string]::IsNullOrEmpty($parentFolder))) {
            $target = Join-Path -Path $parentFolder -ChildPath $filename            
        }

        # <file src="Your_Folder\*.pp" target="content\Your_Folder"/>
        $this.filesXml.AppendLine("  <file src=""$parentFolder"" target=""$target"" />")
    }

    [string] StripParentFolder([string] $folder) {
        return $folder.TrimStart($this.rootFolder)
    }

    [void] Traverse([string] $folderName) {
        [string] $parentFolder = $this.StripParentFolder($folderName)

        $entities = Get-ChildItem `
            -Path $folderName `
            -ErrorAction SilentlyContinue `
            -Force

        foreach ($entry in $entities) {
            if ($entry -is  [System.IO.DirectoryInfo]) {
                $this.Traverse($entry.FullName)
            }

            else { # if ($entry -is  [System.IO.FileInfo])
                $this.Append($parentFolder, $entry.Name)                
            }
        }
    }

    <#
        <files>
            <file src="lib\net472\any_assembly.dll" 
                  target="lib\net472" />
            <file src="Any_Folder\*.txt"               
                  target="content\Any_Folder"/>
            <file src="Any_Folder\Any_SubFolder\*.*" 
                  target="content" />
            <file src="*.config" target="content" />
        </files>
    #>
    [void] Create([string] $folderName)
    {
        $this.rootFolder = $folderName
        $this.filesXml.Clear()
        $this.filesXml.AppendLine('<files>')
        $this.Traverse($folderName)
        $this.filesXml.AppendLine('</files>')
    }

    [string] GetFilesXmlElement()
    {
        return $this.filesXml.ToString()
    }
}

[NuSpecFiles] $nuspecFiles = [NuSpecFiles]::new()

$nuspecFiles.Create($folderName)
$nuspecFiles.GetFilesXmlElement()

No comments :

Post a Comment