using Sunfish.Config;
namespace Sunfish.Cli;
/// <summary>sunfish-cli share add|set|del|list: shares del fichero de configuracion.</summary>
internal static class ShareCommands
{
public static int Run(string[] args)
{
string? configPath = null;
var rest = new List<string>();
for (int i = 0; i < args.Length; i++)
{
if (args[i] is "-c" or "--config" && i + 1 < args.Length)
configPath = args[++i];
else if (args[i] == "--lang" && i + 1 < args.Length)
Strings.Force(args[++i]);
else
rest.Add(args[i]);
}
if (rest.Count == 0)
return Usage();
string path = ConfigLocator.Find(configPath) ?? ConfigLocator.PortablePath;
var config = File.Exists(path) ? SunfishConfig.Load(path) : new SunfishConfig { FilePath = path };
string verb = rest[0];
if (verb == "list")
{
if (config.Shares.Count == 0)
Console.WriteLine(Strings.AppNoShares);
foreach (var s in config.Shares)
{
string flags = string.Join(' ', new[]
{
s.Enabled ? "" : "(off)", s.Listing ? "listing" : "", s.Upload ? "upload" : "", s.Overwrite ? "overwrite" : "",
s.Rename ? "rename" : "", s.Delete ? "delete" : "", s.Zip ? "zip" : "",
s.Users.Count > 0 ? "users=" + string.Join(',', s.Users) : "",
}.Where(f => f.Length > 0));
Console.WriteLine($"{s.Name} {s.Location} {s.Path} {flags}");
}
return 0;
}
if (rest.Count < 2)
return Usage();
string name = rest[1];
var share = config.Shares.FirstOrDefault(s => s.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
switch (verb)
{
case "add":
{
if (rest.Count < 3)
return Usage();
if (!ShareSettings.IsValidName(name))
return Fail(Strings.ErrorBadName(name));
if (share is not null)
return Fail(Strings.ErrorNameInUse(name));
string folder = Path.GetFullPath(rest[2]);
if (!Directory.Exists(folder))
return Fail(Strings.ErrorNotAFolder(folder));
share = new ShareConfig { Name = name, Path = folder, Location = ShareSettings.SuggestLocation(config, name) };
if (ApplySettings(share, rest.Skip(3)) is { } error)
return Fail(error);
if (config.Shares.Any(s => s.Enabled && s.Location.Equals(share.Location, StringComparison.OrdinalIgnoreCase)))
return Fail(Strings.ErrorNameInUse(share.Location));
config.Shares.Add(share);
break;
}
case "set":
{
if (share is null)
return Fail(Texts.ShareMissing(name));
if (ApplySettings(share, rest.Skip(2)) is { } error)
return Fail(error);
break;
}
case "del":
if (share is null)
return Fail(Texts.ShareMissing(name));
config.Shares.Remove(share);
break;
default:
return Usage();
}
config.Save(path);
Console.WriteLine(Texts.ShareSaved(name, path));
return 0;
}
/// <summary>Opciones "Clave=valor" (las del INI) o "--location /x".</summary>
private static string? ApplySettings(ShareConfig share, IEnumerable<string> settings)
{
var list = settings.ToList();
for (int i = 0; i < list.Count; i++)
{
string item = list[i];
if (item == "--location" && i + 1 < list.Count)
{
if (ShareSettings.TrySet(share, "Location", list[++i]) is { } bad)
return bad;
continue;
}
int eq = item.IndexOf('=');
if (eq <= 0)
return Strings.UnknownShareKey(item);
if (ShareSettings.TrySet(share, item[..eq], item[(eq + 1)..]) is { } error)
return error;
}
return null;
}
private static int Usage()
{
Console.Error.WriteLine(Texts.ShareUsage);
return 1;
}
private static int Fail(string message)
{
Console.Error.WriteLine(message);
return 1;
}
}