-
Couldn't load subscription status.
- Fork 6
Adding ability to generate nuget packages #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
aaronpowell
wants to merge
8
commits into
asg017:main
Choose a base branch
from
aaronpowell:nuget-generator
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
0df85b2
Adding ability to generate nuget packages
aaronpowell 58300b5
Fixing how the runtime identifiers are mapped in the nuget package
aaronpowell 231e799
Update src/nuget.rs
aaronpowell 0432fb0
Adding the props and targets files for the nuget package
aaronpowell 7197da7
Apply suggestions from code review
aaronpowell 5987d9e
making the package a nuget source-only so it can provide a helper method
aaronpowell bd79475
Merge branch 'nuget-generator' of https://github.com/aaronpowell/sqli…
aaronpowell 12f006b
Apply suggestions from code review
aaronpowell File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,288 @@ | ||
| use crate::{Cpu, GeneratedAsset, GeneratedAssetKind, Os, Project}; | ||
| use serde::{Deserialize, Serialize}; | ||
| use std::{ | ||
| io::{self, Cursor, Write}, | ||
| path::Path, | ||
| }; | ||
| use zip::{write::FileOptions, ZipWriter}; | ||
|
|
||
| #[derive(Debug, Deserialize, Serialize)] | ||
| pub struct Nuspec { | ||
| pub metadata: Metadata, | ||
| } | ||
|
|
||
| #[derive(Debug, Deserialize, Serialize)] | ||
| pub struct Metadata { | ||
| pub id: String, | ||
| pub version: String, | ||
| pub title: String, | ||
| pub authors: String, | ||
| pub owners: String, | ||
| pub require_license_acceptance: bool, | ||
| pub description: String, | ||
| pub files: Option<Vec<String>>, | ||
| } | ||
|
|
||
| impl Nuspec { | ||
| fn new(project: &Project) -> Self { | ||
| let author = project.spec.package.authors.first().unwrap(); | ||
| Self { | ||
| metadata: Metadata { | ||
| id: project.spec.package.name.clone(), | ||
| version: project.version.to_string(), | ||
| title: project.spec.package.name.clone(), | ||
| authors: author.clone(), | ||
| owners: author.clone(), | ||
| require_license_acceptance: false, | ||
| description: project.spec.package.description.clone(), | ||
| files: None, | ||
| }, | ||
| } | ||
| } | ||
|
|
||
| fn to_xml(&self) -> String { | ||
| let files_xml = if let Some(files) = &self.metadata.files { | ||
| files | ||
| .iter() | ||
| .map(|file| format!("<file src=\"{}\" target=\"{}\" />", file, file)) | ||
| .collect::<Vec<_>>() | ||
| .join("\n") | ||
| } else { | ||
| String::new() | ||
| }; | ||
|
|
||
| format!( | ||
| r#"<?xml version="1.0" encoding="utf-8"?> | ||
| <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> | ||
| <metadata> | ||
| <id>{}</id> | ||
| <version>{}</version> | ||
| <title>{}</title> | ||
| <authors>{}</authors> | ||
| <owners>{}</owners> | ||
| <requireLicenseAcceptance>{}</requireLicenseAcceptance> | ||
| <description>{}</description> | ||
| </metadata> | ||
| <files> | ||
| {} | ||
| </files> | ||
| </package>"#, | ||
| self.metadata.id, | ||
| self.metadata.version, | ||
| self.metadata.title, | ||
| self.metadata.authors, | ||
| self.metadata.owners, | ||
| self.metadata.require_license_acceptance, | ||
| self.metadata.description, | ||
| files_xml | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| pub struct NugetPackage { | ||
| zip: ZipWriter<Cursor<Vec<u8>>>, | ||
| } | ||
|
|
||
| impl NugetPackage { | ||
| pub fn new(package_id: &str) -> io::Result<Self> { | ||
| let buffer = Vec::new(); | ||
| let cursor = Cursor::new(buffer); | ||
| let mut zip = ZipWriter::new(cursor); | ||
| zip.start_file("[Content_Types].xml", FileOptions::default())?; | ||
| zip.write_all(Self::content_types().as_bytes())?; | ||
| // add props_file to the folder buildTransitive\net46 | ||
| let props_file_name = format!("build/netstandard2.0/{}.props", package_id); | ||
| zip.start_file(&props_file_name, FileOptions::default())?; | ||
| zip.write_all(Self::props_file().as_bytes())?; | ||
|
|
||
| // add targets_file to the folder buildTransitive\net46 | ||
| let targets_file_name = format!("build/netstandard2.0/{}.targets", package_id); | ||
| zip.start_file(&targets_file_name, FileOptions::default())?; | ||
| zip.write_all(Self::targets_file(package_id).as_bytes())?; | ||
| Ok(Self { zip }) | ||
| } | ||
|
|
||
| fn content_types() -> String { | ||
| r#"<?xml version="1.0" encoding="utf-8"?> | ||
| <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"> | ||
| <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> | ||
| <Default Extension="xml" ContentType="application/xml"/> | ||
| <Default Extension="nuspec" ContentType="application/octet-stream"/> | ||
| <Default Extension="psmdcp" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/> | ||
| </Types>"#.to_string() | ||
| } | ||
|
|
||
| fn props_file() -> String { | ||
| r#"<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
|
|
||
| <!-- | ||
| NuGet packages.config doesn't support native assemblies automatically, | ||
| so copy the native assemblies to the output directory. | ||
| --> | ||
| <ItemGroup Condition="Exists('packages.config') OR | ||
| Exists('$(MSBuildProjectName).packages.config') OR | ||
| Exists('packages.$(MSBuildProjectName).config')"> | ||
| <Content Include="$(MSBuildThisFileDirectory)\..\..\runtimes\win-x64\native\*.dll" | ||
| Condition="'$(PlatformTarget)' == 'x64'"> | ||
| <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
| <Visible>false</Visible> | ||
| <Link>%(Filename)%(Extension)</Link> | ||
| </Content> | ||
|
|
||
| <Content Include="$(MSBuildThisFileDirectory)\..\..\runtimes\win-x86\native\*.dll" | ||
| Condition="'$(PlatformTarget)' == 'x86'"> | ||
| <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
| <Visible>false</Visible> | ||
| <Link>%(Filename)%(Extension)</Link> | ||
| </Content> | ||
|
|
||
| <Content Include="$(MSBuildThisFileDirectory)\..\..\runtimes\win-arm64\native\*.dll" | ||
| Condition="'$(PlatformTarget)' == 'arm64'"> | ||
| <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
| <Visible>false</Visible> | ||
| <Link>%(Filename)%(Extension)</Link> | ||
| </Content> | ||
| </ItemGroup> | ||
|
|
||
| </Project>"# | ||
| .to_string() | ||
| } | ||
|
|
||
| fn targets_file(package_id: &str) -> String { | ||
| format!( | ||
| r#"<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
|
|
||
| <PropertyGroup> | ||
| <EnableUnsupportedPlatformTargetCheck Condition="'$(EnableUnsupportedPlatformTargetCheck)' == ''">true</EnableUnsupportedPlatformTargetCheck> | ||
| </PropertyGroup> | ||
|
|
||
| <Target Name="_CheckForUnsupportedPlatformTarget" | ||
| Condition="'$(EnableUnsupportedPlatformTargetCheck)' == 'true'" | ||
| AfterTargets="_CheckForInvalidConfigurationAndPlatform"> | ||
|
|
||
| <!-- | ||
| Special case .NET Core portable applications. When building a portable .NET Core app, | ||
| the PlatformTarget is empty, and you don't know until runtime (i.e. which dotnet.exe) | ||
| what processor architecture will be used. | ||
| --> | ||
| <Error Condition="('$(PlatformTarget)' != 'x64' AND '$(PlatformTarget)' != 'x86') AND | ||
| ('$(OutputType)' == 'Exe' OR '$(OutputType)'=='WinExe') AND | ||
| !('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(PlatformTarget)' == '')" | ||
| Text="{} currently supports 'x64' and 'x86' processor architectures. Please ensure your application is targeting 'x64' or 'x86'." /> | ||
| </Target> | ||
|
|
||
| </Project>"#, | ||
| package_id | ||
| ) | ||
| } | ||
|
|
||
| pub fn add_nuspec(&mut self, nuspec: &Nuspec) -> io::Result<()> { | ||
| let nuspec_file_name = format!("{}.nuspec", nuspec.metadata.id); | ||
| let nuspec_content = nuspec.to_xml(); | ||
| self.zip | ||
| .start_file(&nuspec_file_name, FileOptions::default())?; | ||
| self.zip.write_all(nuspec_content.as_bytes())?; | ||
| Ok(()) | ||
| } | ||
|
|
||
| pub fn add_files(&mut self, project: &Project) -> io::Result<()> { | ||
| for platform_dir in &project.platform_directories { | ||
| if !(matches!(platform_dir.os, Os::Linux | Os::Macos | Os::Windows) | ||
| && matches!(platform_dir.cpu, Cpu::X86_64 | Cpu::Aarch64)) | ||
| { | ||
| continue; | ||
| } | ||
| for loadable_file in &platform_dir.loadable_files { | ||
| let os = match platform_dir.os { | ||
| Os::Windows => "win", | ||
| Os::Linux => "linux", | ||
| Os::Macos => "osx", | ||
| Os::Android => "android", | ||
| Os::Ios => "ios", | ||
| Os::IosSimulator => "ios-simulator", | ||
| }; | ||
| let cpu = match platform_dir.cpu { | ||
| Cpu::Aarch64 => "arm64", | ||
| Cpu::X86_64 => "x64", | ||
| Cpu::I686 => "x86", | ||
| Cpu::Armv7a => "armv7", | ||
| }; | ||
| let file_path = | ||
| format!("runtimes/{}-{}/native/{}", os, cpu, loadable_file.file.name); | ||
| self.zip.start_file(&file_path, FileOptions::default())?; | ||
| self.zip.write_all(&loadable_file.file.data)?; | ||
| } | ||
| } | ||
| Ok(()) | ||
| } | ||
|
|
||
| pub fn add_cs_file(&mut self, project: &Project) -> io::Result<()> { | ||
| let package_name = project.spec.targets.nuget.as_ref().map_or_else( | ||
| || project.spec.package.name.replace('-', "_"), | ||
| |nuget| nuget.friendly_name.clone(), | ||
| ); | ||
| let cs_file_content = format!( | ||
| r#"// <auto-generated/> | ||
|
|
||
| namespace Microsoft.Data.Sqlite | ||
| {{ | ||
| public static class Sqlite{0}Extensions | ||
| {{ | ||
| public static void Load{0}(this SqliteConnection connection) | ||
| => connection.LoadExtension("{1}"); | ||
| }} | ||
| }}"#, | ||
| package_name, | ||
| project.platform_directories[0].loadable_files[0] | ||
| .file | ||
| .name | ||
| .replace(".dll", "") | ||
| .replace(".so", "") | ||
| .replace(".dylib", "") | ||
| ); | ||
| let cs_file_path = format!( | ||
| "contentFiles/cs/netstandard2.0/{}/{}.cs", | ||
| package_name, package_name | ||
| ); | ||
| self.zip.start_file(&cs_file_path, FileOptions::default())?; | ||
| self.zip.write_all(cs_file_content.as_bytes())?; | ||
| Ok(()) | ||
| } | ||
|
|
||
| fn update_nuspec_with_files(&self, nuspec: &mut Nuspec) { | ||
| nuspec.metadata.files = Some(vec![format!( | ||
| "<file src=\"*.cs\" target=\"contentFiles/cs/netstandard2.0/{}\"/>", | ||
| nuspec.metadata.id | ||
| )]); | ||
| } | ||
|
|
||
| pub fn finish(mut self) -> io::Result<Vec<u8>> { | ||
| let result = self.zip.finish()?; | ||
| Ok(result.into_inner()) | ||
| } | ||
| } | ||
|
|
||
| pub(crate) fn write_nuget_packages( | ||
| project: &Project, | ||
| nuget_output_directory: &Path, | ||
| ) -> io::Result<Vec<GeneratedAsset>> { | ||
| let mut assets = vec![]; | ||
| let mut nuspec = Nuspec::new(project); | ||
| let mut package = NugetPackage::new(&nuspec.metadata.id)?; | ||
| package.add_nuspec(&nuspec)?; | ||
| package.add_files(project)?; | ||
| package.add_cs_file(project)?; | ||
| package.update_nuspec_with_files(&mut nuspec); | ||
| let buffer = package.finish()?; | ||
| let output_path = nuget_output_directory.join(format!( | ||
| "{}.{}.nupkg", | ||
| nuspec.metadata.id, nuspec.metadata.version | ||
| )); | ||
| std::fs::write(&output_path, &buffer)?; | ||
| assets.push(GeneratedAsset::from( | ||
| GeneratedAssetKind::Nuget, | ||
| &output_path, | ||
| &buffer, | ||
| )?); | ||
| Ok(assets) | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see jeffhandley#1 for details
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest adding a
theon 230:Utility for loading the SQLite vector extension.