儲存庫指示的組態 - 3/1:可繼承的屬性

本文經由原始位置 http://blogs.collab.net/subversion/the-road-to-repository-dictated-configuration-day-2-autoprops 的許可鏡像。已移除或更新失效的連結。

作者:Paul Burba

張貼 2013-06-25

這是三篇文章系列的第一篇文章,說明可以在儲存庫中設定的不同組態選項。

屬性繼承

即使是 Subversion 最一般的使用者也可能熟悉版本化屬性。這些名稱:值對的元資料會指定給檔案或目錄。有些(名稱以「svn:」開頭的屬性)被 Subversion 賦予特殊意義,並觸發特定行為;其餘的則開放給使用者或第三方 Subversion 相關工具定義和詮釋。

在 Subversion 1.7 之前,版本化屬性通常僅套用於設定屬性的檔案或目錄。最多,設定於目錄上的屬性可能會套用於目錄的直接子目錄 1。例如,如果 svn:ignore 屬性存在於目錄中,則會定義未版本化檔案模式的清單(在同一個目錄中),而 svn status 和其他子指令會忽略這些模式。

從這裡開始,我們將僅討論「屬性」,而不會區分版本化屬性和修訂屬性 — 因此請記住,在這一系列部落格中,我們討論的是版本化屬性!修訂屬性沒有繼承的概念。

新發布的 Subversion 1.8 引入了繼承屬性的概念。這個新功能相當透明,事實上,您可以像往常一樣使用屬性,而您可能永遠不會注意到任何差異。這是因為實際上沒有所謂的「可繼承」屬性或「不可繼承」屬性 — 所有屬性都是潛在可繼承的!

1.8 中真正不同的點在於,給定工作副本路徑(或 URL)後,Subversion 現在有一個機制可以找出設定於該路徑父目錄上的屬性。即使路徑是工作副本路徑,而路徑的父目錄未在工作副本中找到,此機制仍然有效。此機制會透過 svn proplistsvn propget 子指令的新 --show-inherited-props 選項來體現。

一個快速範例將展示這個新選項如何運作。

注意:在今天的範例中,我將使用無意義的自訂屬性。在第二和第三部分,我們將展示一些實際上會執行真實工作的 Subversion 保留屬性;現在我只想展示一些新的核心概念。

假設我們的儲存庫在儲存庫的根目錄和各種子樹上設定了屬性 foo。我們可以使用儲存庫根目錄上的遞迴 svn propget 來查看所有這些屬性、它們的位置和值 2

1.8.0>svn pg foo http://svn.example.com/repos --verbose --recursive
Properties on 'http://svn.example.com/repos':
  foo
    bar
Properties on 'http://svn.example.com/repos/calc':
  foo
    baz
Properties on 'http://svn.example.com/repos/calc/trunk':
  foo
    qux
Properties on 'http://svn.example.com/repos/paint':
  foo
    fum
Properties on 'http://svn.example.com/repos/paint/trunk':
  foo
    zot

現在讓我們簽出儲存庫的子樹 ^/calc/trunk

1.8.0>svn co http://svn.example.com/repos/calc/trunk calc-trunk-wc
A    calc-trunk-wc\doc
A    calc-trunk-wc\src
A    calc-trunk-wc\doc\INSTALL
A    calc-trunk-wc\FAQ
A    calc-trunk-wc\src\real.c
A    calc-trunk-wc\src\main.c
A    calc-trunk-wc\src\button.c
A    calc-trunk-wc\src\integer.c
A    calc-trunk-wc\Makefile
A    calc-trunk-wc\README
 U   calc-trunk-wc
Checked out revision 478.

毫不意外地,在剛簽出的工作副本的根目錄上執行遞迴 propget 只會顯示對應於 ^/calc/trunk 的工作副本路徑上的 foo 屬性

1.8.0>svn pg foo calc-trunk-wc --verbose --recursive
Properties on 'calc-trunk-wc':
  foo
    qux

使用相同的 propget 指令,但這次加上新的 --show-inherited-props 選項,會在工作副本根路徑上顯示相同的屬性,但也會顯示該路徑的儲存庫父項目的 foo 屬性

1.8.0>svn pg foo calc-trunk-wc --verbose --recursive --show-inherited-props
Inherited properties on 'calc-trunk-wc',
from 'http://svn.example.com/repos':
  foo
    bar
Inherited properties on 'calc-trunk-wc',
from 'http://svn.example.com/repos/calc':
  foo
    baz
Properties on 'calc-trunk-wc':
  foo
    qux

^/paint^/paint/trunk 上設定的 foo 屬性不會顯示,因為這些路徑不是工作副本的父項目。svn proplist 子指令也支援 --show-inherited-props 選項,並以類似的方式運作,但當然會顯示所有繼承的屬性,不論名稱為何。

建構區塊

所以現在我們有了遞迴 propget/proplist 的反向操作;一種向上查看儲存庫樹狀結構的方式,而不仅仅是向下查看。我們可以用這個新發現的能力做些什麼?

請記住,所有在 1.8 之前就存在的 Subversion 保留屬性仍然只套用於設定其屬性的路徑,或最多只套用於該路徑的直接子路徑 3。您新增至自己儲存庫的任何自訂屬性可能也適用相同的原則 — 舊屬性不會突然擁有新的範圍。

