virtual bool Run(P4Task& task, const CommandArgs& args)
	{
		if (!task.IsConnected()) // Cannot login without being connected
		{
			Conn().Log().Info() << "Cannot login when not connected" << Endl;
			return false;
		}
		
		ClearStatus();
		
		m_LoggedIn = false;
		m_Password = task.GetP4Password();
		m_CheckingForLoggedIn = args.size() > 1;
		const string cmd = string("login") + (m_CheckingForLoggedIn ? string(" " ) + args[1] : string());

		if (!task.CommandRun(cmd, this) && !m_CheckingForLoggedIn)
		{
			string errorMessage = GetStatusMessage();			
			Conn().Log().Notice() << "ERROR: " << errorMessage << Endl;
		}
		
		if (m_CheckingForLoggedIn)
			Conn().Log().Debug() << "Is logged in: " << (m_LoggedIn ? "yes" : "no") << Endl;
		else
			Conn().Log().Info() << "Login " << (m_LoggedIn ? "succeeded" : "failed") << Endl;

		m_CheckingForLoggedIn = false;
		return m_LoggedIn;
	}
	virtual bool Run(P4Task& task, const CommandArgs& args)
	{
		ClearStatus();
		m_ProjectPath = task.GetP4Root();
		
		ChangelistRevision cl;
		upipe >> cl;
		
		upipe.BeginList();
		
		vector<string> toks;
		if (Tokenize(toks, m_ProjectPath, "/") == 0)
		{
			upipe.ErrorLine(string("Project path invalid - ") + m_ProjectPath);
			upipe.EndList();
			upipe.ErrorLine("Invalid project path", MARemote);
			upipe.EndResponse();
			return true;
		}
		
		upipe.Log() << "Project path is " << m_ProjectPath << endl;
		
		string rev = cl == kDefaultListRevision ? string("default") : cl;
		const std::string cmd = string("describe -s ") + rev;
		
		task.CommandRun(cmd, this);
		
		// The OutputState and other callbacks will now output to stdout.
		// We just wrap up the communication here.
		upipe.EndList();
		upipe << GetStatus();
		upipe.EndResponse();
		
		return true;
	}
	virtual bool Run(P4Task& task, const CommandArgs& args)
	{				
		ClearStatus();
		Conn().Log().Info() << args[0] << "::Run()" << Endl;
		const string cmd = string("changes -s pending -u ") + Quote(task.GetP4User()) + " -c " + Quote(task.GetP4Client());

		Conn().BeginList();
		
		// The default list is always there
		Changelist defaultItem;
		const char * kDefaultList = "default";		
		defaultItem.SetDescription(kDefaultList);
		defaultItem.SetRevision(kDefaultListRevision);
		
		Conn() << defaultItem;
		
		task.CommandRun(cmd, this);
		Conn().EndList();
		Conn() << GetStatus();

		// The OutputState and other callbacks will now output to stdout.
		// We just wrap up the communication here.
		Conn().EndResponse();
		
		return true;
	}
	virtual bool Run(P4Task& task, const CommandArgs& args)
	{		
		// Old version used "changes -l -s submitted ...#>have" but that does not include submitted
		// changelist only containing files not already synced to current workspace ie. newly added
		// files from another client.
		// Instead do as the p4v tool does:
		// Run a fstat on entire workspace and get headChange for all files. This will give the
		// most recent changelist available.
		// On the same fstate get the headRev and haveRev revision for each file. If they are not equal 
		// then record the changelist id. 
		ClearStatus();
		m_Changelists.clear();

		Conn().Log().Info() << args[0] << "::Run()" << Endl;
		
		// const std::string cmd = string("fstat -T \"depotFile headChange haveRev headRev headAction action\" //depot/...");
		string rootPathWildcard = TrimEnd(TrimEnd(task.GetProjectPath(), '/'), '\\') + "/...";
		const std::string cmd = string("fstat -T \"depotFile headChange haveRev headRev headAction action\" \"") + rootPathWildcard + "\"";
		
		Conn().BeginList();
		
		if (!task.CommandRun(cmd, this))
		{
			// The OutputStat and other callbacks will now output to stdout.
			// We just wrap up the communication here.
			m_Changelists.clear();
			Conn().EndList();
			Conn() << GetStatus();
			Conn().EndResponse();
			return true;
		}
		
		// Fetch the descriptions for the incoming changelists.
		// @TODO: could save some roundtrips by make only one changes call for each sequence of 
		//        changelist ids.
		stringstream ss;
		for (set<int>::const_iterator i = m_Changelists.begin(); i != m_Changelists.end(); ++i) 
		{
			ss.str("");
			ss << "changes -l -s submitted \"@" << *i << ",@" << *i << "\"";
			Conn().Log().Info() << "    " << ss.str() << Endl;
			
			if (!task.CommandRun(ss.str(), this))
			{
				break;
			}
		}
		
		m_Changelists.clear();
		
		// The OutputState and other callbacks will now output to stdout.
		// We just wrap up the communication here.
		Conn().EndList();
		Conn() << GetStatus();
		Conn().EndResponse();
		
		return true;
	}
