using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Web.Script.Serialization;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace StardewModdingAPI.ModBuildConfig.Tasks
{
/// A build task which packs mod files into a conventional release zip.
public class CreateModReleaseZip : Task
{
/*********
** Accessors
*********/
/// The mod files to pack.
[Required]
public ITaskItem[] Files { get; set; }
/// The name of the mod.
[Required]
public string ModName { get; set; }
/// The absolute or relative path to the folder which should contain the generated zip file.
[Required]
public string OutputFolderPath { get; set; }
/*********
** Public methods
*********/
public override bool Execute()
{
try
{
// create output path if needed
Directory.CreateDirectory(this.OutputFolderPath);
// get zip filename
string fileName = string.Format("{0}-{1}.zip", this.ModName, this.GetManifestVersion());
// clear old zip file if present
string zipPath = Path.Combine(this.OutputFolderPath, fileName);
if (File.Exists(zipPath))
File.Delete(zipPath);
// create zip file
using (Stream zipStream = new FileStream(zipPath, FileMode.Create, FileAccess.Write))
using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create))
{
foreach (ITaskItem file in this.Files)
{
// get file info
string filePath = file.ItemSpec;
string entryName = this.ModName + '/' + file.GetMetadata("RecursiveDir") + file.GetMetadata("Filename") + file.GetMetadata("Extension");
if (new FileInfo(filePath).Directory.Name.Equals("i18n", StringComparison.InvariantCultureIgnoreCase))
entryName = Path.Combine("i18n", entryName);
// add to zip
using (Stream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
using (Stream fileStreamInZip = archive.CreateEntry(entryName).Open())
{
fileStream.CopyTo(fileStreamInZip);
}
}
}
return true;
}
catch (Exception ex)
{
this.Log.LogErrorFromException(ex);
return false;
}
}
/// Get a semantic version from the mod manifest (if available).
public string GetManifestVersion()
{
// Get the file JSON string
string json = "";
foreach (ITaskItem file in this.Files)
{
if (Path.GetFileName(file.ItemSpec).ToLower() != "manifest.json")
continue;
json = File.ReadAllText(file.ItemSpec);
break;
}
// Serialize the manifest json into a data object, then get a version object from that.
IDictionary data = (IDictionary)new JavaScriptSerializer().DeserializeObject(json);
IDictionary version = (IDictionary)data["Version"];
// Store our version numbers for ease of use
int major = (int)version["MajorVersion"];
int minor = (int)version["MinorVersion"];
int patch = (int)version["PatchVersion"];
return String.Format("{0}.{1}.{2}", major, minor, patch);
}
}
}