Ticket #1940: vfs-mod-write.patch

File vfs-mod-write.patch, 8.0 KB (added by leper, 11 years ago)

Dev implies -noUserMod. Exclude dev.cfg from release packaging. Updated to work properly with mods present in both mod folders

  • source/lib/file/vfs/vfs.cpp

     
    132132    {
    133133        ScopedLock s;
    134134        VfsDirectory* directory;
    135         WARN_RETURN_STATUS_IF_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, 0, VFS_LOOKUP_ADD|VFS_LOOKUP_CREATE));
     135        WARN_RETURN_STATUS_IF_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, 0, VFS_LOOKUP_ADD|VFS_LOOKUP_CREATE|VFS_LOOKUP_CREATE_ALWAYS));
    136136
    137137        const PRealDirectory& realDirectory = directory->AssociatedDirectory();
    138138        const OsPath name = pathname.Filename();
  • source/lib/file/vfs/vfs.h

     
    6565     * ".DELETED" suffix will still apply.
    6666     * (the default behavior is to hide both the suffixed and unsuffixed files)
    6767     **/
    68     VFS_MOUNT_KEEP_DELETED = 8
     68    VFS_MOUNT_KEEP_DELETED = 8,
     69
     70    /**
     71     * mark a directory replaceable, so that when writing a file to this path
     72     * new real directories will be created instead of reusing already existing
     73     * ones mounted at a subpath of the VFS path.
     74     * (the default behaviour is to write to the real directory associated
     75     * with the VFS directory that was last mounted to this path (or subpath))
     76     **/
     77    VFS_MOUNT_REPLACEABLE = 16
    6978};
    7079
    7180// (member functions are thread-safe after the instance has been
  • source/lib/file/vfs/vfs_lookup.cpp

     
    1 /* Copyright (c) 2010 Wildfire Games
     1/* Copyright (c) 2013 Wildfire Games
    22 *
    33 * Permission is hereby granted, free of charge, to any person obtaining
    44 * a copy of this software and associated documentation files (the
     
    7474    const bool addMissingDirectories    = (flags & VFS_LOOKUP_ADD) != 0;
    7575    const bool createMissingDirectories = (flags & VFS_LOOKUP_CREATE) != 0;
    7676    const bool skipPopulate = (flags & VFS_LOOKUP_SKIP_POPULATE) != 0;
    77     ENSURE((flags & ~(VFS_LOOKUP_ADD|VFS_LOOKUP_CREATE|VFS_LOOKUP_SKIP_POPULATE)) == 0);
     77    const bool createAlways = (flags & VFS_LOOKUP_CREATE_ALWAYS) != 0;
     78    ENSURE((flags & ~(VFS_LOOKUP_ADD|VFS_LOOKUP_CREATE|VFS_LOOKUP_SKIP_POPULATE|VFS_LOOKUP_CREATE_ALWAYS)) == 0);
    7879
    7980    directory = startDirectory;
    8081    if(pfile)
     
    111112                return ERR::VFS_DIR_NOT_FOUND;  // NOWARN
    112113        }
    113114
    114         if(createMissingDirectories && !subdirectory->AssociatedDirectory())
     115        if(createMissingDirectories && (!subdirectory->AssociatedDirectory()
     116             || (createAlways && (subdirectory->AssociatedDirectory()->Flags() & VFS_MOUNT_REPLACEABLE) != 0)))
    115117        {
    116118            OsPath currentPath;
    117119            if(directory->AssociatedDirectory())    // (is NULL when mounting into root)
  • source/lib/file/vfs/vfs_lookup.h

     
    1 /* Copyright (c) 2010 Wildfire Games
     1/* Copyright (c) 2013 Wildfire Games
    22 *
    33 * Permission is hereby granted, free of charge, to any person obtaining
    44 * a copy of this software and associated documentation files (the
     
    4949    // don't populate the directories encountered. this makes sense
    5050    // when adding files from an archive, which would otherwise
    5151    // cause nearly every directory to be populated.
    52     VFS_LOOKUP_SKIP_POPULATE = 4
     52    VFS_LOOKUP_SKIP_POPULATE = 4,
     53
     54    // even create directories if they are already present, this is
     55    // useful to write new files to the directory that was attached
     56    // last, if the directory wasn't mounted with VFS_MOUNT_REPLACEABLE
     57    VFS_LOOKUP_CREATE_ALWAYS = 8
    5358};
    5459
    5560/**
  • source/ps/GameSetup/GameSetup.cpp

     
    421421    return ERI_NOT_IMPLEMENTED;
    422422}
    423423
     424static std::vector<CStr> GetMods(const CmdLineArgs& args, bool dev)
     425{
     426    std::vector<CStr> mods = args.GetMultiple("mod");
     427    // TODO: It would be nice to remove this hard-coding
     428    mods.insert(mods.begin(), "public");
     429
     430    // Add the user mod if not explicitly disabled or we have a dev copy so
     431    // that saved files end up in version control and not in the user mod.
     432    if (!dev && !args.Has("noUserMod"))
     433        mods.push_back("user");
     434
     435    return mods;
     436}
     437
    424438static void InitVfs(const CmdLineArgs& args)
    425439{
    426440    TIMER(L"InitVfs");
     
    441455
    442456    const size_t cacheSize = ChooseCacheSize();
    443457    g_VFS = CreateVfs(cacheSize);
     458   
     459    // Work out whether we are a dev version to make sure saved files
     460    // (maps, etc) end up in version control.
     461    const OsPath readonlyConfig = paths.RData()/"config"/"";
     462    g_VFS->Mount(L"config/", readonlyConfig);
     463    bool dev = (g_VFS->GetFileInfo(L"config/dev.cfg", NULL) == INFO::OK);
    444464
    445     std::vector<CStr> mods = args.GetMultiple("mod");
    446     mods.insert(mods.begin(), "public");
    447 
    448     if (!args.Has("noUserMod"))
    449         mods.push_back("user");
     465    std::vector<CStr> mods = GetMods(args, dev);
    450466
    451467    OsPath modPath = paths.RData()/"mods";
    452468    OsPath modUserPath = paths.UserData()/"mods";
    453469    for (size_t i = 0; i < mods.size(); ++i)
    454470    {
    455         size_t priority = i+1;  // mods are higher priority than regular mountings, which default to priority 0
    456         size_t flags = VFS_MOUNT_WATCH|VFS_MOUNT_ARCHIVABLE|VFS_MOUNT_MUST_EXIST;
     471        size_t priority = (i+1)*2;  // mods are higher priority than regular mountings, which default to priority 0
     472        size_t userFlags = VFS_MOUNT_WATCH|VFS_MOUNT_ARCHIVABLE|VFS_MOUNT_REPLACEABLE;
     473        size_t flags = userFlags|VFS_MOUNT_MUST_EXIST;
     474       
    457475        OsPath modName(mods[i]);
    458         g_VFS->Mount(L"", modPath / modName/"", flags, priority);
    459         g_VFS->Mount(L"", modUserPath / modName/"", flags, priority);
     476        if (dev)
     477        {
     478            // We are running a dev copy, so only mount mods in the user mod path
     479            // if the mod does not exist in the data path.
     480            if (DirectoryExists(modPath / modName/""))
     481                g_VFS->Mount(L"", modPath / modName/"", flags, priority);
     482            else
     483                g_VFS->Mount(L"", modUserPath / modName/"", userFlags, priority);
     484        }
     485        else
     486        {
     487            g_VFS->Mount(L"", modPath / modName/"", flags, priority);
     488            // Ensure that user modified files are loaded, if they are present
     489            g_VFS->Mount(L"", modUserPath / modName/"", userFlags, priority+1);
     490        }
    460491    }
    461492
    462493    // We mount these dirs last as otherwise writing could result in files being placed in a mod's dir.
    463494    g_VFS->Mount(L"screenshots/", paths.UserData()/"screenshots"/"");
    464495    g_VFS->Mount(L"saves/", paths.UserData()/"saves"/"", VFS_MOUNT_WATCH);
    465     const OsPath readonlyConfig = paths.RData()/"config"/"";
    466496    // Mounting with highest priority, so that a mod supplied user.cfg is harmless
    467497    g_VFS->Mount(L"config/", readonlyConfig, 0, (size_t)-1);
    468498    if(readonlyConfig != paths.Config())
     
    889919
    890920    // g_ConfigDB, command line args, globals
    891921    CONFIG_Init(args);
    892    
     922
    893923    // before scripting
    894924    if (g_JSDebuggerEnabled)
    895925        g_DebuggingServer = new CDebuggingServer();
    896926
    897927    InitScripting();    // before GUI
    898    
     928
    899929    g_ConfigDB.RegisterJSConfigDB();    // after scripting
    900930
    901931    // Optionally start profiler HTTP output automatically
  • source/tools/dist/build.sh

     
    3939    --exclude='libraries/source/fcollada/src/FCollada/FColladaTest' \
    4040    --exclude='libraries/source/spidermonkey/include-win32' \
    4141    ${PREFIX}/{source,build,libraries/source,binaries/system/readme.txt,binaries/data/tests,binaries/data/mods/_test.*,*.txt}
    42 tar cf $PREFIX-unix-data.tar ${PREFIX}/binaries/data/{config,mods/public/public.zip,tools}
     42tar cf $PREFIX-unix-data.tar \
     43    --exclude='binaries/data/config/dev.cfg' \
     44     ${PREFIX}/binaries/data/{config,mods/public/public.zip,tools}
    4345# TODO: ought to include generated docs in here, perhaps?
    4446
    4547# Compress