程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> Team System: 簽入說明和策略

Team System: 簽入說明和策略

編輯:關於.NET

在本專欄 2007 年 1 月刊中,我開始討論使用 Microsoft® Word 2003 加載項提供的 Team Foundation Server (TFS) 版本控制 API。一年多之後,我又在這裡為大家奉上第五部分,同時也是最後 一部分有關版本控制 API 和 Word 加載項的專項討論(我確實沒想到會有這麼多部分)。

您也許還記得在以前的專欄裡我們曾提到加載項目前支持簽入、簽出、撤消掛起的更改,並能夠將工 作項與簽入相關聯。在我最新的專欄中,我詳細分析了簽入說明和簽入策略。本月,我將為您介紹如何將 簽入說明和簽入策略支持添加到 Word 加載項。另外,您還將了解到如何處理簽入沖突。如果您尚未閱讀 本系列的其他部分(列在側欄“本系列前四部分”中),請確保先閱讀其中的內容。

簽入說明

簽入說明是可以與簽入關聯的自由格式的文本字段。可以將簽入說明標記為強制使用, 並控制其在 Visual Studio® 簽入對話框中出現的順序。為了在 Word 加載項中模擬此行為,必須獲 得用於活動團隊項目的簽入說明列表、對此列表進行排序並顯示每個簽入說明的標簽和文本框。

VersionControlServer 對象公開 GetCheckinNoteDefinitions 方法,該方法接受團隊項目名稱 數組並返回 CheckinNoteFieldDefinition 對象數組。每個 CheckinNoteFieldDefinition 實例都會公開 簽入說明的名稱、顯示順序、是否必需以及服務器項字符串屬性。GetCheckinNoteDefinitions 將以近似 隨機順序返回項目列表。在測試中,我發現無論以何種順序將團隊項目引用傳遞到方法中,返回說明時都 會按照簽入說明名稱排序並按團隊項目名稱分組。因此,假設使用默認說明組定義了兩個團隊項目,一個 叫 MSF-Agile,另一個叫 MSF-CMMI,結果如圖 1 所示。如果創建稱為 Build Master 的簽入說明並將其 添加到 MSF-CMMI 團隊項目中,它將出現在列表的第一個位置。

Figure 1 調用 GetCheckinNoteDefinitions 的結果

簽入說明名稱 團隊項目 代碼審閱者 MSF- Agile 代碼審閱者 MSF-CMMI 性能審閱者 MSF- Agile 性能審閱者 MSF-CMMI 安全性審閱者 MSF-Agile 安全性審閱者 MSF-CMMI

為 Word 加載項創建的 tfsVCUtil 類提供兩種新的共享方法,您可以用它們來檢索簽入說明: GetAllCheckInNotesByTeamProjectName 和 GetAllCheckInNotesByItemLocalPath。可以使用其中任何一 種方法獲得未修改的團隊項目 CheckinNoteFieldDefinitions 列表(如果有)。

支持簽入對話框 的簽入說明需要在現有工作項按鈕下方另行添加切換按鈕、並添加作為容器的面板,還要為每個簽入說明 添加標簽和文本框。(代碼下載提供了一種簡單的實現示例。)但是,為簽入對話框添加簽入說明支持只 解決了部分難題。您還需要通過添加代碼來強制使用必需的說明。簽入策略和沖突檢測要求為 tfsVCUtil 類中簽入對話框和支持代碼的工作方式進行一些更改。

簽入策略

就象簽入說明一樣,支持 簽入策略的第一步是指出為活動團隊項目啟用哪些策略。第二步是決定如何處理簽入策略。因為 Microsoft 設計簽入策略的主要目的是為了讓開發人員能夠從 Visual Studio 中簽入代碼,所以當用於 驗證單個 Word 文檔簽入時,隨 TFS 2005 發布的三項內置策略中有兩項將無法正確工作。因此需要使加 載項僅處理在 Word 文檔上下文中有意義的簽入策略的錯誤。

解決此問題只有一種方法。使用加 載項評估所有啟用的策略,並忽略由不相關策略生成的錯誤。在首次檢查簽入策略的工作情況時,有一種 看似可行的方法是手動使加載項根據應該啟用的策略執行評估。但事實證明這種方法不可行。

默 認情況下,當使用自定義代碼時,不會在簽入過程中評估簽入策略和簽入說明。為了模擬 Visual Studio 的行為,您的應用程序可以自行編寫代碼以確保提供所需的簽入說明,並確保不會違反策略—或者 ,如果違反了策略,則提供該策略的重寫信息。