bool P4FileSetBaseCommand::Run(P4Task& task, const CommandArgs& args)
{
    ClearStatus();
    Conn().Log().Info() << args[0] << "::Run()" << Endl;
    
    string cmd = SetupCommand(args);
    
    VersionedAssetList assetList;
    Conn() >> assetList;
    string paths = ResolvePaths(assetList, GetResolvePathFlags());
    
    Conn().Log().Debug() << "Paths resolved are: " << paths << Endl;
    
    if (paths.empty())
    {
        Conn().WarnLine("No paths in fileset perforce command", MARemote);
        Conn().EndResponse();
        return true;
    }
    
    cmd += " " + paths;
    
    task.CommandRun(cmd, this);
    Conn() << GetStatus();

    // Stat the files to get the most recent state.
    // This could probably be optimized by reading the output of the specific
    // commands and figure out the new state. 
    RunAndSendStatus(task, assetList);    
    
    // The OutputState and other callbacks will now output to stdout.
    // We just wrap up the communication here.
    Conn().EndResponse();
    return true;
}
void P4StatusCommand::RunAndSend(P4Task& task, const VersionedAssetList& assetList, bool recursive)
{
	string paths = ResolvePaths(assetList, kPathWild | kPathSkipFolders | (recursive ? kPathRecursive : kNone) );
	
	Pipe().Log().Debug() << "Paths to stat are: " << paths << unityplugin::Endl;
	
	Pipe().BeginList();
	
	if (paths.empty())
	{
		Pipe().EndList();
		// Pipe().ErrorLine("No paths to stat", MASystem);
		return;
	}
	
	string cmd = "fstat -T \"depotFile,clientFile,action,ourLock,unresolved,headAction,otherOpen,otherLock,headRev,haveRev\" ";
	cmd += " " + paths;

	// We're sending along an asset list with an unknown size.
	task.CommandRun(cmd, this);
	
	// The OutputState and other callbacks will now output to stdout.
	// We just wrap up the communication here.
	Pipe().EndList();
}
	virtual bool Run(P4Task& task, const CommandArgs& args)
	{
		incomingAssetList.clear();
		ClearStatus();
		Pipe().Log().Info() << args[0] << "::Run()" << unityplugin::Endl;
		
		string cmd = "sync";
		
		VersionedAssetList assetList;
		Pipe() >> assetList;
		string paths = ResolvePaths(assetList, kPathWild | kPathRecursive);
		
		Pipe().Log().Debug() << "Paths resolved are: " << paths << unityplugin::Endl;
		
		if (paths.empty())
		{
			Pipe().WarnLine("No paths in getlatest perforce command", MARemote);
			Pipe().EndResponse();
			return true;
		}
		
		cmd += " " + paths;
		
		task.CommandRun(cmd, this);
		Pipe() << GetStatus();
		
		// Stat the files to get the most recent state.
		// This could probably be optimized by reading the output of the command better
		RunAndSendStatus(task, incomingAssetList);
		
		// The OutputState and other callbacks will now output to stdout.
		// We just wrap up the communication here.
		Pipe().EndResponse();
		return true;
	}
	virtual bool Run(P4Task& task, const CommandArgs& args)
	{
		if (!task.IsConnected()) // Cannot logout without being connected
		{
			Pipe().Log().Info() << "Cannot logout when not connected" << unityplugin::Endl;
			return false;
		}
		
		ClearStatus();
		
		if (!task.CommandRun("logout", this))
		{
			string errorMessage = GetStatusMessage();			
			Pipe().Log().Notice() << errorMessage << unityplugin::Endl;
		}
		
		return true;
	}
	virtual bool Run(P4Task& task, const CommandArgs& args)
	{
		ClearStatus();
		m_ProjectPath = task.GetP4Root();
		m_Result.clear();

		ChangelistRevision cl;
		Pipe() >> cl;
		
		vector<string> toks;
		if (Tokenize(toks, m_ProjectPath, "/") == 0)
		{
			Pipe().BeginList();
			Pipe().WarnLine(string("Project path invalid - ") + m_ProjectPath);
			Pipe().EndList();
			Pipe().EndResponse();
			return true;
		}
		
		Pipe().Log().Debug() << "Project path is " << m_ProjectPath << unityplugin::Endl;
		
		string rev = cl == kDefaultListRevision ? string("default") : cl;
		const std::string cmd = string("describe -s ") + rev;
		
		task.CommandRun(cmd, this);
		
		if (!MapToLocal(task, m_Result))
		{
			// Abort since there was an error mapping files to depot path
			Pipe().BeginList();
			Pipe().WarnLine("Files couldn't be mapped in perforce view");
			Pipe().EndList();
			Pipe().EndResponse();
			return true;
		}

		Pipe() << m_Result;
		m_Result.clear();
		Pipe() << GetStatus();

		Pipe().EndResponse();
		
		return true;
	}
 virtual bool Run(P4Task& task, const CommandArgs& args)
 {
     ClearStatus();
     Conn().Log().Info() << "ChangeDescriptionCommand::Run()"  << Endl;
     
     ChangelistRevision cl;
     Conn() >> cl;
     
     const string cmd = string("change -o ") + (cl == kDefaultListRevision ? string("") : cl);
             
     task.CommandRun(cmd, this);
     Conn() << GetStatus();
     
     // The OutputState and other callbacks will now output to stdout.
     // We just wrap up the communication here.
     Conn().EndResponse();
     
     return true;
 }