撇開這個警告,屬性繼承在兩種情況下會變得非常有用

第一種情況是使用新的 Subversion 保留屬性 4,該屬性利用繼承將屬性套用至屬性設定路徑下的所有子樹。在本部落格的第 2 部分中,我們將看到兩個此類屬性的第一個屬性,svn:auto-props

第二個案例是使用您自己的自訂工具、指令碼、工作流程等,這些工具、指令碼、工作流程仰賴版本化屬性來驅動行為。對於所有這些,現在您有新的工具可以使用,如何使用由您決定 — 我猜測你們有些人會想出我們在開發此功能時從未考慮過的巧妙可繼承屬性應用程式。

注意事項

在我們結束今天的課程之前,有幾件事項需要關於屬性繼承記住

升級較舊的工作副本

回想一下,在上述範例中,svn propget --show-inherited-props calc-trunk-wc 會揭露 calc-trunk-wc 上的屬性,以及在儲存庫中其父層級上設定的屬性。Subversion 在不連絡儲存庫的情況下完成這個繼承屬性的查詢 5。它透過在工作副本資料庫中保留工作副本根目錄的繼承屬性快取來執行此操作 6。這個快取會在工作副本每次進行結帳、更新或切換時更新。當您透過「svn upgrade」指令升級較舊格式的工作副本時,這個快取會建立,但不會填入資料。因此,請務必在升級後更新您的工作副本。

例如:糟糕,這是較舊的工作副本!

>svn pg foo --verbose --show-inherited-props
svn: E155036: Please see the 'svn upgrade' command
svn: E155036: The working copy at 'C:\SVN\calc-trunk-wc'
is too old (format 29) to work with client version '1.8.0 (r1490375)' (expects format 31). You need to upgrade the working copy first.

我們會根據錯誤訊息升級工作副本

>svn upgrade

現在檢查繼承屬性

>svn pg foo --verbose --show-inherited-props
Properties on '.':
  foo
    qux

喔,對了,快取需要透過更新來填入資料!

>svn up
Updating '.':
At revision 478.

現在已找到繼承屬性

>svn pg foo --verbose --show-inherited-props
Inherited properties on '.',
from 'http://svn.example.com/repos':
  foo
    bar
Inherited properties on '.',
from 'http://svn.example.com/repos/calc':
  foo
    baz
Properties on '.':
  foo
    qux

最低需求

雖然您顯然需要 1.8 Subversion 伺服器,但 1.8 伺服器是選用的。在填入繼承屬性快取或對 URL 使用 proplist/propget 子指令時,1.8 伺服器可能會提供更好的效能。

授權

您只能繼承您擁有讀取權限的儲存庫路徑的屬性。如果您沒有某個路徑的讀取權限,它將顯示為您似乎沒有任何屬性可以從該路徑繼承。在此情況下,不會發出警告或錯誤。

工作副本內的繼承

如上所述,繼承屬性快取僅知道工作副本的根目錄繼承了哪些屬性。這表示本機變更或 混合版本工作副本對給定的工作副本路徑繼承的內容沒有影響。這裡不是探討此問題的全部含意的適當地方,但請記住這個簡單的規則,您就不會感到意外:如果您依賴於擁有繼承屬性的最新值(例如來自儲存庫的根目錄),請確定工作副本的根目錄是最新的。

備註

  1. 有經驗的使用者可能會合理地抗議 Subversion 已經有一個屬性,其影響可以延伸到目錄的直接子目錄以外,即 svn:mergeinfo 屬性。您當然是對的,svn:mergeinfo 是可繼承的,但它是一個特殊情況,有 它自己完善的規則集,在討論「一般」可繼承屬性時可以安全地忽略它。

  2. --verbose 選項在此用於提供格式良好的輸出。

  3. 再次強調,svn:mergeinfo 是顯著的例外。

  4. 自 Subversion 1.8.0 起,Subversion 解釋為可繼承的唯一保留屬性為 svn:auto-props(在本部落格的第 2 部分中涵蓋)和 svn:global-ignores(在本部落格的第 3 部分中涵蓋)。在未來的 Subversion 版本中尋找更多使用繼承屬性建置的功能(例如記錄訊息範本機制)。在此同時,請隨時隨意使用該功能。任何您想套用至整個儲存庫(或其大型子區段)的版本化元資料片段,都可以輕鬆儲存在儲存庫根目錄(或適當的子樹)上的屬性中。

  5. 一般來說,Subversion 工作副本會努力在絕對必要時才連繫儲存庫。這保留了在無法連繫儲存庫時使用工作副本的能力,並且在其他條件相同的情況下,如果不需要連繫儲存庫,則某個作業可能會更快。

  6. 工作副本中的任何已切換路徑都算作獨立的工作副本根目錄,並且會有自己的快取。

關於作者

Paul Burba 是 Apache 軟體基金會 Subversion 專案的提交者,並且在過去九年來一直致力於 Subversion。他從新罕布夏州的家中擔任 Collabnet 的軟體工程師,並且在不寫程式碼時,通常可以發現他與姪子們一起滑雪、與朋友們一起騎登山車,或與妻子一起旅行。在遙遠的過去,Paul 曾從新罕布夏大學畢業,取得商業學位。最近,他從波士頓大學取得電腦科學碩士學位。