/// <summary> /// Gets the latest mod tag. /// </summary> /// <param name="asset">The asset.</param> /// <returns>The latest tag.</returns> public async Task <string> GetLatestModTag(IModAsset asset) { if (asset == null) { throw new ArgumentNullException(nameof(asset)); } return((await _website.API.GetAsset(asset.Id)).Resource.Data.Version); }
public CompileModTask(IModAsset mod, IModCompiler modCompiler, IModLoadOrderBuilder modLoadOrderBuilder) : base("Compile mod") { if (mod == null) throw new ArgumentNullException(nameof(mod)); _mod = mod; _modCompiler = modCompiler; _modLoadOrderBuilder = modLoadOrderBuilder; StatusDescription = $"Compile mod {mod.Name}."; }
public UpdateModTask(IModAsset mod, IParkitect parkitect, IQueueableTaskManager queueableTaskManager, IWebsite website) : base($"Update mod {mod?.Name}") { if (mod == null) throw new ArgumentNullException(nameof(mod)); _mod = mod; _parkitect = parkitect; _queueableTaskManager = queueableTaskManager; _website = website; StatusDescription = $"Update mod {mod.Name}"; }
public CompileModTask(IModAsset mod, IModCompiler modCompiler, IModLoadOrderBuilder modLoadOrderBuilder) : base("Compile mod") { if (mod == null) { throw new ArgumentNullException(nameof(mod)); } _mod = mod; _modCompiler = modCompiler; _modLoadOrderBuilder = modLoadOrderBuilder; StatusDescription = $"Compile mod {mod.Name}."; }
public UpdateModTask(IModAsset mod, IParkitect parkitect, IQueueableTaskManager queueableTaskManager, IWebsite website) : base($"Update mod {mod?.Name}") { if (mod == null) { throw new ArgumentNullException(nameof(mod)); } _mod = mod; _parkitect = parkitect; _queueableTaskManager = queueableTaskManager; _website = website; StatusDescription = $"Update mod {mod.Name}"; }
private string GetBuildPath(IModAsset mod) { var currentFile = Path.Combine(mod.InstallationPath, "bin/build.dat"); if (!File.Exists(currentFile)) { return(null); } var relativePath = File.ReadAllText(currentFile); return(File.Exists(Path.Combine(mod.InstallationPath, relativePath)) ? relativePath : null); }
public async Task<ModCompileResults> Compile(IModAsset mod) { return await Task.Run(() => { var dependencies = mod.Information.Dependencies?.Where(repository => repository != null) .Select(repository => { var dep = _parkitect.Assets[AssetType.Mod].OfType<IModAsset>() .FirstOrDefault(m => m.Repository?.ToLower() == repository.ToLower()); if (dep == null) throw new Exception($"Dependency {repository} was not installed."); return dep; }).ToArray() ?? new IModAsset[0]; using (var logFile = mod.OpenLogFile()) { try { // Delete old builds. var binPath = Path.Combine(mod.InstallationPath, "bin"); if (Directory.Exists(binPath)) { foreach (var build in Directory.GetFiles(binPath, "build-*.dll")) try { File.Delete(build); } catch { } } var buildPath = GetBuildPath(mod); // Compute build path if (mod.Information.IsDevelopment || string.IsNullOrWhiteSpace(buildPath) || !File.Exists(Path.Combine(mod.InstallationPath, buildPath))) { Directory.CreateDirectory(binPath); buildPath = $"bin/build-{DateTime.Now.ToString("yyMMddHHmmssfff")}.dll"; SetBuildPath(mod, buildPath); } var fullBuildPath = Path.Combine(mod.InstallationPath, buildPath); // Delete existing compiled file if compilation is forced. if (File.Exists(fullBuildPath)) { return ModCompileResults.Successful; } _log.WriteLine($"Compiling {mod.Name} to {buildPath}..."); logFile.Log($"Compiling {mod.Name} to {buildPath}..."); var assemblyFiles = new List<string>(); var sourceFiles = new List<string>(); var codeDir = string.IsNullOrWhiteSpace(mod.Information.BaseDir) || mod.Information.BaseDir.All(c => c == '/' || c == '\\') ? mod.InstallationPath : Path.Combine(mod.InstallationPath, mod.Information.BaseDir); var csProjPath = mod.Information.Project == null ? null : Path.Combine(codeDir, mod.Information.Project); List<string> unresolvedAssemblyReferences; List<string> unresolvedSourceFiles; if (csProjPath != null) { // Load source files and referenced assemblies from *.csproj file. _log.WriteLine($"Compiling from `{mod.Information.Project}`."); logFile.Log($"Compiling from `{mod.Information.Project}`."); // Open the .csproj file of the mod. var document = new XmlDocument(); document.Load(csProjPath); var manager = new XmlNamespaceManager(document.NameTable); manager.AddNamespace("x", "http://schemas.microsoft.com/developer/msbuild/2003"); // List the referenced assemblies of the mod. unresolvedAssemblyReferences = document.SelectNodes("//x:Reference", manager) .Cast<XmlNode>() .Select(node => node.Attributes["Include"]) .Select(name => name.Value.Split(',').FirstOrDefault()).ToList(); // List the source files of the mod. unresolvedSourceFiles = document.SelectNodes("//x:Compile", manager) .Cast<XmlNode>() .Select(node => node.Attributes["Include"].Value).ToList(); } else { throw new Exception("No project file set"); } // Resolve the assembly references. foreach (var name in unresolvedAssemblyReferences) { var resolved = ResolveAssembly(dependencies, name); if (resolved != null) { assemblyFiles.Add(resolved); _log.WriteLine($"Resolved assembly reference `{name}` to `{resolved}`"); logFile.Log($"Resolved assembly reference `{name}` to `{resolved}`"); } else { _log.WriteLine($"IGNORING assembly reference `{name}`"); logFile.Log($"IGNORING assembly reference `{name}`"); } } foreach (var depMod in dependencies) { var dep = GetBuildPath(depMod); if (dep == null) throw new Exception($"Dependency {depMod.Name} wasn't build yet"); assemblyFiles.Add(Path.Combine(depMod.InstallationPath, dep)); } // Resolve the source file paths. _log.WriteLine($"Source files: {string.Join(", ", unresolvedSourceFiles)} from `{codeDir}`."); logFile.Log($"Source files: {string.Join(", ", unresolvedSourceFiles)} from `{codeDir}`."); sourceFiles.AddRange( unresolvedSourceFiles.Select(file => { var repl = file.Replace("\\", Path.DirectorySeparatorChar.ToString()); return Path.Combine(codeDir, repl); })); // Compile. _log.WriteLine($"Compile using compiler version {mod.Information.CompilerVersion ?? "v3.5"}."); logFile.Log($"Compile using compiler version {mod.Information.CompilerVersion ?? "v3.5"}."); var csCodeProvider = new CSharpCodeProvider(new Dictionary<string, string> { {"CompilerVersion", mod.Information.CompilerVersion ?? "v3.5"} }); var parameters = new CompilerParameters(assemblyFiles.ToArray(), fullBuildPath); var result = csCodeProvider.CompileAssemblyFromFile(parameters, sourceFiles.ToArray()); // Copy to persistant instance if (File.Exists(fullBuildPath)) { var persistantPath = Path.Combine(mod.InstallationPath, $"bin/{Path.GetFileName(mod.InstallationPath)}.dll"); try { File.Copy(fullBuildPath, persistantPath, true); } catch (Exception e) { _log.WriteLine($"Could not copy binaries to persistant path {persistantPath}!", LogLevel.Warn); _log.WriteException(e, LogLevel.Warn); logFile.Log($"Could not copy binaries to persistant path {persistantPath}!", LogLevel.Warn); logFile.Log(e.Message, LogLevel.Warn); } } // Log errors. foreach (var error in result.Errors.Cast<CompilerError>()) { _log.WriteLine( $"{error.ErrorNumber}: {error.Line}:{error.Column}: {error.ErrorText} in {error.FileName}", LogLevel.Error); logFile.Log( $"{error.ErrorNumber}: {error.Line}:{error.Column}: {error.ErrorText} in {error.FileName}", LogLevel.Error); } return result.Errors.HasErrors ? new ModCompileResults(result.Errors.OfType<CompilerError>().ToArray(), false) : ModCompileResults.Successful; } catch (Exception e) { logFile.Log(e.Message, LogLevel.Error); return ModCompileResults.Failure; } } }); }
private string ResolveAssembly(IModAsset[] dependencies, string assemblyName) { if (assemblyName == null) throw new ArgumentNullException(nameof(assemblyName)); var dllName = $"{assemblyName}.dll"; if (SystemAssemblies.Contains(assemblyName)) return dllName; if (IgnoredAssemblies.Contains(assemblyName)) return null; // var modPath = Path.Combine(InstallationPath, BaseDir ?? "", dllName); // if (File.Exists(Path.Combine(modPath))) // return modPath; var managedAssemblyNames = Directory.GetFiles(_parkitect.Paths.DataManaged, "*.dll").Select(Path.GetFileName).ToArray(); if (managedAssemblyNames.Contains(dllName)) return Path.Combine(_parkitect.Paths.DataManaged, dllName); // if (SystemAssemblies.Contains(assemblyName)) // return dllName; return null; //throw new Exception($"Failed to resolve referenced assembly '{assemblyName}'"); }
private void SetBuildPath(IModAsset mod, string relativePath) { var currentFile = Path.Combine(mod.InstallationPath, "bin/build.dat"); File.WriteAllText(currentFile, relativePath); }
private string GetBuildPath(IModAsset mod) { var currentFile = Path.Combine(mod.InstallationPath, "bin/build.dat"); if (!File.Exists(currentFile)) return null; var relativePath = File.ReadAllText(currentFile); return File.Exists(Path.Combine(mod.InstallationPath, relativePath)) ? relativePath : null; }
/// <summary> /// Gets the latest mod tag. /// </summary> /// <param name="asset">The asset.</param> /// <returns>The latest tag.</returns> public async Task<string> GetLatestModTag(IModAsset asset) { if (asset == null) throw new ArgumentNullException(nameof(asset)); return (await _website.API.GetAsset(asset.Id)).Resource.Data.Version; }
private static void AddModToList(IModAsset[] allMods, Stack <IModAsset> buildStack, IModAsset mod, IList <IModAsset> orderedList) { if (orderedList.Contains(mod)) { return; } if (mod.Information.Dependencies != null) { buildStack.Push(mod); foreach (var dependency in mod.Information.Dependencies) { if (buildStack.Any(m => m.Repository == dependency)) { throw new Exception("Curcular dependency detected"); } var dependencyMod = allMods.FirstOrDefault(m => m.Repository == dependency); if (dependencyMod != null) { AddModToList(allMods, buildStack, dependencyMod, orderedList); } } buildStack.Pop(); } orderedList.Add(mod); }
public async Task <ModCompileResults> Compile(IModAsset mod) { return(await Task.Run(() => { var dependencies = mod.Information.Dependencies?.Where(repository => repository != null) .Select(repository => { var dep = _parkitect.Assets[AssetType.Mod].OfType <IModAsset>() .FirstOrDefault(m => m.Repository?.ToLower() == repository.ToLower()); if (dep == null) { throw new Exception($"Dependency {repository} was not installed."); } return dep; }).ToArray() ?? new IModAsset[0]; using (var logFile = mod.OpenLogFile()) { try { // Delete old builds. var binPath = Path.Combine(mod.InstallationPath, "bin"); if (Directory.Exists(binPath)) { foreach (var build in Directory.GetFiles(binPath, "build-*.dll")) { try { File.Delete(build); } catch { } } } var buildPath = GetBuildPath(mod); // Compute build path if (mod.Information.IsDevelopment || string.IsNullOrWhiteSpace(buildPath) || !File.Exists(Path.Combine(mod.InstallationPath, buildPath))) { Directory.CreateDirectory(binPath); buildPath = $"bin/build-{DateTime.Now.ToString("yyMMddHHmmssfff")}.dll"; SetBuildPath(mod, buildPath); } var fullBuildPath = Path.Combine(mod.InstallationPath, buildPath); // Delete existing compiled file if compilation is forced. if (File.Exists(fullBuildPath)) { return ModCompileResults.Successful; } _log.WriteLine($"Compiling {mod.Name} to {buildPath}..."); logFile.Log($"Compiling {mod.Name} to {buildPath}..."); var assemblyFiles = new List <string>(); var sourceFiles = new List <string>(); var codeDir = string.IsNullOrWhiteSpace(mod.Information.BaseDir) || mod.Information.BaseDir.All(c => c == '/' || c == '\\') ? mod.InstallationPath : Path.Combine(mod.InstallationPath, mod.Information.BaseDir); var csProjPath = mod.Information.Project == null ? null : Path.Combine(codeDir, mod.Information.Project); List <string> unresolvedAssemblyReferences; List <string> unresolvedSourceFiles; if (csProjPath != null) { // Load source files and referenced assemblies from *.csproj file. _log.WriteLine($"Compiling from `{mod.Information.Project}`."); logFile.Log($"Compiling from `{mod.Information.Project}`."); // Open the .csproj file of the mod. var document = new XmlDocument(); document.Load(csProjPath); var manager = new XmlNamespaceManager(document.NameTable); manager.AddNamespace("x", "http://schemas.microsoft.com/developer/msbuild/2003"); // List the referenced assemblies of the mod. unresolvedAssemblyReferences = document.SelectNodes("//x:Reference", manager) .Cast <XmlNode>() .Select(node => node.Attributes["Include"]) .Select(name => name.Value.Split(',').FirstOrDefault()).ToList(); // List the source files of the mod. unresolvedSourceFiles = document.SelectNodes("//x:Compile", manager) .Cast <XmlNode>() .Select(node => node.Attributes["Include"].Value).ToList(); } else { throw new Exception("No project file set"); } // Resolve the assembly references. foreach (var name in unresolvedAssemblyReferences) { var resolved = ResolveAssembly(dependencies, name); if (resolved != null) { assemblyFiles.Add(resolved); _log.WriteLine($"Resolved assembly reference `{name}` to `{resolved}`"); logFile.Log($"Resolved assembly reference `{name}` to `{resolved}`"); } else { _log.WriteLine($"IGNORING assembly reference `{name}`"); logFile.Log($"IGNORING assembly reference `{name}`"); } } foreach (var depMod in dependencies) { var dep = GetBuildPath(depMod); if (dep == null) { throw new Exception($"Dependency {depMod.Name} wasn't build yet"); } assemblyFiles.Add(Path.Combine(depMod.InstallationPath, dep)); } // Resolve the source file paths. _log.WriteLine($"Source files: {string.Join(", ", unresolvedSourceFiles)} from `{codeDir}`."); logFile.Log($"Source files: {string.Join(", ", unresolvedSourceFiles)} from `{codeDir}`."); sourceFiles.AddRange( unresolvedSourceFiles.Select(file => { var repl = file.Replace("\\", Path.DirectorySeparatorChar.ToString()); return Path.Combine(codeDir, repl); })); // Compile. _log.WriteLine($"Compile using compiler version {mod.Information.CompilerVersion ?? "v3.5"}."); logFile.Log($"Compile using compiler version {mod.Information.CompilerVersion ?? "v3.5"}."); var csCodeProvider = new CSharpCodeProvider(new Dictionary <string, string> { { "CompilerVersion", mod.Information.CompilerVersion ?? "v3.5" } }); var parameters = new CompilerParameters(assemblyFiles.ToArray(), fullBuildPath); var result = csCodeProvider.CompileAssemblyFromFile(parameters, sourceFiles.ToArray()); // Copy to persistant instance if (File.Exists(fullBuildPath)) { var persistantPath = Path.Combine(mod.InstallationPath, $"bin/{Path.GetFileName(mod.InstallationPath)}.dll"); try { File.Copy(fullBuildPath, persistantPath, true); } catch (Exception e) { _log.WriteLine($"Could not copy binaries to persistant path {persistantPath}!", LogLevel.Warn); _log.WriteException(e, LogLevel.Warn); logFile.Log($"Could not copy binaries to persistant path {persistantPath}!", LogLevel.Warn); logFile.Log(e.Message, LogLevel.Warn); } } // Log errors. foreach (var error in result.Errors.Cast <CompilerError>()) { _log.WriteLine( $"{error.ErrorNumber}: {error.Line}:{error.Column}: {error.ErrorText} in {error.FileName}", LogLevel.Error); logFile.Log( $"{error.ErrorNumber}: {error.Line}:{error.Column}: {error.ErrorText} in {error.FileName}", LogLevel.Error); } return result.Errors.HasErrors ? new ModCompileResults(result.Errors.OfType <CompilerError>().ToArray(), false) : ModCompileResults.Successful; } catch (Exception e) { logFile.Log(e.Message, LogLevel.Error); return ModCompileResults.Failure; } } })); }
private void SetBuildPath(IModAsset mod, string relativePath) { var currentFile = Path.Combine(mod.InstallationPath, "bin/build.dat"); File.WriteAllText(currentFile, relativePath); }