為了方便起見,Workspace 類公開了 EvaluateCheckin 方法。您可以使用該方法來檢查可能會導致簽 入失敗的情況。下面是來自 MSDN® 文檔的方法原型:

Public Function EvaluateCheckin 

( _
  options As CheckinEvaluationOptions, _
  allChanges As PendingChange(), _
  changes As PendingChange(), _
  comment As String, _
  checkinNote As CheckinNote, _
  workItemChanges As WorkItemCheckinInfo() _
) As CheckinEvaluationResult

該方法首先需要知道想評估什麼內容。可以通過選項參數傳遞 正確的枚舉值來提供此信息。您可以使用該方法來查找簽入沖突、所需的簽入說明、策略違規情況,或者 同時查找所有這三項內容。

該方法隨後要求傳入 PendingChange 對象數組作為第二個和第三個參 數。為什麼要兩組參數?例如,在 Visual Studio 中,您可能已經在當前工作區中修改了十個文件,但 用戶可以只選中三個文件進行簽入。因此,Visual Studio 將通過 allChanges 參數傳遞所有十個文件, 並通過 changes 參數傳遞那三個選中的文件。該方法為啟用策略程序集提供這一信息。如果是在 Word 加載項中,將為兩個參數傳遞相同的數組。

對於第四個參數,您可以傳入由執行簽入的用戶提供 的注釋文本(如果有)。要傳遞簽入說明,您需要創建類型 CheckInNote 的實例,該實例接受 CheckinNoteFieldValue 實例數組,並將此數組作為第五個參數。最後,為第五個參數傳遞 WorkItemCheckinInfo 實例數組。可以不為後三個參數傳遞任何值。

調用 EvaluateCheckin 後, 您將收到 CheckinEvaluationResult 實例。該對象通過三組屬性公開結果:Conflicts、NoteFailures 和 PolicyFailures。如果特定結果集沒有值,EvaluateCheckin 將返回長度為零的數組。您可以選擇枚 舉每個數組並處理結果。請注意,即使 EvaluateCheckin 為簽入說明或策略返回失敗,也不會阻止簽入 。您必須在自己的代碼中實現某種邏輯,以防止當這些規則不滿足時仍繼續簽入。但是,如果存在沖突, TFS 就一定會阻止簽入。為了充分利用 Word 加載項的這一方法,可以使用稱為 PreValidateCheckIn 的 共享方法通過 tfsVCUtil 類公開 EvaluateCheckin:

Public Shared Function 

PreValidateCheckIn( _
 ByVal docPath As String, _
 ByVal options As CheckinEvaluationOptions, _
 ByVal comments As String, ByVal notes As CheckinNote, _
 ByVal workitems() As WorkItemCheckinInfo) _
 As CheckinEvaluationResult
 Dim pc As PendingChange() = _
   m_userWorkspace.GetPendingChanges(docPath)
 Return m_userWorkspace.EvaluateCheckin(options, _
   pc, pc, comments, notes, workitems)
End Function

如列出的這段代碼所示,PreValidateCheckIn 使用評估文檔所使用的其他參數模 擬 EvaluateCheckin 的簽名。從簽入對話框中調用此方法後,您必須枚舉所請求驗證項的數組、查找問 題,並且在必要的時候使用戶直觀地看到發生了什麼錯誤。

如出現違反策略,您必須決定哪些策 略與您的應用程序有關。通常,由 Microsoft 提供的內置策略,以及許多其他策略在 Visual Studio 中 都偏重於簽入體驗。如果是 Word 加載項,當在 Visual Studio Team System 2005 版中檢查三種內置策 略時,只有 work-item-required 策略與您的應用程序有關。除了內置策略外,Word 加載項解決方案只 需考慮由相關程序集引發的策略錯誤。通過使用一些帶外機制(如存儲在加載項配置文件中的 name/value 對),代碼可以知道應該注意哪些策略。然後,在運行時,代碼將檢查策略錯誤集合並忽略 所有不在列表中的錯誤。實現此目的的一種方法是將 PolicyFailure 實例的 Policy 屬性返回的 IPolicyEvaluation 引用轉換為 IpolicyDefinition 實例。然後,IPolicyDefinition 公開可以確定策 略源的 Type 屬性。以下是一個簡單的示例:

Dim cer As CheckinEvaluationResult = {Call 

to server elided}
Dim i As IPolicyDefinition = Nothing
For Each pf As PolicyFailure In cer.PolicyFailures
 i = DirectCast(pf.Policy, IPolicyDefinition)
 If i.Type = "Work Items" Then
  ' process this policy failure
 End If
Next

但是這種方法有個弊端。在 Visual Studio 2005 Team Foundation Server Power Tool 中,Microsoft 另外添加了四個簽入策略(請參見 msdn2.microsoft.com/vstudio/aa718351)。在提供 的掛起更改與特殊正則表達式匹配時,其中一個比較特別的策略(custom path 策略)可以通過委派間接 運行另一個策略(如 work item 策略)。團隊可以使用此策略僅在其自己的代碼存儲庫部分使用更嚴格 的簽入規則,而其他部分仍可以使用較寬松的簽入規則。因此,如果使用此策略,之前列出的代碼將看到 custom path 策略的類型,而不是實際執行的策略(例如,work items 策略)。

您可以嘗試按照 Visual Studio 的方式去做,但這樣做不會成功。同時您還可以通過調用有效 TeamProject 實例的 GetCheckinPolicies 獲得已啟用策略的列表,沒有任何方法(合理的方法)能夠獲 得作為參數傳遞給 IpolicyEvaluation 初始化方法的有效 IPendingCheckin 引用。因此,為了處理 custom path 策略,您需要檢查 IpolicyDefinition 返回的 Description 屬性。策略編寫者選擇將委派 策略中的 Type 值存放在這裡。因此,重構後的代碼如下:

Dim cer As 

CheckinEvaluationResult = '{Call to server elided}
Dim i As IPolicyDefinition = Nothing
Dim processPolicy As Boolean = False
For Each pf As PolicyFailure In cer.PolicyFailures
 i = DirectCast(pf.Policy, IPolicyDefinition)
 processPolicy = (i.Type = "Work Items")
 If Not processPolicy AndAlso _
  i.Type = "Custom Path Policy" Then
  processPolicy = (i.Description = "Work Items")
 End If
 If processPolicy Then
  ' process this policy failure
 End If

此版本使用 Custom Path 策略處理標准 Work Items 策略和委派版本的基本工作。您 自己的實現方案可能更為復雜,並且可能需要更為詳盡的解決方案,但現在您已經有了解決問題的工具。

我已經說明了如何獲得簽入說明列表,因此現在您可以開始展示 UI 了。如果查看 EvaluateCheckin 和包裝方法 PreValidateCheckIn,您會發現為了驗證簽入說明,您需要創建並傳遞一 個 CheckinNote 實例。當您執行完 EvaluateCheckin 之後(直接或通過包裝),您需要檢查 NoteFailures 集合。每個 NoteFailure 實例都會公開 Definition 屬性,該屬性代表簽入說明的 CheckinNoteFieldDefinitions。從這裡,您可以輕松地獲得 Name 屬性以了解在 UI 中應該突出的簽入 說明。Message 屬性是一則通用消息,指明“必須為簽入說明指定值”。如前所述,違反策略 或缺少簽入說明都不會阻止代碼執行簽入。這就需要您在調用簽入代碼之前確保滿足各項條件。

簽入沖突

簽入沖突卻一定會阻止您簽入。您可以通過使用“File Types”(文件類型 )對話框(如圖 2 所示)控制對版本控制存儲庫產物的簽出行為,該對話框可通過“Team” (團隊)|“Team Foundation Server Settings”(Team Foundation Server 設置) |“Source Control File Types”(源代碼控制文件類型)訪問。使用此對話框,您可以控制 哪些文件支持文件合並以及同時簽出。例如,您可以從圖 2 中看出 Microsoft Office 文件已禁用文件 合並。因此,當使用“源代碼管理資源管理器”或 API 執行簽出時,使用的是獨占簽出方式 。要調整一組文件擴展名的多重簽出和文件合並設置,只需單擊“Edit”(編輯)按鈕打開 “Edit File Types”(編輯文件類型)對話框即可。

圖 2 為版本控制配置的文件類型

如果為特定文件擴展名啟用了文件合並,並且在簽入時發生沖突,默認情況下 Visual Studio 將顯示 “Team Explorer 合並工具”。Microsoft 使該工具成為每個開發人員都可自由配置的選項。 在 Visual Studio 中,您可以轉到“Tools”(工具)|“Options”(選項),然 後在“Source Control”(源代碼控制)節點中,選擇“Visual Studio Team Foundation Server”節點。在“options”(選項)頁面中,您可以單擊 “Configure User Tools”(配置用戶工具)並單擊“Add”(添加)。現在您可 完全控制特定文件擴展名或擴展名組的處理方式(請參見圖 3)。

