第 8 章 嵌入 Subversion

目錄

分層的庫設計
版本庫層
版本庫訪問層
客戶端層
進入工作副本的管理區
條目文件
原始副本和屬性文件
使用 API
Apache 可移植運行庫
URL 和路徑需求
使用 C 和 C++ 以外的語言
代碼範例

Subversion有一個模塊化的設計,以庫的形式由C編寫和實現。每個庫都有一個定義良好的目的和API,而且這些介面不僅僅為了Subversion本身使用,也可以為任何希望嵌入編程方式控制Subversion的軟體。此外,Subversion的API不僅僅可以為C程序使用,也可以使用如Ptyhon、Perl、Java或Ruby等高級語言調用。

本章是為那些希望編寫代碼或其他語言綁定與Subversion交互的人準備的。如果你圍繞Subversion功能編寫健壯的腳本來簡化你的生活,設法開發Subversion與其他軟體的複雜集成,或者只是對Subversion不同庫模塊提供功能感興趣,這一章是為你準備的。然而,如果你不能預見你會以此種程度參與Subversion,你可以放心的跳過本章,略過本章不會影響你對Subversion使用的體驗。

分層的庫設計

每個Subversion核心模塊都屬於三層中的某一層—版本庫層、版本庫訪問(RA)層或是客戶端層(見圖 1 「Subversion 的架構」)。我們很快就會考察這些層,但首先讓我們看一下Subversion庫的摘要目錄,為了一致性,我們將通過它們的無擴展Unix庫名(例如libsvn_fs、libsvn_wc和mod_dav_svn)來引用它們。

libsvn_client

客戶端程序的主要介面

libsvn_delta

目錄樹和文字區別程序

libsvn_diff

上下文區別和合併例程

libsvn_fs

Subversion文件系統庫和模塊加載器

libsvn_fs_base

Berkeley DB文件系統後端

libsvn_fs_fs

本地文件系統(FSFS)後端

libsvn_ra

版本庫訪問通用組件和模塊裝載器

libsvn_ra_dav

WebDAV版本庫訪問模塊

libsvn_ra_local

本地版本庫訪問模塊

libsvn_ra_serf

另一個(實驗性的) WebDAV 版本庫訪問模塊

libsvn_ra_svn

一個自行定義版本庫訪問模塊

libsvn_repos

版本庫介面

libsvn_subr

各色各樣的有用的子程序

libsvn_wc

工作副本管理庫

mod_authz_svn

使用WebDAV訪問Subversion版本庫的Apache授權模塊

mod_dav_svn

影射WebDAV操作為Subversion操作的Apache模塊

單詞「各色各樣的(miscellaneous)」只在列表中出現過一次是一個好的跡象。Subversion開發團隊非常注意將功能歸入合適的層和庫,或許模塊化設計最大的好處就是從開發者的角度看減少了複雜性。作為一個開發者,你可以很快就描畫出一副「大圖像」,以便於你更精確地,也相對容易地找出某一功能所在的位置。

模塊化的另一個好處是我們有能力去構造一個全新的,能夠完全實現相同API功能的庫,以替換整個給定的模塊,而又不會影響基礎代碼。在某種意義上,Subversion已經這樣做了。libsvn_ra_dav、libsvn_ra_local、libsvn_ra_serf和libsvn_ra_svn all都實現了相同的介面,均與版本庫層進行通訊—libsvn_ra_loca與版本庫直接連接其他幾個則通過網路。 libsvn_fs_base和libsvn_fs_fs庫是另外一對以不同方式實現相同功能的庫—都是可以與libsvn_fs庫連接。

客戶端本身也得益於Subversion設計的模塊化,Subversion的libsvn_client庫提供了設計一個Subversion工作客戶端(見「客戶端層」一節)的絕大多數功能。所以儘管Subversion的發佈版只有svn指令列客戶端程序,依然有許多第三方的程序提供了各種形式的圖形化客戶端UI。這些GUI使用的API與指令列客戶端完全相同。模塊化類型的API的促使了大量Subversion客戶端和IDE集成外掛使用Subversion本身。

版本庫層

當提到Subversion版本庫層時,我們通常會討論兩個基本概念—版本化文件系統實現(通過libsvn_fs訪問,libsvn_fs_base和libsvn_fs_fs支持),和包裝在外的(以libsvn_repos實現)版本庫邏輯。這些庫提供了版本控制資料的儲存和報告機制,這些層通過版本庫訪問層連接客戶端層,從Subversion用戶的角度,這些事情在整個過程的另一端。

