private void DoRefreshFileState() { // need to handle login exceptions string[] path = SelectedItemPaths.ToArray(); try { P4EXPProgram.RefreshFileState(path); } catch (P4Exception e) { FileLogger.LogException(Properties.Resources.FileLogger_RefreshFileState, e); if (P4EXPProgram.IsLoginException(e.ErrorCode)) { P4EXPProgram.Login(path[0]); P4EXPProgram.RefreshFileState(path); } } catch (Exception e) { FileLogger.LogException(Properties.Resources.FileLogger_RefreshFileState, e); } }
/// <summary> /// Determines whether this instance can a shell context show menu, given the specified selected file list. /// </summary> /// <returns> /// <c>true</c> if this instance should show a shell context menu for the specified file list; otherwise, <c>false</c>. /// </returns> protected override bool CanShowMenu() { string[] TargetFiles = SelectedItemPaths.ToArray(); // start a connection here. P4EXPProgram.Connect(TargetFiles[0]); RepoStorage store = null; try { store = P4EXPProgram.getRepoStorage(TargetFiles[0]); } catch (Exception e) { FileLogger.LogException(Properties.Resources.FileLogger_MenuExtension, e); return(true); } lock (store) { try { loginVisible = !store.connected || !store.loggedIn; if (!store.connected) { // notify of disconnected in top menu item setConnection = Properties.Resources.ContextMenus_SetConnectionNotConnectedMenuItem; setConnectionImage = Properties.Resources.disconnected; outsideRootMenuitemVisible = false; startP4VMenuitemVisible = true; return(true); } if (store.rep.Connection.Client == null || (store.rep.Connection.Client.Root == null && store.roots.Count < 1)) { // notify of missing P4CLIENT in top menu item setConnection = Properties.Resources.ContextMenus_SetConnectionConnectedMenuItem; setConnectionImage = Properties.Resources.connected_with_issues; outside = Properties.Resources.ContextMenus_NoWorkspaceSet; outsideRootMenuitemVisible = true; startP4VMenuitemVisible = true; return(true); } if (!store.IsUnderClientRoot(TargetFiles[0])) { // notify of outside root in top menu item setConnection = Properties.Resources.ContextMenus_SetConnectionConnectedMenuItem; setConnectionImage = Properties.Resources.connected_with_issues; outside = Properties.Resources.ContextMenus_OutsideRoot; outsideRootMenuitemVisible = true; startP4VMenuitemVisible = true; return(true); } Repository rep = store.rep; // checking here for connected and directory change bool stale = false; bool checkedout = false; bool indepot = false; bool notindepot = false; bool haverev = false; bool cancheckout = false; bool folderselect = false; //check if each target file is a directory and if so, convert // convert to =+/... List <string> selectedItems = new List <string>(); commandFiles = new List <FileMetaData>(); foreach (string path in TargetFiles) { string pathToAdd = path; FileAttributes attr = System.IO.File.GetAttributes(path); if ((attr & FileAttributes.Directory) == FileAttributes.Directory) { pathToAdd += @"\..."; notindepot = true; folderselect = true; FileMetaData folder = new FileMetaData(); folder.LocalPath = new LocalPath(pathToAdd); commandFiles.Add(folder); pathToAdd = pathToAdd.Replace(@"\...", @"\*"); selectedItems.Add(pathToAdd); } else { selectedItems.Add(pathToAdd); FileMetaData file = new FileMetaData(); file.LocalPath = new LocalPath(pathToAdd); commandFiles.Add(file); } } FileSpec[] fs = new FileSpec[TargetFiles.Length]; fs = FileSpec.LocalSpecArray(selectedItems.ToArray()); // TODO might need to set an fstat -m limit here if (store.loggedIn) { IList <FileMetaData> fmd = P4EXPProgram.GetFileMetaData(fs); // if no P4Exception is caught by attempting to get // FileMetaData, remove the initial menu items and // add the rest of the menu items and seperators if (fmd != null) { moreMenuitemVisible = true; foreach (FileMetaData d in fmd) { if (stale && checkedout && indepot && notindepot && haverev && cancheckout) { break; } if (d == null || (d.HaveRev == -1 && d.Action != FileAction.Add)) { notindepot = true; break; } if (d.HaveRev < d.HeadRev) { stale = true; } if (d.Action != FileAction.None) { checkedout = true; } if (d.IsInDepot) { indepot = true; } if (d.IsInClient) { haverev = true; } if ((d.Action == FileAction.None) && d.IsInClient && d.IsInDepot) { cancheckout = true; } } } else { outsideRootMenuitemVisible = true; startP4VMenuitemVisible = true; } if (stale || folderselect) { getLatestMenuitemVisible = true; subSeperator1Visible = true; } if (checkedout || folderselect) { submitMenuitemVisible = true; } if (cancheckout || folderselect) { checkoutMenuitemVisible = true; subSeperator2Visible = true; } if (notindepot || folderselect) { addMenuitemVisible = true; } if (cancheckout) { deleteMenuitemVisible = true; subSeperator2Visible = true; } if (checkedout || folderselect || notindepot) { subSeperator2Visible = true; if (!notindepot) { if (!folderselect) { revertMenuitemVisible = true; } revertUnchangedMenuitemVisible = true; subSeperator3Visible = true; } } // only on single selection of file if (TargetFiles.Length == 1) { if (!folderselect && haverev) { diffAgainstHaveMenuitemVisible = true; diffAgainstMenuitemVisible = true; fileHistoryMenuitemVisible = true; timeLapseViewMenuitemVisible = true; propertiesMenuitemVisible = true; showInP4VMenuitemVisible = true; subSeperator4Visible = true; } else { if (!folderselect) { diffAgainstMenuitemVisible = true; } // don't allow folder history on the // workspace root if (TargetFiles[0] != store.rep.Connection.Client.Root) { fileHistoryMenuitemVisible = true; } subSeperator4Visible = true; } } if ((haverev && !(checkedout)) || folderselect) { removeFromWorkspaceMenuitemVisible = true; } if (fmd != null || folderselect || notindepot) { refreshFileStateMenuitemVisible = true; subSeperator5Visible = true; pendingChangesMenuitemVisible = true; moreMenuitemVisible = true; } } } catch (P4Exception ex) { // Leaving this for now. It looks like it is a possible redundant check // of more efficient if (ex.ErrorCode == P4ClientError.MsgDb_NotUnderRoot) // below. It also looks like it would never be hit based on the string // "outside root". Adding a message dialog for the case that this ever gets // hit. if (ex.ErrorLevel == ErrorSeverity.E_FATAL && ex.Message == "outside root") { Message message = new Message("CanShowMenu() P4Exception", ex.Message); message.ShowDialog(); setConnection = Properties.Resources.ContextMenus_SetConnectionConnectedMenuItem; setConnectionImage = Properties.Resources.connected_with_issues; outside = Properties.Resources.ContextMenus_OutsideRoot; outsideRootMenuitemVisible = true; startP4VMenuitemVisible = true; } if (P4EXPProgram.IsLoginException(ex.ErrorCode)) { P4EXPProgram.Login(TargetFiles[0]); if (store.rep.Connection.Status == ConnectionStatus.Disconnected) { // notify of disconnected in top menu item setConnection = Properties.Resources.ContextMenus_SetConnectionNotConnectedMenuItem; setConnectionImage = Properties.Resources.disconnected; outsideRootMenuitemVisible = false; startP4VMenuitemVisible = true; } } else if (ex.ErrorCode == P4ClientError.MsgServer_PasswordExpired) { store.loggedIn = false; loginVisible = true; string message = ex.Message; Message dlg = new Message(Properties.Resources.MessageDlg_PasswordExpired, message); dlg.ShowDialog(); } else if (ex.ErrorCode == P4ClientError.MsgDm_NeedClient) { // second happens when P4CLIENT is not set 841226339 setConnection = Properties.Resources.ContextMenus_SetConnectionConnectedMenuItem; setConnectionImage = Properties.Resources.connected_with_issues; outside = Properties.Resources.ContextMenus_NoWorkspaceSet; outsideRootMenuitemVisible = true; startP4VMenuitemVisible = true; } else if (ex.ErrorCode == P4ClientError.MsgDb_NotUnderRoot) { // do nothing, this is a file not under workspace root. // just return, the context menu is already set to show this. outsideRootMenuitemVisible = true; startP4VMenuitemVisible = true; } if (P4EXPProgram.showP4Exception()) { string message = ex.Message + "\n" + ex.StackTrace + "\n" + ex.TargetSite.Name; Message dlg = new Message(Properties.Resources.MessageDlg_P4Exception, message); dlg.ShowDialog(); } FileLogger.LogException(Properties.Resources.FileLogger_BuildContextMenu, ex); return(true); } catch (Exception ex) { // TODO: is this catching a login request? // this does not appear to be something that will be // part of a P4ClientError. Leaving it in for now. Unsure if it // would ever be hit. Adding a message dialog for the case that // this ever gets hit. if (ex.Message.Contains("requires")) { Message message = new Message("CanShowMenu() Exception", ex.Message); message.ShowDialog(); P4EXPProgram.Connect(TargetFiles[0]); } if (store.rep != null && store.rep.Connection.Status == ConnectionStatus.Disconnected) { // notify of disconnected in top menu item setConnection = Properties.Resources.ContextMenus_SetConnectionNotConnectedMenuItem; setConnectionImage = Properties.Resources.disconnected; outsideRootMenuitemVisible = false; startP4VMenuitemVisible = true; } if (P4EXPProgram.showException()) { string message = ex.Message + "\n" + ex.StackTrace + "\n" + ex.TargetSite.Name; Message dlg = new Message(Properties.Resources.MessageDlg_Exception, message); dlg.ShowDialog(); } FileLogger.LogException(Properties.Resources.FileLogger_BuildContextMenu, ex); return(true); } } // We always show the menu for now. This will still return true, // but individual menu items may be made invisible return(true); }
public bool RefreshPath(String basePath, bool force) { // if the list of paths is large (configurable?), try to expire some paths if (expirationList.Count > 100) { ClearExpiredPaths(); } // first check if basePath is under the client's root. if not, don't bother if (!connected || !IsUnderClientRoot(basePath)) { return(false); } PathCache pc = (pathCache.ContainsKey(basePath) ? pathCache[basePath] : null); bool useCache = (pc != null); if (pc != null) { useCache = !pc.IsExpired(); } if (force) { useCache = false; } if (useCache) { return(true); } FileLogger.LogMessage(3, Properties.Resources.FileLogger_RepoStorage, string.Format(Properties.Resources.FileLogger_RefreshingPath, basePath)); if (pc != null) { // remove from the lists pathCache.Remove(basePath); expirationList.Remove(pc); pc = null; } // TODO: configurable expiration pc = new PathCache(basePath, DateTime.Now.AddMinutes(5)); // is it better to do a local dir call to build a list of fstat targets, or to // do a fstat path/* ? // the answer from the performance lab is that passing the wildcard to the server should be more performant FileSpec[] specs = new FileSpec[] { new FileSpec(null, null, new LocalPath(Path.Combine(basePath, "*")), null) }; IList <FileMetaData> fds = null; try { fds = rep.GetFileMetaData(null, specs); } catch (P4Exception e) { // add it anyway or we get lots of retries if (fds != null) { pc.AddFiles(fds); } pathCache[basePath] = pc; expirationList.Add(pc); // alaways throw here? display an error message? if (P4EXPProgram.IsLoginException(e.ErrorCode)) { throw; } FileLogger.LogException(Properties.Resources.FileLogger_P4EXPProgram, e); } catch (Exception e) { FileLogger.LogException(Properties.Resources.FileLogger_P4EXPProgram, e); } // add it anyway if (fds != null) { pc.AddFiles(fds); } pathCache[basePath] = pc; expirationList.Add(pc); return(true); }
protected override object GetPropertyValue(Property property) { if (!(checkServer())) { return(null); } if (!P4EXPProgram.connected) { P4EXPProgram.Connect(); } if (TargetFile != null) { try { IList <FileMetaData> fmd = P4EXPProgram.rep.GetFileMetaData(null, new FileSpec(null, null, new LocalPath(TargetFile), null)); if (property.CanonicalName == "P4File.State") { if (fmd != null && fmd[0] != null) { if (fmd[0].Action != FileAction.None && fmd[0].HaveRev == fmd[0].HeadRev) { if (fmd[0].Action == FileAction.Add) { return("Marked for add"); } else { return("Checked out"); } } else if (fmd[0].HaveRev == fmd[0].HeadRev) { return("Up-to-date"); } else { return("Needs Update"); } } return("Not on Server"); } if (property.CanonicalName == "P4File.Action") { if (fmd != null && fmd[0] != null && fmd[0].Action != FileAction.None) { return(fmd[0].Action.ToString()); } return(null); } if (property.CanonicalName == "P4File.Rev") { if (fmd != null && fmd[0] != null) { if (fmd[0].HaveRev != -1 && fmd[0].HeadRev != -1) { return("#" + fmd[0].HaveRev + "/" + fmd[0].HeadRev); } } return(null); } } catch (P4Exception ex) { if (P4EXPProgram.showP4Exception()) { string message = ex.Message + "\n" + ex.StackTrace + "\n" + ex.TargetSite.Name; Message dlg = new Message("P4Exception", message); dlg.ShowDialog(); } FileLogger.LogException("Get column value", ex); } catch (Exception ex) { if (P4EXPProgram.showException()) { string message = ex.Message + "\n" + ex.StackTrace + "\n" + ex.TargetSite.Name; Message dlg = new Message("Exception", message); dlg.ShowDialog(); } FileLogger.LogException("Get column value", ex); } } return(null); }
private void RefreshClientData(bool force = false) { lock (this) { if (!connected) { return; } DateTime now = DateTime.Now; if (now.CompareTo(clientFailed) < 0) { return; // give up for a bit, there was a client error } if (roots.Count > 0 && !force && now.CompareTo(clientExpire) < 0) { return; // no need to refresh } FileLogger.LogMessage(3, Properties.Resources.FileLogger_RepoStorage, String.Format(Properties.Resources.FileLogger_RefreshingClient, clientName)); // re-initializing this RepoStorage roots.Clear(); // set the client again, forcing a refresh try { // Check for valid Client IList <Client> clients = rep.GetClients(new ClientsCmdOptions(ClientsCmdFlags.None, null, clientName, 1, null)); if (clients == null || clients.Count <= 0) { // If P4CLIENT is non-existent or a client that does not exist on the // server, make sure the Client itself is set to null. rep.Connection.Client = null; } else { rep.Connection.Client = clients[0]; } } catch (P4Exception e) { if (e.ErrorCode == P4ClientError.MsgServer_LoginExpired || e.ErrorCode == P4ClientError.MsgServer_BadPassword || e.ErrorCode == P4ClientError.MsgServer_PasswordExpired) { clientFailed = now.AddSeconds(15); throw; // throw it out, someone should handle with a Login call } } catch (Exception e) { FileLogger.LogException(Properties.Resources.FileLogger_RefreshClientData, e); rep.Connection.Client = null; } // we failed for some reason, record the failure so that we // don't launch a retry attack if (rep.Connection.Client == null || rep.Connection.Client.Root == null) { FileLogger.LogMessage(1, Properties.Resources.FileLogger_RefreshClientData, Properties.Resources.FileLogger_FailedToSetClientDelay15); clientFailed = now.AddSeconds(15); return; } // now read the roots into our root array // convert to lower case, reverse the path indicators roots.Add(cleanRoot(rep.Connection.Client.Root)); if (rep.Connection.Client.AltRoots != null) { foreach (String root in rep.Connection.Client.AltRoots) { roots.Add(cleanRoot(root)); } } // TODO: make this configurable clientExpire = now.AddMinutes(5); } }