圖 3 為文件擴展名配置新合並工具

當使用 Word 加載項簽出 Word 文檔時,默認行為是獨占簽出。理論上,這樣就不必在加載項代碼中 處理沖突了。但是,這種默認行為有一個問題,它使許多新 TFS 用戶脫離保護。默認情況下,如果使用 TFS 2005 通過 Visual Studio 或 API 請求簽出,簽出發生在您工作區的當前本地文件上—即使它 並不是 TFS 中存儲的最新版本文件。基礎代碼不會執行獲取最新版本文件的操作。因此,在您通過 Word 加載項簽出文件並進行一些更改後,簽入可能會出現失敗。

您可以通過多種方式解決這個問題。事實上,Microsoft 已經得到客戶反饋,並且在 TFS 2008 中, 您可對每個團隊項目啟用“簽出時獲取最新版本”操作;您還可以在本地安裝中控制此功能。Microsoft 還會更新 PendEdit API 以支持此功能。但是,對於工作在 TFS 2005 中的加載項,您需要修改現有簽出 代碼以便在簽出之前手動獲取最新版本。為此,您需要在調用 PendEdit 之前添加一行代碼,讓它使用正 確的參數調用 Workspace.Get。圖 4 中的代碼正好可以完成這項工作。

Figure 4 在簽出之前獲取最新版本的代碼

Public Shared Function CheckOutDocument( _
  ByVal docPath As String) As Boolean
  If serverValidated Then
    If m_userWorkspace Is Nothing Then
      ' We need the Workstation
      Dim userWorkstation As Workstation = Workstation.Current
      ' We need the Workspace
      Dim docWSInfo As WorkspaceInfo = _
        userWorkstation.GetLocalWorkspaceInfo(docPath)
      m_userWorkspace = m_tfsVCS.GetWorkspace(docWSInfo)
    End If
    Dim status As GetStatus = _
    m_userWorkspace.Get(New String() {docPath}, _
      VersionSpec.Latest, RecursionType.None, _
      GetOptions.GetAll Or GetOptions.Overwrite)
    Dim statusCount As Integer = status.NumConflicts + _
      status.NumFailures + status.NumOperations + _
      status.NumWarnings
    If statusCount = 1 Then
      If m_userWorkspace.PendEdit(docPath) = 1 Then
        Return True
      Else
        Return False
      End If
    Else
      Throw New tfsUtilException( _
        String.Format(MSG_UNEXPECTED_GETLATEST_CONFLICT, _
          "Failures count: " & status.NumFailures))
    End If
  Else
    Throw New tfsUtilException(MSG_SERVER_NOT_VALIDATED)
  End If
End Function

Get 命令將返回 GetStatus 對象的實例,該實例將公開一組屬性,用於提供與沖突、失敗、操作和警 告數量相關的統計信息。您可以使用該數據確定 Get 命令是否按預期方式工作。

如果有使用此版本 CheckOutDocument 的加載項,您應該不會再遇到任何沖突問題。但如果您仍然擔 心會發生沖突,則可以檢查由 EvaluateCheckin 返回的 Conflicts 數組。如果發生沖突,您需要提供一 種體驗來讓用戶選擇所謂的“優勝者”。如果希望優勝者是試圖執行當前簽入的人員,您需要使用 Workspace 對象的 QueryConflicts 方法。它將返回 Conflict 對象數組。隨後可以將 Conflict 實例的 Resolution 屬性設置為 Resolution.AcceptYours,並將此對象傳遞給 Workspace.ResolveConflict 方 法。要提供比這更豐富的選項,需要深入思考並投入更多的時間編寫更多的代碼。

現在,您已了解本系列的全部內容,您應該已經具備所需的工具和信息,可以為自己的應用程序編寫 豐富的自定義簽入體驗了。如欲繼續深入學習,您需要查閱 Team Foundation Server 2008 提供的更新 API,並准備好學習今後將要發布的“Rosario”版本中的更多增強功能。

特別感謝 Teamprise 的 Martin Woodward 及所有 Visual Studio Team System 團隊的同事幫助我完 成本文及本系列以前的專欄。

請將您想詢問的問題和提出的意見發送至 [email protected].

本文配套源碼:http://www.bianceng.net/dotnet/201212/770.htm

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved