private async Task StageDefinition(Definition definition) { foreach (var dependency in definition.Dependencies ?? new Dictionary <Name, VersionRange>()) { var repo = definition.Repositories?.FirstOrDefault(r => r.Name == dependency.Key); var adapter = new AdapterBuilder(dependency.Key, repo).Adapter(); var versions = await adapter.GetVersions(); var versionMatch = versions.LastOrDefault(version => dependency.Value.IsSatisfied(version)); if (versionMatch == null) { throw new Exception("No matching version found"); } Directory.CreateDirectory(Path.Combine(Environment.CurrentDirectory, Program.PluginPath, ".staging", dependency.Key.Vendor, dependency.Key.Project)); await adapter.Download(versionMatch); var dependencyDefinition = Definition.Load(Path.Combine(Environment.CurrentDirectory, Program.PluginPath, ".staging", dependency.Key.Vendor, dependency.Key.Project, Program.DefinitionFile)); // TODO: What should be validated? if (dependencyDefinition.Name != dependency.Key) { throw new Exception("Downloaded package does not match requested."); } if (dependencyDefinition.Version != versionMatch) { throw new Exception("Downloaded package does not match requested."); } await StageDefinition(dependencyDefinition); } }
public async Task Apply() { if (Directory.Exists(Path.Combine(Environment.CurrentDirectory, Program.PluginPath, ".staging"))) { Directory.Delete(Path.Combine(Environment.CurrentDirectory, Program.PluginPath, ".staging"), true); } foreach (var definition in this.Definitions) { var path = Path.Combine(Environment.CurrentDirectory, Program.PluginPath, definition.Name.Vendor, definition.Name.Project, Program.DefinitionFile); if (File.Exists(path)) { var loadedDefinition = Definition.Load(path); if (loadedDefinition.Name == definition.Name && loadedDefinition.Version == definition.Version) { continue; } } // Missing or outdated var dir = Path.Combine(Environment.CurrentDirectory, Program.PluginPath, definition.Name.Vendor, definition.Name.Project); if (Directory.Exists(dir)) { Directory.Delete(dir, true); } Directory.CreateDirectory(Path.Combine(Environment.CurrentDirectory, Program.PluginPath, ".staging", definition.Name.Vendor, definition.Name.Project)); Repository repo = null; // masterDefinition.Repositories?.FirstOrDefault(r => r.Name == definition.Name); // TODO var adapter = new AdapterBuilder(definition.Name, repo).Adapter(); await adapter.Download(definition.Version); var dependencyDefinition = Definition.Load(Path.Combine(Environment.CurrentDirectory, Program.PluginPath, ".staging", definition.Name.Vendor, definition.Name.Project, Program.DefinitionFile)); if (dependencyDefinition.Name != definition.Name) { throw new Exception("Downloaded package does not match requested."); } if (dependencyDefinition.Version != definition.Version) { throw new Exception("Downloaded package does not match requested."); } var src = Path.Combine(Environment.CurrentDirectory, Program.PluginPath, ".staging", definition.Name.Vendor, definition.Name.Project); var dst = Path.Combine(Environment.CurrentDirectory, Program.PluginPath, definition.Name.Vendor, definition.Name.Project); var configSrc = Path.Combine(src, "config"); var configDst = Path.Combine(Environment.CurrentDirectory, "config", definition.Name.Vendor, definition.Name.Project); new DirectoryInfo(src).Copy(dst); if (Directory.Exists(configSrc)) { Directory.CreateDirectory(configDst); foreach (var yml in Directory.EnumerateFiles(configSrc, "*.yml", SearchOption.TopDirectoryOnly)) { File.Copy(yml, configDst, false); } } } if (Directory.Exists(Path.Combine(Environment.CurrentDirectory, Program.PluginPath, ".staging"))) { Directory.Delete(Path.Combine(Environment.CurrentDirectory, Program.PluginPath, ".staging"), true); } }
public async Task Apply(Plugin baseDefinition = null) { if (baseDefinition != null) { var results = await StageDefinition(baseDefinition); var top = results.Item1; var all = top.Concat(results.Item2).Distinct().ToList(); foreach (var plugin in top.Where(d => d.Dependencies != null)) { foreach (var dependency in plugin.Dependencies) { var dependencyPlugin = all.FirstOrDefault(p => p.Name == dependency.Key); if (dependencyPlugin == null) { throw new Exception($"Unable to find dependency {dependency.Key}@{dependency.Value} required by {plugin.Name}@{plugin.Version}"); // TODO: DependencyException } if (!dependency.Value.IsSatisfied(dependencyPlugin.Version)) { throw new Exception($"{plugin.Name}@{plugin.Version} requires {dependencyPlugin.Name}@{dependency.Value} but {dependencyPlugin.Name}@{dependencyPlugin.Version} was found"); } if (plugin.DependencyNodes == null) { plugin.DependencyNodes = new List <Plugin>(); } plugin.DependencyNodes.Add(dependencyPlugin); } } this.Plugins = top; } this.Plugins = Sort(this.Plugins); // TODO: Don't store nested dependencies but still load them foreach (var definition in this.Plugins) { var path = Path.Combine(Environment.CurrentDirectory, ConfigurationManager.PluginPath, definition.Name.Vendor, definition.Name.Project, ConfigurationManager.DefinitionFile); if (File.Exists(path)) { var loadedDefinition = Plugin.Load(path); // TODO: IEquality if (loadedDefinition.Name.ToString() == definition.Name.ToString() && loadedDefinition.Version.ToString() == definition.Version.ToString() && baseDefinition?.Repositories?.FirstOrDefault(r => r.Name == definition.Name && r.Type == "local") == null) { continue; } } // TODO: Remove extra plugin folders/files // Missing or outdated var dir = Path.Combine(Environment.CurrentDirectory, ConfigurationManager.PluginPath, definition.Name.Vendor, definition.Name.Project); if (Directory.Exists(dir)) { DeleteDirectory(dir); } Directory.CreateDirectory(dir); var repo = baseDefinition?.Repositories?.FirstOrDefault(r => r.Name == definition.Name); var adapter = new AdapterBuilder(definition.Name, repo).Adapter(); await adapter.Download(new Version(definition.Version.ToString())); var dependencyDefinition = Plugin.Load(Path.Combine(dir, ConfigurationManager.DefinitionFile)); if (dependencyDefinition.Name != definition.Name) { throw new Exception("Downloaded package does not match requested."); } if (dependencyDefinition.Version.ToString() != definition.Version.ToString()) { throw new Exception("Downloaded package does not match requested."); } var configSrc = Path.Combine(dir, ConfigurationManager.ConfigurationPath); var configDst = Path.Combine(Environment.CurrentDirectory, ConfigurationManager.ConfigurationPath, definition.Name.Vendor, definition.Name.Project); if (!Directory.Exists(configSrc)) { continue; } if (!Directory.Exists(configDst)) { Directory.CreateDirectory(configDst); } // TODO: More files? // TODO: Ask user to replace foreach (var yml in Directory.EnumerateFiles(configSrc, "*.yml", SearchOption.TopDirectoryOnly)) { try { File.Copy(yml, Path.Combine(configDst, Path.GetFileName(yml)), false); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } }