using System;
using System.IO;
using System.Linq;
namespace GarrysMod.AddonCreator
{
internal static class Program
{
private static void Main(string[] args)
{
switch (args[0])
{
case "create":
{
var folder = new DirectoryInfo(args[1]);
var output = args[2];
var addon = new Addon();
// recursively add files
foreach (var file in folder.EnumerateFiles("*", SearchOption.AllDirectories))
{
var relpath = MakeRelativePath(folder.FullName, file.FullName).Replace(Path.DirectorySeparatorChar, '/');
Console.WriteLine("Adding: {0}", relpath);
addon.Files.Add(relpath, new PhysicalAddonFileInfo(file.FullName));
}
// create addon
Console.WriteLine("Exporting addon...");
addon.Export(output);
Console.WriteLine("Done.");
break;
}
case "extract":
{
var gma = args[1];
var folder = new DirectoryInfo(args[2]);
var addon = new Addon();
addon.Import(gma);
Console.WriteLine("Loaded addon {0} by {1}, Version {2}", addon.Title, addon.Author, addon.Version);
// extract files
foreach (var file in addon.Files)
{
var relpath = file.Key;
var targetFile = new FileInfo(Path.Combine(folder.FullName, relpath.Replace('/', Path.DirectorySeparatorChar)));
Console.WriteLine("Extracting: {0}", relpath);
// create directory
var dir = targetFile.Directory;
if (dir == null)
continue; // I still need to think about the weird logic here
dir.Create();
// create file
using (var fs = targetFile.Create())
{
var buffer = file.Value.GetContents();
// long-compatible copy algorithm
for (long i = 0; i < buffer.LongLength; i += int.MaxValue)
{
var toWrite = (int)Math.Min(int.MaxValue, buffer.LongLength - i);
var toWriteBuf = buffer.AsEnumerable();
for (long j = 0; j < i; j += int.MaxValue)
{
toWriteBuf = toWriteBuf.Skip(int.MaxValue);
}
fs.Write(toWriteBuf.ToArray(), 0, toWrite);
}
}
}
Console.WriteLine("Done.");
break;
}
}
}
///
/// Creates a relative path from one file or folder to another.
///
/// Contains the directory that defines the start of the relative path.
/// Contains the path that defines the endpoint of the relative path.
/// The relative path from the start directory to the end path.
///
///
///
private static String MakeRelativePath(String fromPath, String toPath)
{
if (String.IsNullOrEmpty(fromPath)) throw new ArgumentNullException("fromPath");
if (String.IsNullOrEmpty(toPath)) throw new ArgumentNullException("toPath");
var fromUri = new Uri(fromPath);
var toUri = new Uri(toPath);
if (fromUri.Scheme != toUri.Scheme)
{
return toPath;
} // path can't be made relative.
Uri relativeUri = fromUri.MakeRelativeUri(toUri);
String relativePath = Uri.UnescapeDataString(relativeUri.ToString());
if (toUri.Scheme.ToUpperInvariant() == "FILE")
{
relativePath = relativePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
}
return relativePath;
}
}
}