Merge pull request #37 from That-One-Nerd/more-compression-options
Update main with some new compression formats.
This commit is contained in:
commit
51f58e6e82
@ -1,9 +1,13 @@
|
|||||||
global using Nerd_STF.Mathematics;
|
global using Nerd_STF.Mathematics;
|
||||||
|
global using SharpCompress.Archives.Rar;
|
||||||
|
global using SharpCompress.Archives.SevenZip;
|
||||||
|
global using SharpCompress.Readers;
|
||||||
global using SrcMod.Shell;
|
global using SrcMod.Shell;
|
||||||
global using SrcMod.Shell.Modules.ObjectModels;
|
global using SrcMod.Shell.Modules.ObjectModels;
|
||||||
global using System;
|
global using System;
|
||||||
global using System.Collections.Generic;
|
global using System.Collections.Generic;
|
||||||
global using System.Diagnostics;
|
global using System.Diagnostics;
|
||||||
|
global using System.Formats.Tar;
|
||||||
global using System.IO;
|
global using System.IO;
|
||||||
global using System.IO.Compression;
|
global using System.IO.Compression;
|
||||||
global using System.Linq;
|
global using System.Linq;
|
||||||
|
|||||||
@ -1,14 +1,24 @@
|
|||||||
namespace SrcMod.Shell.Modules;
|
namespace SrcMod.Shell.Modules;
|
||||||
|
|
||||||
|
// Some things that can be extracted can't be compressed by SharpCompress.
|
||||||
|
// In the future I might replace it with my own, but that'll take a *really*
|
||||||
|
// long time and I'm already planning to do that for the valve compression formats,
|
||||||
|
// so I'll seethe for now.
|
||||||
[Module("compress")]
|
[Module("compress")]
|
||||||
public static class CompressionModule
|
public static class CompressionModule
|
||||||
{
|
{
|
||||||
[Command("zip")]
|
[Command("gz")]
|
||||||
public static void CompressZip(string source, string? destination = null,
|
[Command("gzip")]
|
||||||
|
public static void CompressGZip(string source, string? destination = null,
|
||||||
CompressionLevel level = CompressionLevel.Optimal)
|
CompressionLevel level = CompressionLevel.Optimal)
|
||||||
{
|
{
|
||||||
destination ??= Path.Combine(Path.GetDirectoryName(Path.GetFullPath(source))!,
|
if (destination is null)
|
||||||
$"{Path.GetFileNameWithoutExtension(source)}.zip");
|
{
|
||||||
|
string full = Path.GetFullPath(source),
|
||||||
|
name = Path.GetFileName(full),
|
||||||
|
folder = Program.Shell!.WorkingDirectory;
|
||||||
|
destination ??= $"{folder}\\{name}.gz";
|
||||||
|
}
|
||||||
|
|
||||||
string absSource = Path.GetFullPath(source),
|
string absSource = Path.GetFullPath(source),
|
||||||
localDest = Path.GetRelativePath(Program.Shell!.WorkingDirectory, destination);
|
localDest = Path.GetRelativePath(Program.Shell!.WorkingDirectory, destination);
|
||||||
@ -19,8 +29,109 @@ public static class CompressionModule
|
|||||||
string message = $"Compressing file at \"{source}\" into \"{localDest}\"...";
|
string message = $"Compressing file at \"{source}\" into \"{localDest}\"...";
|
||||||
Write(message);
|
Write(message);
|
||||||
|
|
||||||
Stream writer = new FileStream(destination, FileMode.CreateNew);
|
FileStream writer = new(localDest, FileMode.CreateNew),
|
||||||
|
reader = new(absSource, FileMode.Open);
|
||||||
|
GZipStream gzip = new(writer, level);
|
||||||
|
|
||||||
|
reader.CopyTo(gzip);
|
||||||
|
|
||||||
|
gzip.Close();
|
||||||
|
reader.Close();
|
||||||
|
writer.Close();
|
||||||
|
|
||||||
|
Console.CursorLeft = 0;
|
||||||
|
Console.CursorTop -= (message.Length / Console.BufferWidth) + 1;
|
||||||
|
Write(new string(' ', message.Length), newLine: false);
|
||||||
|
}
|
||||||
|
else if (Directory.Exists(source)) throw new("The GZip format can only compress 1 file.");
|
||||||
|
else throw new("No file located at \"source\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("tar")]
|
||||||
|
[Command("tarball")]
|
||||||
|
public static void CompressTar(string source, string? destination = null)
|
||||||
|
{
|
||||||
|
if (destination is null)
|
||||||
|
{
|
||||||
|
string full = Path.GetFullPath(source),
|
||||||
|
name = Path.GetFileNameWithoutExtension(full),
|
||||||
|
folder = Program.Shell!.WorkingDirectory;
|
||||||
|
destination ??= $"{folder}\\{name}.tar";
|
||||||
|
}
|
||||||
|
|
||||||
|
string absSource = Path.GetFullPath(source),
|
||||||
|
localDest = Path.GetRelativePath(Program.Shell!.WorkingDirectory, destination);
|
||||||
|
|
||||||
|
if (File.Exists(source)) throw new("The Tar format cannot compress a single file.");
|
||||||
|
else if (Directory.Exists(source))
|
||||||
|
{
|
||||||
|
if (File.Exists(destination)) throw new($"File already exists at \"{localDest}\"");
|
||||||
|
|
||||||
|
Write($"Compressing folder at \"{source}\" into \"{localDest}\"...");
|
||||||
|
|
||||||
|
FileStream writer = new(destination, FileMode.CreateNew);
|
||||||
|
TarFile.CreateFromDirectory(absSource, writer, false);
|
||||||
|
|
||||||
|
writer.Close();
|
||||||
|
|
||||||
|
Console.CursorLeft = 0;
|
||||||
|
Write(new string(' ', Console.BufferWidth), newLine: false);
|
||||||
|
Console.SetCursorPosition(0, Console.CursorTop - 1);
|
||||||
|
Write(new string(' ', Console.BufferWidth), newLine: false);
|
||||||
|
}
|
||||||
|
else throw new("No file or directory located at \"source\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rar can't be compressed.
|
||||||
|
|
||||||
|
[Command("targz")]
|
||||||
|
[Command("tar.gz")]
|
||||||
|
[Command("tar-gz")]
|
||||||
|
public static void CompressTarGzip(string source, string? destination = null,
|
||||||
|
CompressionLevel level = CompressionLevel.Optimal)
|
||||||
|
{
|
||||||
|
if (destination is null)
|
||||||
|
{
|
||||||
|
string full = Path.GetFullPath(source),
|
||||||
|
name = Path.GetFileNameWithoutExtension(full),
|
||||||
|
folder = Program.Shell!.WorkingDirectory;
|
||||||
|
destination ??= $"{folder}\\{name}.tar.gz";
|
||||||
|
}
|
||||||
|
|
||||||
|
string firstDest = Path.GetFileNameWithoutExtension(destination);
|
||||||
|
|
||||||
|
CompressTar(source, firstDest);
|
||||||
|
CompressGZip(firstDest, destination, level);
|
||||||
|
File.Delete(firstDest);
|
||||||
|
|
||||||
|
Console.CursorLeft = 0;
|
||||||
|
Console.CursorTop--;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("zip")]
|
||||||
|
public static void CompressZip(string source, string? destination = null,
|
||||||
|
CompressionLevel level = CompressionLevel.Optimal, string comment = "")
|
||||||
|
{
|
||||||
|
if (destination is null)
|
||||||
|
{
|
||||||
|
string full = Path.GetFullPath(source),
|
||||||
|
name = Path.GetFileNameWithoutExtension(full),
|
||||||
|
folder = Program.Shell!.WorkingDirectory;
|
||||||
|
destination ??= $"{folder}\\{name}.zip";
|
||||||
|
}
|
||||||
|
|
||||||
|
string absSource = Path.GetFullPath(source),
|
||||||
|
localDest = Path.GetRelativePath(Program.Shell!.WorkingDirectory, destination);
|
||||||
|
|
||||||
|
if (File.Exists(source))
|
||||||
|
{
|
||||||
|
if (File.Exists(destination)) throw new($"File already exists at \"{localDest}\"");
|
||||||
|
string message = $"Compressing file at \"{source}\" into \"{localDest}\"...";
|
||||||
|
Write(message);
|
||||||
|
|
||||||
|
FileStream writer = new(destination, FileMode.CreateNew);
|
||||||
ZipArchive archive = new(writer, ZipArchiveMode.Create);
|
ZipArchive archive = new(writer, ZipArchiveMode.Create);
|
||||||
|
if (!string.IsNullOrWhiteSpace(comment)) archive.Comment = comment;
|
||||||
|
|
||||||
archive.CreateEntryFromFile(absSource, Path.GetFileName(absSource), level);
|
archive.CreateEntryFromFile(absSource, Path.GetFileName(absSource), level);
|
||||||
|
|
||||||
@ -37,18 +148,40 @@ public static class CompressionModule
|
|||||||
|
|
||||||
Write($"Compressing folder at \"{source}\" into \"{localDest}\"...");
|
Write($"Compressing folder at \"{source}\" into \"{localDest}\"...");
|
||||||
|
|
||||||
Stream writer = new FileStream(destination, FileMode.CreateNew);
|
FileStream writer = new(destination, FileMode.CreateNew);
|
||||||
ZipArchive archive = new(writer, ZipArchiveMode.Create);
|
ZipArchive archive = new(writer, ZipArchiveMode.Create);
|
||||||
|
if (!string.IsNullOrWhiteSpace(comment)) archive.Comment = comment;
|
||||||
|
|
||||||
List<string> files = new(GetAllFiles(absSource)),
|
List<string> files = new(GetAllFiles(absSource)),
|
||||||
relative = new();
|
relative = new();
|
||||||
foreach (string f in files) relative.Add(Path.GetRelativePath(absSource, f));
|
for (int i = 0; i < files.Count; i++)
|
||||||
|
{
|
||||||
|
string f = files[i];
|
||||||
|
if (f.Trim().ToLower() == destination.Trim().ToLower())
|
||||||
|
{
|
||||||
|
files.RemoveAt(i);
|
||||||
|
i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
relative.Add(Path.GetRelativePath(absSource, f));
|
||||||
|
}
|
||||||
|
|
||||||
|
int failed = 0;
|
||||||
|
|
||||||
LoadingBarStart();
|
LoadingBarStart();
|
||||||
for (int i = 0; i < files.Count; i++)
|
for (int i = 0; i < files.Count; i++)
|
||||||
{
|
{
|
||||||
archive.CreateEntryFromFile(files[i], relative[i], level);
|
bool failedThisTime = false;
|
||||||
LoadingBarSet((i + 1) / (float)files.Count, ConsoleColor.DarkGreen);
|
try
|
||||||
|
{
|
||||||
|
archive.CreateEntryFromFile(files[i], relative[i], level);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
failedThisTime = true;
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
LoadingBarSet((i + 1) / (float)files.Count, failedThisTime ? ConsoleColor.Red : ConsoleColor.DarkGreen); ;
|
||||||
Console.CursorLeft = 0;
|
Console.CursorLeft = 0;
|
||||||
string message = $"{relative[i]}";
|
string message = $"{relative[i]}";
|
||||||
int remainder = Console.BufferWidth - message.Length;
|
int remainder = Console.BufferWidth - message.Length;
|
||||||
@ -67,6 +200,13 @@ public static class CompressionModule
|
|||||||
Write(new string(' ', Console.BufferWidth), newLine: false);
|
Write(new string(' ', Console.BufferWidth), newLine: false);
|
||||||
Console.SetCursorPosition(0, Console.CursorTop - 2);
|
Console.SetCursorPosition(0, Console.CursorTop - 2);
|
||||||
Write(new string(' ', Console.BufferWidth), newLine: false);
|
Write(new string(' ', Console.BufferWidth), newLine: false);
|
||||||
|
|
||||||
|
if (failed > 0)
|
||||||
|
{
|
||||||
|
Console.CursorLeft = 0;
|
||||||
|
Write($"{failed} file{(failed == 1 ? " has" : "s have")} been ignored due to an error.",
|
||||||
|
ConsoleColor.DarkYellow);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else throw new("No file or directory located at \"source\"");
|
else throw new("No file or directory located at \"source\"");
|
||||||
|
|
||||||
@ -91,4 +231,6 @@ public static class CompressionModule
|
|||||||
name = $"Compressed a file or folder into a zip archive located at \"{destination}\""
|
name = $"Compressed a file or folder into a zip archive located at \"{destination}\""
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 7z can't be compressed.
|
||||||
}
|
}
|
||||||
|
|||||||
182
SrcMod/Shell/Modules/ExtractionModule.cs
Normal file
182
SrcMod/Shell/Modules/ExtractionModule.cs
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
namespace SrcMod.Shell.Modules;
|
||||||
|
|
||||||
|
[Module("extract")]
|
||||||
|
public static class ExtractionModule
|
||||||
|
{
|
||||||
|
[Command("gz")]
|
||||||
|
[Command("gzip")]
|
||||||
|
public static void ExtractGZip(string source, string? destination = null)
|
||||||
|
{
|
||||||
|
if (!File.Exists(source)) throw new($"No file exists at \"{source}\".");
|
||||||
|
|
||||||
|
if (destination is null)
|
||||||
|
{
|
||||||
|
string full = Path.GetFullPath(source);
|
||||||
|
string folder = Program.Shell!.WorkingDirectory;
|
||||||
|
string name = Path.GetFileNameWithoutExtension(full);
|
||||||
|
|
||||||
|
destination = $"{folder}\\{name}";
|
||||||
|
}
|
||||||
|
|
||||||
|
string absSource = Path.GetFullPath(source),
|
||||||
|
localDest = Path.GetRelativePath(Program.Shell!.WorkingDirectory, destination);
|
||||||
|
|
||||||
|
if (File.Exists(destination)) throw new($"File already exists at \"{destination}\".");
|
||||||
|
string message = $"Extracting file at \"{source}\" into \"{localDest}\"...";
|
||||||
|
Write(message);
|
||||||
|
|
||||||
|
FileStream writer = new(destination, FileMode.CreateNew),
|
||||||
|
reader = new(absSource, FileMode.Open);
|
||||||
|
GZipStream gzip = new(reader, CompressionMode.Decompress);
|
||||||
|
|
||||||
|
gzip.CopyTo(writer);
|
||||||
|
|
||||||
|
gzip.Close();
|
||||||
|
reader.Close();
|
||||||
|
writer.Close();
|
||||||
|
|
||||||
|
Console.CursorLeft = 0;
|
||||||
|
Console.CursorTop -= (message.Length / Console.BufferWidth) + 1;
|
||||||
|
Write(new string(' ', message.Length), newLine: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("rar")]
|
||||||
|
public static void ExtractRar(string source, string? destination = null)
|
||||||
|
{
|
||||||
|
if (!File.Exists(source)) throw new($"No file exists at \"{source}\".");
|
||||||
|
|
||||||
|
if (destination is null)
|
||||||
|
{
|
||||||
|
string full = Path.GetFullPath(source);
|
||||||
|
string folder = Program.Shell!.WorkingDirectory;
|
||||||
|
string name = Path.GetFileNameWithoutExtension(full);
|
||||||
|
|
||||||
|
destination = $"{folder}\\{name}";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(destination)) Directory.CreateDirectory(destination);
|
||||||
|
|
||||||
|
FileStream reader = new(source, FileMode.Open);
|
||||||
|
RarArchive rar = RarArchive.Open(reader);
|
||||||
|
|
||||||
|
IReader data = rar.ExtractAllEntries();
|
||||||
|
data.WriteAllToDirectory(destination, new()
|
||||||
|
{
|
||||||
|
ExtractFullPath = true,
|
||||||
|
Overwrite = true,
|
||||||
|
PreserveFileTime = true
|
||||||
|
});
|
||||||
|
|
||||||
|
rar.Dispose();
|
||||||
|
reader.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("tar")]
|
||||||
|
[Command("tarball")]
|
||||||
|
public static void ExtractTar(string source, string? destination = null)
|
||||||
|
{
|
||||||
|
if (!File.Exists(source)) throw new($"No file exists at \"{source}\".");
|
||||||
|
|
||||||
|
if (destination is null)
|
||||||
|
{
|
||||||
|
string full = Path.GetFullPath(source);
|
||||||
|
string folder = Program.Shell!.WorkingDirectory;
|
||||||
|
string name = Path.GetFileNameWithoutExtension(full);
|
||||||
|
|
||||||
|
destination = $"{folder}\\{name}";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(destination)) Directory.CreateDirectory(destination);
|
||||||
|
|
||||||
|
FileStream reader = new(source, FileMode.Open);
|
||||||
|
TarFile.ExtractToDirectory(reader, Path.GetFileName(destination), true);
|
||||||
|
|
||||||
|
reader.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("targz")]
|
||||||
|
[Command("tar.gz")]
|
||||||
|
[Command("tar-gz")]
|
||||||
|
public static void ExtractTarGz(string source, string? destination = null)
|
||||||
|
{
|
||||||
|
if (!File.Exists(source)) throw new($"No file exists at \"{source}\".");
|
||||||
|
|
||||||
|
if (destination is null)
|
||||||
|
{
|
||||||
|
string full = Path.GetFullPath(source);
|
||||||
|
string folder = Program.Shell!.WorkingDirectory;
|
||||||
|
string name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(full));
|
||||||
|
|
||||||
|
destination = $"{folder}\\{name}";
|
||||||
|
}
|
||||||
|
|
||||||
|
string absSource = Path.GetFullPath(source),
|
||||||
|
temp = Path.Combine(Path.GetDirectoryName(absSource)!, Path.GetFileNameWithoutExtension(absSource));
|
||||||
|
|
||||||
|
ExtractGZip(source, temp);
|
||||||
|
ExtractTar(temp, destination);
|
||||||
|
|
||||||
|
File.Delete(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("zip")]
|
||||||
|
public static void ExtractZip(string source, string? destination = null)
|
||||||
|
{
|
||||||
|
if (!File.Exists(source)) throw new($"No file exists at \"{source}\".");
|
||||||
|
|
||||||
|
if (destination is null)
|
||||||
|
{
|
||||||
|
string full = Path.GetFullPath(source);
|
||||||
|
string folder = Program.Shell!.WorkingDirectory;
|
||||||
|
string name = Path.GetFileNameWithoutExtension(full);
|
||||||
|
|
||||||
|
destination = $"{folder}\\{name}";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(destination)) Directory.CreateDirectory(destination);
|
||||||
|
|
||||||
|
FileStream reader = new(source, FileMode.Open);
|
||||||
|
ZipArchive zip = new(reader, ZipArchiveMode.Read);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(zip.Comment)) Write(zip.Comment);
|
||||||
|
|
||||||
|
zip.ExtractToDirectory(destination, true);
|
||||||
|
|
||||||
|
zip.Dispose();
|
||||||
|
reader.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command("7z")]
|
||||||
|
[Command("7zip")]
|
||||||
|
[Command("sevenzip")]
|
||||||
|
public static void Extract7Zip(string source, string? destination = null)
|
||||||
|
{
|
||||||
|
if (!File.Exists(source)) throw new($"No file exists at \"{source}\".");
|
||||||
|
|
||||||
|
if (destination is null)
|
||||||
|
{
|
||||||
|
string full = Path.GetFullPath(source);
|
||||||
|
string folder = Program.Shell!.WorkingDirectory;
|
||||||
|
string name = Path.GetFileNameWithoutExtension(full);
|
||||||
|
|
||||||
|
destination = $"{folder}\\{name}";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(destination)) Directory.CreateDirectory(destination);
|
||||||
|
|
||||||
|
FileStream reader = new(source, FileMode.Open);
|
||||||
|
SevenZipArchive zip = SevenZipArchive.Open(reader);
|
||||||
|
|
||||||
|
IReader data = zip.ExtractAllEntries();
|
||||||
|
data.WriteAllToDirectory(destination, new()
|
||||||
|
{
|
||||||
|
ExtractFullPath = true,
|
||||||
|
Overwrite = true,
|
||||||
|
PreserveAttributes = true,
|
||||||
|
PreserveFileTime = true
|
||||||
|
});
|
||||||
|
|
||||||
|
zip.Dispose();
|
||||||
|
reader.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,7 +4,7 @@ public class Shell
|
|||||||
{
|
{
|
||||||
public const string Author = "That_One_Nerd";
|
public const string Author = "That_One_Nerd";
|
||||||
public const string Name = "SrcMod";
|
public const string Name = "SrcMod";
|
||||||
public const string Version = "Alpha 0.2.2";
|
public const string Version = "Alpha 0.3.0";
|
||||||
|
|
||||||
public readonly string? ShellDirectory;
|
public readonly string? ShellDirectory;
|
||||||
|
|
||||||
@ -170,10 +170,13 @@ public class Shell
|
|||||||
if (command.NameId.Trim().ToLower() != commandName) continue;
|
if (command.NameId.Trim().ToLower() != commandName) continue;
|
||||||
int start = module.NameIsPrefix ? 2 : 1;
|
int start = module.NameIsPrefix ? 2 : 1;
|
||||||
string[] args = parts.GetRange(start, parts.Count - start).ToArray();
|
string[] args = parts.GetRange(start, parts.Count - start).ToArray();
|
||||||
|
|
||||||
|
#if RELEASE
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
#endif
|
||||||
command.Invoke(args);
|
command.Invoke(args);
|
||||||
|
#if RELEASE
|
||||||
}
|
}
|
||||||
catch (TargetInvocationException ex)
|
catch (TargetInvocationException ex)
|
||||||
{
|
{
|
||||||
@ -185,6 +188,7 @@ public class Shell
|
|||||||
Write($"[ERROR] {ex.Message}", ConsoleColor.Red);
|
Write($"[ERROR] {ex.Message}", ConsoleColor.Red);
|
||||||
if (LoadingBarEnabled) LoadingBarEnd();
|
if (LoadingBarEnabled) LoadingBarEnd();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Nerd_STF" Version="2.3.2" />
|
<PackageReference Include="Nerd_STF" Version="2.3.2" />
|
||||||
|
<PackageReference Include="SharpCompress" Version="0.33.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user