public bool CopyFrom(Stream input, bool updateOnly)
{
if (mode == FileMode.Open)
throw new InvalidOperationException("Cannot write into data file retrieved using the FileMode.Open mode.");
// Non-data files such as plugin.txt do not have a request path relative to the data folder
// TODO: Do not provide non-data files via DataFileProvider
if (RequestedPath == null)
throw new InvalidOperationException("Cannot write into a special data file.");
if (updateOnly)
{
// Look if file already exists
// To check whether it needs to be updated
// Retreive new file from the provider with FileMode.Open
var existingFile = provider.GetDataFile(FileMode.Open, RequestedPath);
if (existingFile.Exists())
{
using (var existingStream = existingFile.Open())
{
// If input is not memory stream, create one and copy the data from the input stream into it
MemoryStream memoryStream = input as MemoryStream;
if (memoryStream == null)
{
// Initialize memory stream as big as the existing stream length if imput steam is not seekable
int initialMemoryStreamLength = input.CanSeek ? (int)input.Length : (int)existingStream.Length;
memoryStream = new MemoryStream(initialMemoryStreamLength);
input.CopyTo(memoryStream);
memoryStream.Position = 0;
}
// Compare existing stream with input stream (or memory stream where input stream was copied into)
if (StreamComparer.Compare(existingStream, memoryStream))
{
Log.Fine("Cached file {0} is up to date.", existingFile.FullPath);
return false;
}
// Reset memeory stream after comparison
memoryStream.Position = 0;
// Use memory stream (where input stream has been copied into) instead of input stream
// when updating existing file
if (input != memoryStream)
input = memoryStream;
Log.Fine("Cached file {0} exists but is no longer valid and will be updated.", existingFile.FullPath);
}
}
else
{
Log.Fine("File {0} is not cached and will be created.", existingFile.FullPath);
}
}
using (var newStream = Open())
{
input.CopyTo(newStream);
}
return true;
}