diff options
author | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2019-04-18 22:46:00 -0400 |
---|---|---|
committer | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2019-09-14 17:14:56 -0400 |
commit | b887ecb30b4c41d58c6211ea00423f8259eebef5 (patch) | |
tree | 272fca4a57fc3f35f924231bfc5c550fe95e4a13 | |
parent | aa7e4b9c36bf14656493ee0a7ab2dab394a3cf64 (diff) | |
download | SMAPI-b887ecb30b4c41d58c6211ea00423f8259eebef5.tar.gz SMAPI-b887ecb30b4c41d58c6211ea00423f8259eebef5.tar.bz2 SMAPI-b887ecb30b4c41d58c6211ea00423f8259eebef5.zip |
fix <IgnoreModFilePatterns> not applied to files matched by convention, update readme
-rw-r--r-- | docs/mod-build-config.md | 45 | ||||
-rw-r--r-- | src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs | 97 | ||||
-rw-r--r-- | src/SMAPI.ModBuildConfig/package.nuspec | 1 |
3 files changed, 83 insertions, 60 deletions
diff --git a/docs/mod-build-config.md b/docs/mod-build-config.md index 8bd7b79d..4f46100a 100644 --- a/docs/mod-build-config.md +++ b/docs/mod-build-config.md @@ -26,16 +26,9 @@ The package... ## Configure ### Deploy files into the `Mods` folder -Your mod is copied into the game's `Mods` folder (with a subfolder matching your project name) -when you rebuild the code. The package automatically includes... - -* any build output; -* your `manifest.json`; -* any [`i18n` files](https://stardewvalleywiki.com/Modding:Translations); -* the `assets` folder if present. - -To add custom files to the mod folder, just [add them to the build output](https://stackoverflow.com/a/10828462/262123). -(If your project references another mod, make sure the reference is [_not_ marked 'copy local'](https://msdn.microsoft.com/en-us/library/t1zz5y8c(v=vs.100).aspx).) +Your mod is copied into the game's `Mods` folder when you rebuild the code, with a subfolder +matching the mod's project name. This includes the files set via [_Files included in the release_](#files-included-in-release) +below. You can change the mod's folder name by adding this above the first `</PropertyGroup>` in your `.csproj`: @@ -49,9 +42,9 @@ If you don't want to deploy the mod automatically, you can add this: ``` ### Create release zip -A zip file is also created in the build output folder when you rebuild the code. This contains the -same files deployed to the `Mods` folder, in the recommended format for uploading to Nexus Mods or -other sites. +A zip file is also created in the build output folder when you rebuild the code. This includes the +files set via [_Files included in the release_](#files-included-in-release) below, in the format +recommended for uploading to Nexus Mods or other sites. You can change the zipped folder name (and zip name) by adding this above the first `</PropertyGroup>` in your `.csproj`: @@ -118,15 +111,30 @@ or you have multiple installs, you can specify the path yourself. There's two wa The configuration will check your custom path first, then fall back to the default paths (so it'll still compile on a different computer). -### Ignore files -If you don't want to include a file in the mod folder or release zip: -* Make sure it's not copied to the build output. For a DLL, make sure the reference is [not marked 'copy local'](https://msdn.microsoft.com/en-us/library/t1zz5y8c(v=vs.100).aspx). +You access the game path via `$(GamePath)` in MSBuild properties, if you need to reference another +file in the game folder. + +### Files included in release +The package automatically considers these files to be part of your mod: + +* the `manifest.json` in your project; +* the [`i18n` files](https://stardewvalleywiki.com/Modding:Translations) in your project (if any); +* the `assets` folder in your project (if present); +* and any files in the build output folder. + +To add custom files to the release, just [add them to the build output](https://stackoverflow.com/a/10828462/262123). +(If your project references another mod, make sure the reference is [_not_ marked 'copy local'](https://msdn.microsoft.com/en-us/library/t1zz5y8c(v=vs.100).aspx).) + +To exclude a file from the release: +* Make sure it's not copied to the build output. (For a DLL, make sure the reference is [not marked 'copy local'](https://msdn.microsoft.com/en-us/library/t1zz5y8c(v=vs.100).aspx).) This doesn't apply to `manifest.json`, + `assets`, or `i18n` which are copied regardless.) * Or add this to your `.csproj` file under the `<Project` line: ```xml <IgnoreModFilePatterns>\.txt$, \.pdf$</IgnoreModFilePatterns> ``` This is a comma-delimited list of regular expression patterns. If any pattern matches a file's - relative path in your mod folder, that file won't be included. + relative path in your mod folder, that file won't be included. (This also works for `assets` and + `i18n`.) ### Non-mod projects You can use the package in non-mod projects too (e.g. unit tests or framework DLLs). You'll need to @@ -216,8 +224,9 @@ _[Game path](#game-path)_ above. ### Upcoming release * Updated for Stardew Valley 1.4. * If the project contains an `assets` folder, its contents are now included in the mod automatically. -* Dropped support for very old versions of SMAPI and Visual Studio. * Fixed `Newtonsoft.Json.pdb` included in release zips when Json.NET is referenced directly. +* Fixed `<IgnoreModFilePatterns>` not working for `i18n` files. +* Dropped support for very old versions of SMAPI and Visual Studio. ### 2.2 * Added support for SMAPI 2.8+ (still compatible with earlier versions). diff --git a/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs b/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs index 6c11b0fe..e67a18c1 100644 --- a/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs +++ b/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs @@ -41,13 +41,63 @@ namespace StardewModdingAPI.ModBuildConfig.Framework if (!Directory.Exists(targetDir)) throw new UserErrorException("Could not create mod package because no build output was found."); + // collect files + foreach (Tuple<string, FileInfo> entry in this.GetPossibleFiles(projectDir, targetDir)) + { + string relativePath = entry.Item1; + FileInfo file = entry.Item2; + + if (!this.ShouldIgnore(file, relativePath, ignoreFilePatterns)) + this.Files[relativePath] = file; + } + + // check for required files + if (validateRequiredModFiles) + { + // manifest + if (!this.Files.ContainsKey(this.ManifestFileName)) + throw new UserErrorException($"Could not create mod package because no {this.ManifestFileName} was found in the project or build output."); + + // DLL + // ReSharper disable once SimplifyLinqExpression + if (!this.Files.Any(p => !p.Key.EndsWith(".dll"))) + throw new UserErrorException("Could not create mod package because no .dll file was found in the project or build output."); + } + } + + /// <summary>Get the files in the mod package.</summary> + public IDictionary<string, FileInfo> GetFiles() + { + return new Dictionary<string, FileInfo>(this.Files, StringComparer.InvariantCultureIgnoreCase); + } + + /// <summary>Get a semantic version from the mod manifest.</summary> + /// <exception cref="UserErrorException">The manifest is missing or invalid.</exception> + public string GetManifestVersion() + { + if (!this.Files.TryGetValue(this.ManifestFileName, out FileInfo manifestFile) || !new JsonHelper().ReadJsonFileIfExists(manifestFile.FullName, out Manifest manifest)) + throw new InvalidOperationException($"The mod does not have a {this.ManifestFileName} file."); // shouldn't happen since we validate in constructor + + return manifest.Version.ToString(); + } + + + /********* + ** Private methods + *********/ + /// <summary>Get all files to include in the mod folder, not accounting for ignore patterns.</summary> + /// <param name="projectDir">The folder containing the project files.</param> + /// <param name="targetDir">The folder containing the build output.</param> + /// <returns>Returns tuples containing the relative path within the mod folder, and the file to copy to it.</returns> + private IEnumerable<Tuple<string, FileInfo>> GetPossibleFiles(string projectDir, string targetDir) + { // project manifest bool hasProjectManifest = false; { - FileInfo manifest = new FileInfo(Path.Combine(projectDir, "manifest.json")); + FileInfo manifest = new FileInfo(Path.Combine(projectDir, this.ManifestFileName)); if (manifest.Exists) { - this.Files[this.ManifestFileName] = manifest; + yield return Tuple.Create(this.ManifestFileName, manifest); hasProjectManifest = true; } } @@ -58,7 +108,7 @@ namespace StardewModdingAPI.ModBuildConfig.Framework if (translationsFolder.Exists) { foreach (FileInfo file in translationsFolder.EnumerateFiles()) - this.Files[Path.Combine("i18n", file.Name)] = file; + yield return Tuple.Create(Path.Combine("i18n", file.Name), file); hasProjectTranslations = true; } @@ -70,7 +120,7 @@ namespace StardewModdingAPI.ModBuildConfig.Framework foreach (FileInfo file in assetsFolder.EnumerateFiles("*", SearchOption.AllDirectories)) { string relativePath = PathUtilities.GetRelativePath(projectDir, file.FullName); - this.Files[relativePath] = file; + yield return Tuple.Create(relativePath, file); } hasAssetsFolder = true; } @@ -91,48 +141,11 @@ namespace StardewModdingAPI.ModBuildConfig.Framework if (hasAssetsFolder && this.EqualsInvariant(segments[0], "assets")) continue; - // handle ignored files - if (this.ShouldIgnore(file, relativePath, ignoreFilePatterns)) - continue; - // add file - this.Files[relativePath] = file; - } - - // check for required files - if (validateRequiredModFiles) - { - // manifest - if (!this.Files.ContainsKey(this.ManifestFileName)) - throw new UserErrorException($"Could not create mod package because no {this.ManifestFileName} was found in the project or build output."); - - // DLL - // ReSharper disable once SimplifyLinqExpression - if (!this.Files.Any(p => !p.Key.EndsWith(".dll"))) - throw new UserErrorException("Could not create mod package because no .dll file was found in the project or build output."); + yield return Tuple.Create(relativePath, file); } } - /// <summary>Get the files in the mod package.</summary> - public IDictionary<string, FileInfo> GetFiles() - { - return new Dictionary<string, FileInfo>(this.Files, StringComparer.InvariantCultureIgnoreCase); - } - - /// <summary>Get a semantic version from the mod manifest.</summary> - /// <exception cref="UserErrorException">The manifest is missing or invalid.</exception> - public string GetManifestVersion() - { - if (!this.Files.TryGetValue(this.ManifestFileName, out FileInfo manifestFile) || !new JsonHelper().ReadJsonFileIfExists(manifestFile.FullName, out Manifest manifest)) - throw new InvalidOperationException($"The mod does not have a {this.ManifestFileName} file."); // shouldn't happen since we validate in constructor - - return manifest.Version.ToString(); - } - - - /********* - ** Private methods - *********/ /// <summary>Get whether a build output file should be ignored.</summary> /// <param name="file">The file to check.</param> /// <param name="relativePath">The file's relative path in the package.</param> diff --git a/src/SMAPI.ModBuildConfig/package.nuspec b/src/SMAPI.ModBuildConfig/package.nuspec index b6ef98f0..79a4f008 100644 --- a/src/SMAPI.ModBuildConfig/package.nuspec +++ b/src/SMAPI.ModBuildConfig/package.nuspec @@ -17,6 +17,7 @@ - If the project contains an `assets` folder, its contents are now included in the mod automatically. - Dropped support for very old versions of SMAPI and Visual Studio. - Fixed `Newtonsoft.Json.pdb` included in release zips when Json.NET is referenced directly. + - Fixed `<IgnoreModFilePatterns>` not working for `i18n` files. </releaseNotes> </metadata> </package> |