1
0
forked from 0ad/0ad

add support for removing individual files from VFS and a mechanism for automatically doing so (add filename.extension.DELETED to the same directory/archive), as discussed in meeting.

refactor: split up Invalidate into RemoveFile+RepopulateDirectory
GameSetup: fix: ensure the first mod always overrides game files,
irrespective of timestamp.

This was SVN commit r10610.
This commit is contained in:
janwas 2011-11-26 18:37:53 +00:00
parent d82b85b8f3
commit 301854702c
8 changed files with 66 additions and 20 deletions

View File

@ -224,15 +224,25 @@ public:
return INFO::OK;
}
virtual Status Invalidate(const VfsPath& pathname)
virtual Status RemoveFile(const VfsPath& pathname)
{
ScopedLock s;
m_fileCache.Remove(pathname);
VfsDirectory* directory; VfsFile* file;
RETURN_STATUS_IF_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, &file));
directory->RemoveFile(file->Name());
return INFO::OK;
}
virtual Status RepopulateDirectory(const VfsPath& path)
{
ScopedLock s;
VfsDirectory* directory;
RETURN_STATUS_IF_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, 0));
const OsPath name = pathname.Filename();
directory->Invalidate(name);
RETURN_STATUS_IF_ERR(vfs_Lookup(path, &m_rootDirectory, directory, 0));
directory->RequestRepopulate();
return INFO::OK;
}

View File

