using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using ln.build.secrets; using ln.json; using ln.logging; namespace ln.build.commands { public class CommandEnvironment : IDictionary { public CommandEnvironment Parent { get; } public string WorkingDirectory { get; set; } = Path.GetFullPath("."); static string[] DefaultVariables = { "PATH", "HOME", "USERNAME" }; public Logger Logger { get; set; } Dictionary variables = new Dictionary(); public ICollection Keys => ((IDictionary)variables).Keys; public ICollection Values => ((IDictionary)variables).Values; public int Count => ((ICollection>)variables).Count; public bool IsReadOnly => ((ICollection>)variables).IsReadOnly; public string this[string key] { get => Get(key); set => Set(key,value); } SecretStorage secretStorage; public SecretStorage SecretStorage { get => secretStorage ?? Parent?.SecretStorage; set => secretStorage = value; } CIJob cIJob; public CIJob CIJob { get => cIJob ?? Parent?.CIJob ; set => cIJob = value; } public CommandEnvironment(CommandEnvironment parent) : this(parent.Logger) { Parent = parent; WorkingDirectory = parent.WorkingDirectory; } public CommandEnvironment(CommandEnvironment parent, Logger logger) : this(logger) { Parent = parent; WorkingDirectory = parent.WorkingDirectory; } public CommandEnvironment() : this(Logger.Default) { } public CommandEnvironment(Logger logger) { Logger = logger; foreach (string defName in DefaultVariables) Set(defName, Environment.GetEnvironmentVariable(defName)); } public CommandEnvironment(IEnumerable> setup) : this(Logger.Default, setup) { } public CommandEnvironment(Logger logger, IEnumerable> setup) : this(logger) { foreach (KeyValuePair kvp in setup) variables.Add(kvp.Key,kvp.Value); } public string Get(string varName) => Get(varName, null); public string Get(string varName,string defValue) { if (!variables.TryGetValue(varName,out string value)) { if (Parent != null) value = Parent.Get(varName, defValue); else value = defValue; } return value; } public CommandEnvironment Set(string varName,string value) { if (value != null) variables[varName] = value; else variables.Remove(varName); return this; } public void Extend(string varName,string value) => Extend(varName, value, ':'); public void Extend(string varName, string value, char seperator) { string currentValue = Get(varName, ""); if (string.Empty.Equals(currentValue)) { currentValue = value; } else { currentValue = string.Format("{0}{1}{2}",currentValue, seperator, value); } Set(varName, currentValue); } public bool Contains(string varName) => variables.ContainsKey(varName); public bool Contains(params string[] varNames) { foreach (string varName in varNames) { if (!variables.ContainsKey(varName)) return false; } return true; } public void Add(string key, string value) { ((IDictionary)variables).Add(key, value); } public bool ContainsKey(string key) { return ((IDictionary)variables).ContainsKey(key); } public bool Remove(string key) { return ((IDictionary)variables).Remove(key); } public bool TryGetValue(string key, [MaybeNullWhen(false)] out string value) { return ((IDictionary)variables).TryGetValue(key, out value); } public void Add(KeyValuePair item) { ((ICollection>)variables).Add(item); } public void Clear() { ((ICollection>)variables).Clear(); } public bool Contains(KeyValuePair item) { return ((ICollection>)variables).Contains(item); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { ((ICollection>)variables).CopyTo(array, arrayIndex); } public bool Remove(KeyValuePair item) { return ((ICollection>)variables).Remove(item); } public IEnumerator> GetEnumerator() { if (Parent != null) { return Keys.Concat(Parent.Keys).Distinct().Select((k)=>new KeyValuePair(k,Get(k))).GetEnumerator(); } else { return ((IEnumerable>)variables).GetEnumerator(); } } public void Apply(JSONObject jsonEnvironment) { foreach (string key in jsonEnvironment?.Keys ?? new string[0]) { Set(key, jsonEnvironment[key].ToNative().ToString()); } } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)variables).GetEnumerator(); } } }