Rework zip file updating.
This commit is contained in:
@@ -71,26 +71,13 @@ namespace OpenRA.FileSystem
|
|||||||
public IReadOnlyPackage OpenPackage(string filename, IReadOnlyPackage parent)
|
public IReadOnlyPackage OpenPackage(string filename, IReadOnlyPackage parent)
|
||||||
{
|
{
|
||||||
// HACK: limit support to zip and folder until we generalize the PackageLoader support
|
// HACK: limit support to zip and folder until we generalize the PackageLoader support
|
||||||
if (parent is Folder)
|
if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
var path = Path.Combine(parent.Name, filename);
|
using (var s = parent.GetStream(filename))
|
||||||
|
return new ZipFile(s, filename, parent);
|
||||||
// HACK: work around SharpZipLib's lack of support for writing to in-memory files
|
|
||||||
if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
return new ZipFile(this, path);
|
|
||||||
if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
return new ZipFile(this, path);
|
|
||||||
|
|
||||||
var subFolder = Platform.ResolvePath(path);
|
|
||||||
if (Directory.Exists(subFolder))
|
|
||||||
return new Folder(subFolder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
return new ZipFile(this, filename, parent.GetStream(filename));
|
|
||||||
if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
return new ZipFile(this, filename, parent.GetStream(filename));
|
|
||||||
|
|
||||||
if (parent is ZipFile)
|
if (parent is ZipFile)
|
||||||
return new ZipFolder(this, (ZipFile)parent, filename, filename);
|
return new ZipFolder(this, (ZipFile)parent, filename, filename);
|
||||||
|
|
||||||
@@ -100,19 +87,16 @@ namespace OpenRA.FileSystem
|
|||||||
return new ZipFolder(this, folder.Parent, folder.Name + "/" + filename, filename);
|
return new ZipFolder(this, folder.Parent, folder.Name + "/" + filename, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parent is Folder)
|
||||||
|
{
|
||||||
|
var subFolder = Platform.ResolvePath(Path.Combine(parent.Name, filename));
|
||||||
|
if (Directory.Exists(subFolder))
|
||||||
|
return new Folder(subFolder);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IReadWritePackage OpenWritablePackage(string filename)
|
|
||||||
{
|
|
||||||
if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
return new ZipFile(this, filename);
|
|
||||||
if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
return new ZipFile(this, filename);
|
|
||||||
|
|
||||||
return new Folder(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Mount(string name, string explicitName = null)
|
public void Mount(string name, string explicitName = null)
|
||||||
{
|
{
|
||||||
var optional = name.StartsWith("~");
|
var optional = name.StartsWith("~");
|
||||||
|
|||||||
@@ -9,8 +9,10 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using ICSharpCode.SharpZipLib.Zip;
|
using ICSharpCode.SharpZipLib.Zip;
|
||||||
using SZipFile = ICSharpCode.SharpZipLib.Zip.ZipFile;
|
using SZipFile = ICSharpCode.SharpZipLib.Zip.ZipFile;
|
||||||
@@ -19,32 +21,60 @@ namespace OpenRA.FileSystem
|
|||||||
{
|
{
|
||||||
public sealed class ZipFile : IReadWritePackage
|
public sealed class ZipFile : IReadWritePackage
|
||||||
{
|
{
|
||||||
|
public IReadWritePackage Parent { get; private set; }
|
||||||
public string Name { get; private set; }
|
public string Name { get; private set; }
|
||||||
SZipFile pkg;
|
readonly Stream pkgStream;
|
||||||
|
readonly SZipFile pkg;
|
||||||
|
|
||||||
static ZipFile()
|
static ZipFile()
|
||||||
{
|
{
|
||||||
ZipConstants.DefaultCodePage = Encoding.UTF8.CodePage;
|
ZipConstants.DefaultCodePage = Encoding.UTF8.CodePage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ZipFile(FileSystem context, string filename, Stream stream, bool createOrClearContents = false)
|
public ZipFile(Stream stream, string name, IReadOnlyPackage parent = null)
|
||||||
{
|
{
|
||||||
Name = filename;
|
// SharpZipLib breaks when asked to update archives loaded from outside streams or files
|
||||||
|
// We can work around this by creating a clean in-memory-only file, cutting all outside references
|
||||||
|
pkgStream = new MemoryStream();
|
||||||
|
stream.CopyTo(pkgStream);
|
||||||
|
pkgStream.Position = 0;
|
||||||
|
|
||||||
if (createOrClearContents)
|
Name = name;
|
||||||
pkg = SZipFile.Create(stream);
|
Parent = parent as IReadWritePackage;
|
||||||
else
|
pkg = new SZipFile(pkgStream);
|
||||||
pkg = new SZipFile(stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ZipFile(IReadOnlyFileSystem context, string filename, bool createOrClearContents = false)
|
public ZipFile(IReadOnlyFileSystem context, string filename)
|
||||||
{
|
{
|
||||||
Name = filename;
|
string name;
|
||||||
|
IReadOnlyPackage p;
|
||||||
|
if (!context.TryGetPackageContaining(filename, out p, out name))
|
||||||
|
throw new FileNotFoundException("Unable to find parent package for " + filename);
|
||||||
|
|
||||||
if (createOrClearContents)
|
Name = name;
|
||||||
pkg = SZipFile.Create(filename);
|
Parent = p as IReadWritePackage;
|
||||||
else
|
|
||||||
pkg = new SZipFile(filename);
|
// SharpZipLib breaks when asked to update archives loaded from outside streams or files
|
||||||
|
// We can work around this by creating a clean in-memory-only file, cutting all outside references
|
||||||
|
pkgStream = new MemoryStream();
|
||||||
|
p.GetStream(name).CopyTo(pkgStream);
|
||||||
|
pkgStream.Position = 0;
|
||||||
|
|
||||||
|
pkg = new SZipFile(pkgStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZipFile(string filename, IReadWritePackage parent)
|
||||||
|
{
|
||||||
|
pkgStream = new MemoryStream();
|
||||||
|
|
||||||
|
Name = filename;
|
||||||
|
Parent = parent;
|
||||||
|
pkg = SZipFile.Create(pkgStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ZipFile Create(string filename, IReadWritePackage parent)
|
||||||
|
{
|
||||||
|
return new ZipFile(filename, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream GetStream(string filename)
|
public Stream GetStream(string filename)
|
||||||
@@ -76,11 +106,23 @@ namespace OpenRA.FileSystem
|
|||||||
return pkg.GetEntry(filename) != null;
|
return pkg.GetEntry(filename) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Commit()
|
||||||
|
{
|
||||||
|
if (Parent == null)
|
||||||
|
throw new InvalidDataException("Cannot update ZipFile without writable parent");
|
||||||
|
|
||||||
|
var pos = pkgStream.Position;
|
||||||
|
pkgStream.Position = 0;
|
||||||
|
Parent.Update(Name, pkgStream.ReadBytes((int)pkgStream.Length));
|
||||||
|
pkgStream.Position = pos;
|
||||||
|
}
|
||||||
|
|
||||||
public void Update(string filename, byte[] contents)
|
public void Update(string filename, byte[] contents)
|
||||||
{
|
{
|
||||||
pkg.BeginUpdate();
|
pkg.BeginUpdate();
|
||||||
pkg.Add(new StaticMemoryDataSource(contents), filename);
|
pkg.Add(new StaticStreamDataSource(new MemoryStream(contents)), filename);
|
||||||
pkg.CommitUpdate();
|
pkg.CommitUpdate();
|
||||||
|
Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Delete(string filename)
|
public void Delete(string filename)
|
||||||
@@ -88,6 +130,7 @@ namespace OpenRA.FileSystem
|
|||||||
pkg.BeginUpdate();
|
pkg.BeginUpdate();
|
||||||
pkg.Delete(filename);
|
pkg.Delete(filename);
|
||||||
pkg.CommitUpdate();
|
pkg.CommitUpdate();
|
||||||
|
Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@@ -97,17 +140,17 @@ namespace OpenRA.FileSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StaticMemoryDataSource : IStaticDataSource
|
class StaticStreamDataSource : IStaticDataSource
|
||||||
{
|
{
|
||||||
byte[] data;
|
readonly Stream s;
|
||||||
public StaticMemoryDataSource(byte[] data)
|
public StaticStreamDataSource(Stream s)
|
||||||
{
|
{
|
||||||
this.data = data;
|
this.s = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream GetSource()
|
public Stream GetSource()
|
||||||
{
|
{
|
||||||
return new MemoryStream(data);
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
package = new ZipFile(null, pair.Second);
|
package = new ZipFile(File.OpenRead(pair.Second), pair.Second);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -105,9 +105,8 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
Map.FixOpenAreas();
|
Map.FixOpenAreas();
|
||||||
|
|
||||||
var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";
|
var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";
|
||||||
var package = new ZipFile(modData.ModFiles, dest, true);
|
|
||||||
|
|
||||||
Map.Save(package);
|
Map.Save(ZipFile.Create(dest, new Folder(".")));
|
||||||
Console.WriteLine(dest + " saved.");
|
Console.WriteLine(dest + " saved.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,8 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
// HACK: The engine code assumes that Game.modData is set.
|
// HACK: The engine code assumes that Game.modData is set.
|
||||||
Game.ModData = modData;
|
Game.ModData = modData;
|
||||||
|
|
||||||
var package = modData.ModFiles.OpenWritablePackage(args[1]);
|
// HACK: We know that maps can only be oramap or folders, which are ReadWrite
|
||||||
|
var package = modData.ModFiles.OpenPackage(args[1], new Folder(".")) as IReadWritePackage;
|
||||||
var engineDate = Exts.ParseIntegerInvariant(args[2]);
|
var engineDate = Exts.ParseIntegerInvariant(args[2]);
|
||||||
UpgradeMap(modData, package, engineDate);
|
UpgradeMap(modData, package, engineDate);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
selectedDirectory.Folder.Delete(combinedPath);
|
selectedDirectory.Folder.Delete(combinedPath);
|
||||||
if (fileType == MapFileType.OraMap)
|
if (fileType == MapFileType.OraMap)
|
||||||
package = new ZipFile(modData.DefaultFileSystem, combinedPath, true);
|
package = ZipFile.Create(combinedPath, selectedDirectory.Folder);
|
||||||
else
|
else
|
||||||
package = new Folder(combinedPath);
|
package = new Folder(combinedPath);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,7 @@ namespace OpenRA.Mods.D2k.UtilityCommands
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";
|
var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";
|
||||||
var package = new ZipFile(modData.DefaultFileSystem, dest, true);
|
map.Save(ZipFile.Create(dest, new Folder(".")));
|
||||||
map.Save(package);
|
|
||||||
Console.WriteLine(dest + " saved.");
|
Console.WriteLine(dest + " saved.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,8 +186,7 @@ namespace OpenRA.Mods.TS.UtilityCommands
|
|||||||
map.PlayerDefinitions = mapPlayers.ToMiniYaml();
|
map.PlayerDefinitions = mapPlayers.ToMiniYaml();
|
||||||
|
|
||||||
var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";
|
var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";
|
||||||
var package = new ZipFile(modData.DefaultFileSystem, dest, true);
|
map.Save(ZipFile.Create(dest, new Folder(".")));
|
||||||
map.Save(package);
|
|
||||||
Console.WriteLine(dest + " saved.");
|
Console.WriteLine(dest + " saved.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user