@ -172,12 +172,19 @@ struct IVFS
* directories below a mount point with a matching real path.
**/
virtual Status GetVirtualPath(const OsPath& realPathname, VfsPath& pathname) = 0;
/**
* indicate that a file has changed; remove its data from the cache and
* arrange for its directory to be updated.
* remove file from the virtual directory listing and evict its
* data from the cache.
**/
virtual Status Invalidate(const VfsPath& pathname) = 0;
virtual Status RemoveFile(const VfsPath& pathname) = 0;
/**
* request the directory be re-populated when it is next accessed.
* useful for synchronizing with the underlying filesystem after
* files have been created or their metadata changed.
**/
virtual Status RepopulateDirectory(const VfsPath& path) = 0;
/**
* empty the contents of the filesystem.

View File

@ -69,7 +69,14 @@ public:
private:
void AddFile(const FileInfo& fileInfo) const
{
const VfsFile file(fileInfo.Name(), (size_t)fileInfo.Size(), fileInfo.MTime(), m_realDirectory->Priority(), m_realDirectory);
const VfsPath name = fileInfo.Name();
if(name.Extension() == L".DELETED")
{
m_directory->RemoveFile(name.Basename());
return;
}
const VfsFile file(name, (size_t)fileInfo.Size(), fileInfo.MTime(), m_realDirectory->Priority(), m_realDirectory);
const VfsFile* pfile = m_directory->AddFile(file);
#if ENABLE_ARCHIVE_STATS
@ -94,7 +101,15 @@ private:
const size_t flags = VFS_LOOKUP_ADD|VFS_LOOKUP_SKIP_POPULATE;
VfsDirectory* directory;
WARN_IF_ERR(vfs_Lookup(pathname, this_->m_directory, directory, 0, flags));
const VfsFile file(fileInfo.Name(), (size_t)fileInfo.Size(), fileInfo.MTime(), this_->m_realDirectory->Priority(), archiveFile);
const VfsPath name = fileInfo.Name();
if(name.Extension() == L".DELETED")
{
directory->RemoveFile(name.Basename());
return;
}
const VfsFile file(name, (size_t)fileInfo.Size(), fileInfo.MTime(), this_->m_realDirectory->Priority(), archiveFile);
directory->AddFile(file);
#if ENABLE_ARCHIVE_STATS
s_numArchivedFiles++;

View File

@ -106,6 +106,12 @@ VfsDirectory* VfsDirectory::AddSubdirectory(const VfsPath& name)
}
void VfsDirectory::RemoveFile(const VfsPath& name)
{
m_files.erase(name.string());
}
VfsFile* VfsDirectory::GetFile(const VfsPath& name)
{
VfsFiles::iterator it = m_files.find(name.string());
@ -138,9 +144,8 @@ bool VfsDirectory::ShouldPopulate()
}
void VfsDirectory::Invalidate(const VfsPath& name)
void VfsDirectory::RequestRepopulate()
{
m_files.erase(name.string());
m_shouldPopulate = 1;
}

View File

@ -93,6 +93,12 @@ public:
**/
VfsDirectory* AddSubdirectory(const VfsPath& name);
/**
* remove the given file from the virtual directory (no effect on
* the physical file). no effect if the file does not exist.
**/
void RemoveFile(const VfsPath& name);
/**
* @return file with the given name.
* (note: non-const to allow changes to the file)
@ -135,10 +141,9 @@ public:
bool ShouldPopulate();
/**
* indicate that a file has changed; ensure its new version supersedes
* the old by removing it and marking the directory for re-population.
* ensure the next ShouldPopulate returns true.
**/
void Invalidate(const VfsPath& name);
void RequestRepopulate();
/**
* empty file and subdirectory lists (e.g. when rebuilding VFS).

View File

@ -78,7 +78,8 @@ Status ReloadChangedFiles()
{
VfsPath pathname;
RETURN_STATUS_IF_ERR(g_VFS->GetVirtualPath(notifications[i].Pathname(), pathname));
RETURN_STATUS_IF_ERR(g_VFS->Invalidate(pathname));
RETURN_STATUS_IF_ERR(g_VFS->RemoveFile(pathname));
RETURN_STATUS_IF_ERR(g_VFS->RepopulateDirectory(pathname.Parent()));
// Tell each hotloadable system about this file change:

View File

@ -459,7 +459,7 @@ static void InitVfs(const CmdLineArgs& args)
OsPath modLoosePath = paths.RData()/"mods";
for (size_t i = 0; i < mods.size(); ++i)
{
size_t priority = i;
size_t priority = i+1; // mods are higher priority than regular mountings, which default to priority 0
size_t flags = VFS_MOUNT_WATCH|VFS_MOUNT_ARCHIVABLE|VFS_MOUNT_MUST_EXIST;
OsPath modName(mods[i]);
g_VFS->Mount(L"", modLoosePath / modName/"", flags, priority);

View File

@ -133,7 +133,8 @@ public:
TS_ASSERT_OK(CreateDirectories(DataDir()/"mods"/"_test.sim"/"simulation"/"components"/"hotload"/"", 0700));
copyFile(L"simulation/components/test-hotload1.js", L"simulation/components/hotload/hotload.js");
TS_ASSERT_OK(g_VFS->Invalidate(L"simulation/components/hotload/hotload.js"));
TS_ASSERT_OK(g_VFS->RemoveFile(L"simulation/components/hotload/hotload.js"));
TS_ASSERT_OK(g_VFS->RepopulateDirectory(L"simulation/components/hotload/"));
TS_ASSERT(sim.LoadScripts(L"simulation/components/hotload/"));
sim.ResetState(true, true);
@ -143,7 +144,8 @@ public:
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (sim.QueryInterface(ent, IID_Test1))->GetX(), 100);
copyFile(L"simulation/components/test-hotload2.js", L"simulation/components/hotload/hotload.js");
TS_ASSERT_OK(g_VFS->Invalidate(L"simulation/components/hotload/hotload.js"));
TS_ASSERT_OK(g_VFS->RemoveFile(L"simulation/components/hotload/hotload.js"));
TS_ASSERT_OK(g_VFS->RepopulateDirectory(L"simulation/components/hotload/"));
TS_ASSERT_OK(sim.ReloadChangedFile(L"art/irrelevant.xml"));
TS_ASSERT_OK(sim.ReloadChangedFile(L"simulation/components/irrelevant.js"));
@ -156,7 +158,8 @@ public:
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (sim.QueryInterface(ent, IID_Test1))->GetX(), 1000);
TS_ASSERT_OK(DeleteDirectory(DataDir()/"mods"/"_test.sim"/"simulation"/"components"/"hotload"/""));
TS_ASSERT_OK(g_VFS->Invalidate(L"simulation/components/hotload/hotload.js"));
TS_ASSERT_OK(g_VFS->RemoveFile(L"simulation/components/hotload/hotload.js"));
TS_ASSERT_OK(g_VFS->RepopulateDirectory(L"simulation/components/hotload/"));
TS_ASSERT_OK(sim.ReloadChangedFile(L"simulation/components/hotload/hotload.js"));
}