Subversion文件系統通過libsvn_fs API來訪問,它並不是一個安裝在操作系統之上的內核級的文件系統(例如Linux ext2或NTFS),而是一個虛擬文件系統。它並未將「文件」和「目錄」保存為真實的文件和目錄(也就是用你熟知的shell程序可以瀏覽的那種),而是採用了一種抽像的後端儲存方式,這個後端儲存方式有兩種—一個是Berkeley DB資料庫環境,另一個是普通文件表示。(要瞭解更多關於版本庫後端的訊息,請看「選擇資料儲存格式」一節)。除此之外,開發社群也非常有興趣考慮在Subversion的未來版本 中提供某種使用其它後端資料庫系統的能力,也許是開放式資料庫連接(ODBC)的機制。實際上,Google在2006中期啟動Google Code主機服務項目之前做了一些類似的事情,它的部分開放原始碼專案組成員編寫了新的Subversion文件系統,使用了他們的擴展性極好的Bigtable資料儲存。

libsvn_fs支持的文件系統API包含了所有其他文件系統的功能:你可以建立和刪除文件和目錄、拷貝和移動、修改文件內容等等。它也包含了一些不太常用的特性,如對任意文件和目錄新增、修改和刪除Meta資料(「properties」)的能力。此外,Subversion文件系統是一個版本化的文件系統,意味著你修改你的目錄樹時,Subversion會記住修改以前的樣子。也可以回到所有初始化版本庫之後(且僅僅之後)的版本。

所有你對目錄樹的修改包含在Subversion事務的上下文中,下面描述了修改文件系統的例程:

  1. 開始 Subversion 的提交事務。

  2. 作出修改(新增、刪除、屬性修改等等。)。

  3. 提交事務。

一旦你提交了你的事務,你的文件系統修改就會永久的作為歷史保存起來,每個這樣的週期會產生一個新的樹,所有的修訂版本都是永遠可以訪問的一個不變的快照。

大多數文件系統介面提供的功能作為一個動作發生在一個文件系統路徑上,也就是,從文件系統的外部,描述和訪問文件和目錄獨立版本的主要機制是經過如/foo/bar的路徑,就像你在喜歡的shell程序中定位文件和目錄。你通過傳遞它們的路徑到相應的API功能來新增新的文件和目錄,查詢這些訊息也是同樣的機制。

然而,不像大多數文件系統,一個單獨的路徑不足以在Subversion定位一個文件或目錄,可以把目錄樹看作一個二維的系統,一個節點的兄弟代表了一種從左到右的動作,並且遞減到子目錄是一個向下的動作,圖 8.1 「二維的文件和目錄」展示了一個典型的樹的形式。

圖 8.1. 二維的文件和目錄

二維的文件和目錄

當然,Subversion文件系統有一個其它文件系統所沒有的第三維—時間![49]在一個文件系統介面,幾乎所有的功能都有個路徑(path)參數,也期望一個root參數。svn_fs_root_t參數不僅描述了一個修訂版本或一個Subversion事務(通常正好是一個修訂版本),而且提供了用來區分修訂版本32的/foo/bar和修訂版本98在同樣路徑的三維上下文環境。圖 8.2 「版本時間 - 第三維!」展示了修訂版本歷史作為新增的緯度進入到Subversion文件系統領域。

圖 8.2. 版本時間 - 第三維!

版本時間 - 第三維!

像之前我們提到的,libsvn_fs的API感覺像是其它文件系統,只是有一個美妙的版本化能力。它設計為為所有對版本化的文件系統有興趣的程序使用,不是巧合,Subversion本身也對這個功能很有興趣。但是雖然文件系統API一定必須對基本的文件和目錄版本化提供足夠的支持,Subversion需要的更多—這是libsvn_repos到來的地方。

Subversion版本庫庫(libsvn_repos)建立在(邏輯上講)libsvn_fs的API之上,不僅僅提供了版本化文件系統的功能,它沒有包裹所有的文件系統功能—只有文件系統常規週期中的主要事件使用版本庫介面包裹,如包括Subversion事務的建立和提交,修訂版本屬性的修改。這些特別的事件使用版本庫庫包裹是因為它們有一些關聯的鉤子。版本庫鉤子系統並沒有與與版本化文件系統的緊密關聯,所以它們存在於版本庫的包裹庫。

鉤子機制需求是從文件系統代碼的其它部分中抽像出單獨的版本庫庫的一個原因,libsvn_repos的API提供了許多其他有用的工具,它們可以做到:

  • 在Subversion版本庫和版本庫包括的文件系統的上建立、打開、銷毀和執行恢復步驟。

  • 描述兩個文件系統樹的區別。

  • 關於所有(或者部分)修訂版本中的文件系統中的一組文件的提交日誌訊息的查詢

  • 產生可讀的文件系統「導出」,一個文件系統修訂版本的完整展現。

  • 解析導出格式,加載導出的版本到一個不同的Subversion版本庫。

