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; }
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; }