VERSION 1.0 CLASS BEGIN MultiUse = -1 'True Persistable = 0 'NotPersistable DataBindingBehavior = 0 'vbNone DataSourceBehavior = 0 'vbNone MTSTransactionMode = 0 'NotAnMTSObject END Attribute VB_Name = "Fstat" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = False Attribute VB_Exposed = False Option Explicit ' Class for doing FStat on a file Private m_OfficeApp As OfficeApp Private m_DocPath As String Public Enum LockType NoLock = 0 OurLock = 1 OtherLock = 2 OurExclusiveLock = 3 OtherExclusiveLock = 4 End Enum ' Class member variables - don't forget to initialise below... Private m_DepotFile As String Private m_ClientFile As String Private m_HeadAction As String Private m_HeadType As String Private m_HeadRev As Integer Private m_HeadChange As Integer Private m_HeadTime As Long Private m_HaveRev As Integer Private m_Action As String Private m_ActionOwner As String Private m_Change As String Private m_LockType As String Private m_NumOtherOpen As Integer Private m_WhoOtherOpen As String Private m_Unresolved As String Private m_FormattedInfo() As String Private m_Error As Boolean Private m_Version As String ' optional version specifier Private m_p4 As P4COM.p4 Private Sub InitVars() m_Error = False m_DepotFile = vbNullString m_ClientFile = vbNullString m_HeadAction = vbNullString m_HeadType = vbNullString m_Action = vbNullString m_ActionOwner = vbNullString m_Change = vbNullString m_HeadRev = 0 m_HeadChange = 0 m_HaveRev = 0 m_NumOtherOpen = 0 m_WhoOtherOpen = vbNullString m_LockType = vbNullString m_Unresolved = vbNullString Erase m_FormattedInfo End Sub Public Sub Initialize(App As OfficeApp, Optional Version As String = vbNullString, _ Optional DocPath As String = vbNullString) Set m_OfficeApp = App m_Version = Version m_DocPath = DocPath End Sub Property Get Error() As Boolean Error = m_Error End Property Property Get DepotFile() As String DepotFile = m_DepotFile End Property Property Get ClientFile() As String ClientFile = m_ClientFile End Property Property Get HeadAction() As String HeadAction = m_HeadAction End Property Property Get HeadType() As String HeadType = m_HeadType End Property Property Get HeadRev() As Integer HeadRev = m_HeadRev End Property Property Get HeadTime() As Long HeadTime = m_HeadTime End Property Property Get HeadTimeAsDate() As Date ' Convert to VB date HeadTimeAsDate = CDate(UnixLongToDate(m_HeadTime)) End Property Property Get HeadChange() As Integer HeadChange = m_HeadChange End Property Property Get HaveRev() As Integer HaveRev = m_HaveRev End Property Property Get Action() As String Action = m_Action End Property Property Get ActionOwner() As String ActionOwner = m_ActionOwner End Property Property Get Change() As String Change = m_Change End Property Property Get NumOtherOpen() As Integer NumOtherOpen = m_NumOtherOpen End Property Property Get WhoOtherOpen() As String WhoOtherOpen = m_WhoOtherOpen End Property Property Get Unresolved() As Boolean Unresolved = Len(m_Unresolved) <> 0 End Property Private Function ExclusiveLockFileType() As Boolean Dim i As Integer ExclusiveLockFileType = False i = InStr(1, m_HeadType, "+") If i > 0 Then If InStr(i, m_HeadType, "l") > 0 Then ExclusiveLockFileType = True End If End If End Function Property Get LockType() As LockType If Len(m_LockType) = 0 Then LockType = NoLock If ExclusiveLockFileType Then If m_Action <> "" And m_ActionOwner = m_p4.User Then LockType = OurExclusiveLock ElseIf m_WhoOtherOpen <> "" Then LockType = OtherExclusiveLock End If End If ElseIf m_LockType = "ourLock" Then LockType = OurLock Else LockType = OtherLock End If End Property ' Extract out of line who has file opened. ' Possible formats: ' OtherOpen0 bruno@cl ' OtherOpen 1 Private Sub GetOtherOpened(line As String, WhoElse As String, NumOpened As Integer) Dim T As Tracker: Set T = GStackTrace.Enter(TypeName(Me), "GetOtherOpened") Dim i As Integer Dim n As Integer Const Key = "otherOpen" Dim NextCh As String i = InStr(1, line, Key) If i > 0 Then n = i + Len(Key) NextCh = Mid$(line, n, 1) If NextCh = " " Then NumOpened = Mid$(line, n + 1) Else If Len(WhoElse) <> 0 Then WhoElse = WhoElse & vbCrLf End If WhoElse = WhoElse & Mid$(line, n + 2) SaveFormatted "Also open by", Mid$(line, n + 2) End If End If End Sub Private Sub ProcessOtherAction(line As String) Dim T As Tracker: Set T = GStackTrace.Enter(TypeName(Me), "ProcessOtherAction") Dim i As Integer Dim n As Integer Const Key = "otherAction" Dim NextCh As String i = InStr(1, line, Key) If i > 0 Then n = i + Len(Key) NextCh = Mid$(line, n, 1) If NextCh <> " " Then SaveFormatted "Opened by them for", Mid$(line, n + 2) End If End If End Sub ' Extract OtherOpen formatted information Private Sub GetOtherOpen(line As String, VarName As String, Count As Integer, Var As String) Dim T As Tracker: Set T = GStackTrace.Enter(TypeName(Me), "GetOtherOpen") Dim i As Integer ' Format will be: ' depotFile //depot/.../ i = InStr(1, line, VarName) If i <> 0 Then GetOtherOpened line, Var, Count End If End Sub Private Function IntValue(Value As String) As Integer On Error Resume Next IntValue = CInt(Value) err.Clear End Function Private Function LongValue(Value As String) As Long On Error Resume Next LongValue = CLng(Value) err.Clear End Function Public Sub Run() Dim T As Tracker: Set T = GStackTrace.Enter(TypeName(Me), "Run") Const CmdTitle = "fstat" Dim p4cmd As String Dim Result As Long Dim Msg As String Dim InfoArr() As String Dim ErrorArr() As String Dim FileName As String Dim DocPathname As String Dim i As Integer InitVars Set m_p4 = NewP4 m_p4.ExceptionLevel = 0 If Len(m_DocPath) = 0 Then If m_OfficeApp.NoCurrDoc() Then GoTo Exit_Block End If If Len(m_OfficeApp.GetCurrDocPath()) = 0 Then GoTo Exit_Block End If ' Make sure we change to appropriate directory (to pick up P4CONFIG file if there) m_OfficeApp.ChangeCurrDocDir m_p4.Cwd = m_OfficeApp.GetCurrDocPath DocPathname = m_OfficeApp.GetCurrDocPathname() Else DocPathname = m_DocPath End If If g_p4interface.HideConnectionWarning(m_p4.port) Then GoTo Exit_Block End If If Len(m_Version) = 0 Then p4cmd = "fstat " & Chr(34) & DocPathname & Chr(34) Else p4cmd = "fstat " & Chr(34) & DocPathname & "#" & m_Version & Chr(34) End If Result = p4runcmd(p4cmd, InfoArr, ErrorArr, FileName, m_p4) CheckResult Result, InfoArr, ErrorArr If LoginRequired(m_p4) Then If LoggedIn(m_p4) Then ' Retry command Result = p4runcmd(p4cmd, InfoArr, ErrorArr, FileName, m_p4) CheckResult Result, InfoArr, ErrorArr End If End If ' For debug purposes 'DisplayResult CmdTitle, DocPathname, Result, InfoArr, ErrorArr Exit_Block: End Sub Private Sub CheckResult(Result As Long, InfoArr() As String, ErrorArr() As String) Dim i As Integer If Not IsEmptyArray(ErrorArr) Then If GStacker.Tracing Then GStacker.TraceMsg "Error: " & Join(ErrorArr, "; ") End If End If If Result = 0 Then ' Check what is in the info array ' Format will be: ' depotFile //depot/.../ ' and similar If Not IsEmptyArray(InfoArr) Then For i = LBound(InfoArr) To UBound(InfoArr) ProcessInfo InfoArr(i) Next If LockType = OurExclusiveLock Then SaveFormatted "Exclusively locked by you", "" ElseIf LockType = OtherExclusiveLock Then SaveFormatted "Exclusively locked by them", "" End If End If Else ' Empty Info/Error arrays indicates we failed to talk to server so ' set error flag (otherwise we would at least expect to get an error msg) If IsEmptyArray(InfoArr) And IsEmptyArray(ErrorArr) Then m_Error = True ElseIf UBound(InfoArr) < 0 And UBound(ErrorArr) < 0 Then m_Error = True End If End If End Sub Public Sub ProcessInfo(line As String) ' Parse returned result Dim Key As String Dim val As String Dim i As Integer i = InStr(1, line, " ") If i > 0 Then Key = Left(line, i - 1) val = Mid(line, i + 1) Else Key = line val = vbNullString End If Select Case Key Case "depotFile" m_DepotFile = val SaveFormatted "Depot file", val Case "clientFile" m_ClientFile = val SaveFormatted "Your document", val Case "headAction" m_HeadAction = val SaveFormatted "Latest (head) action in depot", val Case "headType" m_HeadType = val SaveFormatted "File type", val Case "headTime" m_HeadTime = LongValue(val) SaveFormatted "Last modified in depot", _ UnixLongToDate(LongValue(val)) Case "action" m_Action = val SaveFormatted "Open for", val Case "actionOwner" m_ActionOwner = val SaveFormatted "Open by Perforce user", val Case "change" m_Change = val SaveFormatted "In changelist", val Case "headRev" m_HeadRev = IntValue(val) SaveFormatted "Latest (head) revision in depot", val Case "headChange" m_HeadChange = IntValue(val) SaveFormatted "Latest (head) changelist in depot", val Case "haveRev" m_HaveRev = IntValue(val) SaveFormatted "Revision in your workspace", val Case "ourLock" m_LockType = Key SaveFormatted "Locked by you", "" Case "otherLock" m_LockType = Key SaveFormatted "Locked by someone else", "" Case "unresolved" m_Unresolved = Key SaveFormatted "Needs to be resolved", "" Case Else ' Note that we can get "otherOpen" or "otherOpen1" etc If InStr(1, line, "otherOpen") <> 0 Then GetOtherOpened line, m_WhoOtherOpen, m_NumOtherOpen ElseIf InStr(1, line, "otherAction") <> 0 Then ProcessOtherAction line ElseIf Not WhiteSpace(line) Then If Key = "type" Then ' ignore Else Debug.Print "Not processing: " & line End If End If End Select End Sub Private Function WhiteSpace(s As String) As Boolean Dim i As Integer WhiteSpace = True If Len(s) <> 0 Then For i = 1 To Len(s) If Mid(s, i, 1) <> " " Then WhiteSpace = False Exit For End If Next End If End Function Private Sub SaveFormatted(ByVal Desc As String, ByVal val As String) Dim i As Integer Dim Separator As String On Error Resume Next i = UBound(m_FormattedInfo) + 1 If err.Number <> 0 Then i = 1 err.Clear End If ReDim Preserve m_FormattedInfo(i) As String If Len(val) <> 0 Then Separator = ": " m_FormattedInfo(i) = Desc & Separator & val End Sub Public Sub FormattedInfo(FI() As String) FI = m_FormattedInfo End Sub