伴隨著Subversion的發展,版本庫庫會隨著文件系統提供更多的功能和設定選項而不斷成長。

版本庫訪問層

如果說Subversion版本庫層是在「這條線的另一端」,那版本庫訪問層就是這條線。負責在客戶端庫和版本庫之間編碼資料,這一層包括libsvn_ra模塊加載模塊,RA模塊本身(現在包括了libsvn_ra_dav、libsvn_ra_local、libsvn_ra_serf和libsvn_ra_svn),和所有一個或多個RA模塊需要的附加庫,例如與Apache模塊mod_dav_svn通訊的libsvn_ra_dav或者是libsvn_ra_svn的伺服器,svnserve

因為Subversion使用URL來識別版本庫資源,URL模式的協議部分(通常是file:http:https:svn:)用來監測那個RA模塊用來處理通訊。每個模塊註冊一組它們知道如何「說話」的協議,所以RA加載器可以在運行中監測在手邊的任務中使用哪個模塊。通過運行svn --version,你可以監測Subversion指令列客戶端所支持的RA模塊和它們聲明支持的協議:

$ svn --version
svn, version 1.4.3 (r23084)
   compiled Jan 18 2007, 07:47:40

Copyright (C) 2000-2006 CollabNet.
Subversion is open source software, see http://subversion.tigris.org/
This product includes software developed by CollabNet (http://www.Collab.Net/).

The following repository access (RA) modules are available:

* ra_dav : Module for accessing a repository via WebDAV (DeltaV) protocol.
  - handles 'http' scheme
  - handles 'https' scheme
* ra_svn : Module for accessing a repository using the svn network protocol.
  - handles 'svn' scheme
* ra_local : Module for accessing a repository on local disk.
  - handles 'file' scheme

$

RA層導出的API包含了發送和接收版本化資料的必要功能,並且每一個存在的RA外掛可以使用特定協議執行任務—libsvn_ra_dav同設定了mod_dav_svn模塊的Apache HTTP伺服器使用HTTP/WebDAV(可選SSL加密)通訊,libsvn_ra_svn同svnserve使用自行定義網路協議通訊。

對那些一直希望使用另一個協議來訪問Subversion版本庫的人,正好是為什麼版本庫訪問層是模塊化的!開發者可以簡單的編寫一個新的庫來在一側實現RA介面並且與另一側的版本庫通訊。你的新庫可以使用存在的網路協議,或者發明你自己的。你可以使用進程間的通訊調用,或者—讓我們發狂,我們會嗎?—你甚至可以實現一個電子郵件為基礎的協議,Subversion提供了API,你提供創造性。

客戶端層

在客戶端這一面,Subversion工作副本是所有動作發生的地方。大多數客戶端庫實現的功能是為了管理工作副本的目的實現的—滿是文件子目錄的目錄是一個或多個版本庫位置的可編輯的本地「影射」—從版本庫訪問層來回傳遞修改。

Subversion的工作副本庫,libsvn_wc直接負責管理工作副本的資料,為了完成這一點,庫會在工作副本的每個目錄的特殊子目錄中保存關於工作副本的管理性訊息。這個子目錄叫做.svn,出現在所有工作副本目錄裡,保存了各種記錄了狀態和用來在私有工作區工作的文件和目錄。對那些熟悉CVS的用戶,.svn子目錄與CVS工作副本管理目錄的作用類似,關於.svn管理區域的更多訊息,見本章的「進入工作副本的管理區」一節

Subversion客戶端庫libsvn_client具備最廣泛的職責;它的工作是結合工作副本庫和版本庫訪問庫的功能,然後為希望普通版本控制的應用提供最高級的API。舉個例子,svn_client_checkout()方法是用一個URL作為參數,傳遞這個URL到RA層然後在特定版本庫打開一個會話。然後向版本庫要求一個特定的目錄樹,然後把目錄樹發送給工作副本庫,然後把完全的工作副本寫到磁碟(.svn目錄和一切)。

客戶端庫是為任何程序使用設計的,儘管Subversion的原始碼括了一個標準的指令列客戶端,用客戶端庫編寫GUI客戶端也是很簡單,Subversion新的GUI(或者任何新的客戶端,真的)不需要緊密圍繞包含的指令列客戶端—他們對具有相同功能、資料和回調機制的libsvn_client的API有完全的訪問權利。事實上,Subversion原始碼中包含了一段C程序(可以在tools/examples/minimal_client.c)例子,演示了如何利用Subversion客戶端建立簡單的客戶端程序。



[49] 我們理解這一定會給科幻小說迷帶來一個震撼,他們認為時間是第四維的,我們要為提出這樣一個不同理論的斷言而傷害了他們的作出道歉。