예제 #11
0
    bool P4EditCommand::Run(P4Task &task)
    {
        CommandArgs myArgs;

        // Append changelist if available
        if(!m_changelist.empty())
        {
            myArgs.emplace_back("-c");
            myArgs.emplace_back(m_changelist);
        }

        // Append custom arguments
        std::copy(m_customArgs.begin(), m_customArgs.end(), std::back_inserter(myArgs));

        // Append paths
        for(auto &path : m_paths)
        {
            myArgs.emplace_back(path);
        }

        return task.runP4Command("edit", myArgs, this);
    }
	virtual bool Run(P4Task& task, const CommandArgs& args)
	{
		//ConfigRequest req(args, task.
		if (args.size() < 2)
		{
			string msg = "Perforce plugin got invalid config setting :"; 
			for (CommandArgs::const_iterator i = args.begin(); i != args.end(); ++i) {
				msg += " ";
				msg += *i;
			}
			Conn().WarnLine(msg, MAConfig);
			Conn().EndResponse();
			return true;
		}
		
		string key = args[1];
		string value = Join(args.begin() + 2, args.end(), " ");
		
		ClearStatus();
		
		string logValue = value;
		if (key == "vcPerforcePassword")
			logValue = "*";

		Conn().Log().Info() << "Got config " << key << " = '" << logValue << "'" << Endl;

		// This command actually handles several commands all 
		// concerning connecting to the perforce server
		if (key == "vcPerforceUsername") 
		{
			task.SetP4User(value);
		}
		else if (key == "vcPerforceWorkspace")
		{
			task.SetP4Client(value);
		}
		else if (key == "projectPath")
		{
			task.SetProjectPath(TrimEnd(value));
			Conn().Log().Info() << "Set projectPath to" << value << Endl;
		}
		else if (key == "vcSharedLogLevel")
		{
			Conn().Log().Info() << "Set log level to " << value << Endl;
			LogLevel level = LOG_DEBUG;
			if (value == "info")
				level = LOG_INFO;
			else if (value == "notice")
				level = LOG_NOTICE;
			else if (value == "fatal")
				level = LOG_FATAL;
		    Conn().Log().SetLogLevel(level);
		}
		else if (key == "vcPerforcePassword")
		{
			task.SetP4Password(value);
			value = "*";
		}
		else if (key == "vcPerforceServer")
		{
			if (value.empty())
				value = "perforce";
			
			string::size_type i = (StartsWith(value, "ssl:") ? value.substr(4) : value).find(":");
			if (i == string::npos)
				value += ":1666"; // default port
			task.SetP4Port(value);
		}
		else if (key == "vcPerforceHost")
		{
			task.SetP4Host(value);
		}
		else if (key == "pluginVersions")
		{
			int sel = SelectVersion(args);
			Conn().DataLine(sel, MAConfig); 
			Conn().Log().Info() << "Selected plugin protocol version " << sel << Endl;
		}
		else if (key == "pluginTraits")
		{
			// We have 4 flags set
			Conn().DataLine("6");
			Conn().DataLine("requiresNetwork", MAConfig); 			
			Conn().DataLine("enablesCheckout", MAConfig);
			Conn().DataLine("enablesLocking", MAConfig);
			Conn().DataLine("enablesRevertUnchanged", MAConfig);
			Conn().DataLine("enablesChangelists", MAConfig);
			Conn().DataLine("enablesGetLatestOnChangeSetSubset", MAConfig);

			// We provide 4 configuration fields for the GUI to display
			Conn().DataLine("5");
			Conn().DataLine("vcPerforceUsername");               // key
			Conn().DataLine("Username", MAConfig);               // label
			Conn().DataLine("The perforce user name", MAConfig); // description
			Conn().DataLine("");                                 // default
			Conn().DataLine("1");                                // 1 == required field, 2 == password field

			Conn().DataLine("vcPerforcePassword");
			Conn().DataLine("Password", MAConfig);
			Conn().DataLine("The perforce password", MAConfig);
			Conn().DataLine("");
			Conn().DataLine("2"); // password field

			Conn().DataLine("vcPerforceWorkspace");
			Conn().DataLine("Workspace", MAConfig);
			Conn().DataLine("The perforce workspace/client", MAConfig);
			Conn().DataLine("");
			Conn().DataLine("1"); // required field

			Conn().DataLine("vcPerforceServer");
			Conn().DataLine("Server", MAConfig);
			Conn().DataLine("The perforce server using format: hostname:port. Port hostname defaults to 'perforce' and port defaults to 1666", MAConfig);
			Conn().DataLine("perforce");
			Conn().DataLine("0"); // 

			Conn().DataLine("vcPerforceHost");
			Conn().DataLine("Host", MAConfig);
			Conn().DataLine("The perforce host ie. P4HOST. It can often be left blank.", MAConfig);
			Conn().DataLine("");
			Conn().DataLine("0"); // 

			// We have 11 custom overlay icons
			Conn().DataLine("overlays");
			Conn().DataLine("11");
			Conn().DataLine(IntToString(kLocal)); // for this state
			Conn().DataLine("default");           // use this path. "default" and "blank" paths can be used when you have not custom overlays.
			Conn().DataLine(IntToString(kOutOfSync));
			Conn().DataLine("default");
			Conn().DataLine(IntToString(kCheckedOutLocal));
			Conn().DataLine("default");
			Conn().DataLine(IntToString(kCheckedOutRemote));
			Conn().DataLine("default");
			Conn().DataLine(IntToString(kDeletedLocal));
			Conn().DataLine("default");
			Conn().DataLine(IntToString(kDeletedRemote));
			Conn().DataLine("default");
			Conn().DataLine(IntToString(kAddedLocal));
			Conn().DataLine("default");
			Conn().DataLine(IntToString(kAddedRemote));
			Conn().DataLine("default");
			Conn().DataLine(IntToString(kConflicted));
			Conn().DataLine("default");
			Conn().DataLine(IntToString(kLockedLocal));
			Conn().DataLine("default");
		    Conn().DataLine(IntToString(kLockedRemote));
			Conn().DataLine("default");
		}
		else if (key == "end")
		{
			task.Logout();
			task.Disconnect();
			task.DisableUTF8Mode();
		}
		else 
		{
			Conn().WarnLine(ToString("Unknown config field set on version control plugin: ", key), MAConfig);
		}
		Conn().EndResponse();
		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;
    }