Ejemplo n.º 1
0
bool P4Command::MapToLocal(P4Task& task, VersionedAssetList& assets)
{
    const vector<Mapping>& mappings = GetMappings(task, assets);
    if (mappings.size() != assets.size())
        return false; // error

    vector<Mapping>::const_iterator m = mappings.begin();
    for (VersionedAssetList::iterator i = assets.begin(); i != assets.end(); ++i, ++m)
    {
        i->SetPath(m->clientPath);
    }
    return true;
}
    virtual bool Run(P4Task& task, const CommandArgs& args)
    {
        ClearStatus();
        Conn().Log().Info() << args[0] << "::Run()" << Endl;
        
        bool noLocalFileMove = args.size() > 1 && args[1] == "noLocalFileMove";

        VersionedAssetList assetList;
        Conn() >> assetList;
        
        if ( assetList.empty() ) 
        {
            Conn().EndResponse();
            return true;
        }
        
        // Process two assets at a time ie. src,dest
        if ( assetList.size() % 2 ) 
        {
            Conn().WarnLine("uneven number of assets during move", MASystem);
            Conn().EndResponse();
            return true;
        }

        VersionedAssetList::const_iterator b = assetList.begin();
        VersionedAssetList::const_iterator e = b;
        
        // Split into two steps. 1st make everything editable and 2nd do the move.
        // this makes changes more atomic.
        while (b != assetList.end())
        {
            e += 2;
            const VersionedAsset& src = *b;
            
            string paths = ResolvePaths(b, e, kPathWild | kPathRecursive);
            
            Conn().Log().Debug() << "Ensure editable source " << paths << Endl;
            
            string err;
            bool editable = (src.GetState() & (kCheckedOutLocal | kAddedLocal | kLockedLocal)) != 0;
            
            if (!editable)
            {
                string srcPath = ResolvePaths(b, b+1, kPathWild | kPathRecursive);
                Conn().Log().Info() << "edit " << srcPath << Endl;
                if (!task.CommandRun("edit " + srcPath, this))
                {
                    break;
                }
            }
            b = e;
        }

        b = assetList.begin();
        e = b;

        VersionedAssetList targetAssetList;
        string noLocalFileMoveFlag = noLocalFileMove ? " -k " : "";
        while (!HasErrors() && b != assetList.end())
        {
            e += 2;
            
            const VersionedAsset& src = *b;
            const VersionedAsset& dest = *(b+1);

            targetAssetList.push_back(dest);
            
            string paths = ResolvePaths(b, e, kPathWild | kPathRecursive);
            
            Conn().Log().Info() << "move " << noLocalFileMoveFlag << paths << Endl;
            if (!task.CommandRun("move " + noLocalFileMoveFlag + paths, this))
            {
                break;
            }
            
            // Make the actual file system move if perforce didn't do it ie. in
            // the case of an empty folder rename or a non versioned asset/folder move/rename
            if (!PathExists(dest.GetPath()))
            {
                // Move the file
                if (!MoveAFile(src.GetPath(), dest.GetPath()))
                {
                    string errorMessage = "Error moving file ";
                    errorMessage += src.GetPath();
                    errorMessage += " to ";
                    errorMessage += dest.GetPath();
                    Conn().WarnLine(errorMessage);
                }
            }

            // Delete move folder src since perforce leaves around empty folders.
            // This only works because unity will not send embedded moves.
            if (src.IsFolder() && IsDirectory(src.GetPath()))
            {
                DeleteRecursive(src.GetPath());
            }

            b = e;
        }
        
        // We just wrap up the communication here.
        Conn() << GetStatus();
        
        RunAndSendStatus(task, targetAssetList);
        
        Conn().EndResponse();

        return true;
    }