Fossil SCM 是一套軟體組態管理 (Software Configuration Management) 系統, 其中包含分散式版次控管 (DVC, Distributed Version Control) 、WikiBug TrackingTechnote 等功能, 可以用來控制及追蹤軟體開發專案, 並且紀錄專案開發歷程, 在協同產品設計實習課程中, 我們除了使用 git、github 與 bitbucket 之外, 將要在區域網路與系上主幹中, 配置每班兩台的 Fossil SCM 實習主機.

採用 git, github, bitbucket 與 fossil 原因

使用 git 原因 - git 是目前使用最廣泛的分散式版次管理工具.

使用 github 原因 - github 是目前主流 git 網際服務系統, 允許無協同人數限制的免費倉儲協同, 提供 github pages 可以伺服 html 與 javascript 網頁.

使用 bitbucket 原因 - bitbucket 允許使用者免費建立非公開型倉儲, 可採用 git 進行分散式版次管理.

使用 fossil scm 原因 - fossil 工具精簡, 適合用於小團隊分散式版次管理, 提供網際 wiki, ticket, technote 等實用功能.

Fossil SCM

Fossil Concepts

check-in - 簽入版本: 對所開發的軟體進行改版後, 簽入倉儲的版本, 稱為簽入版本.

repository - 倉儲: 包含開發專案歷程中, 所有簽入版本檔案的資料庫, 稱為倉儲.

建立新倉儲

可以使用 fossil newfossil init

建議使用 fossil init 建立新倉儲:

fossil init foo.fossil

表示建立一個新的倉儲專案, 且倉儲檔案名稱為 foo.fossil, 在 fossil SCM 中建立新專案時, 登入用戶名稱會成為內定的倉儲管理者, 若要指定管理者名稱, 可以附加 -A USERNAME 或 --admin-user USERNAME, 新增的倉儲就會以 USERNAME 作為管理者名稱, 且指定對應的密碼 (有關 fossil 密碼管理), 當使用者在近端以網際模式啟動該倉儲時 (以 fossil ui 指令) fossil SCM 會直接以管理者身份登入, 無需輸入管理者密碼.

以 sqlite3 擷取 .fossil 檔案內容

由於 fossil SCM 的倉儲格式為 Sqlite3 資料庫檔案, 因此利用 fossil init foo.fossil 建立倉儲後, 可以利用 sqlite3 工具查驗資料庫中的欄位資料.

首先以 sqlite3 工具指令開啟 foo.fossil 資料庫檔案, 進入 sql 指令環境:

sqlite3 foo.fossil

接著以 .schema user 查詢 user 資料表的欄位名稱, 然後直接讀取資料表中 login, pw 與 info 欄位中的資料:

.schema user
select login, pw, info from user;

其中可以發現 fossil SCM 已經使用 SHA1 hash 編碼使用者帳號對應的登入密碼, 但是當使用者 fossil clone 遠端倉儲到近端時, fossil SCM 會自動以明碼設定倉儲原管理者對應的管理密碼, 且在 fossil clone 結束後, 直接顯示在命令列視窗中 .

以 fossil sql 指令擷取 .fossil 檔案內容

使用者以 fossil init foo.fossil 建立倉儲檔案後, 除了使用 sqlite3 命令檢視 fossil 倉儲內容外, 也可以利用 fossil 指令查驗倉儲資料庫檔案的內容.

fossil sql -R foo.fossil

進入 sqlite 指令環境後, 可以利用 .schema user 查驗 user 資料表的欄位設計.

以 select login, pw, cap from user;

可以查詢目前 foo.fossil 檔案中 user 資料表 login, pw 與 cap 等3個欄位的資料內容.

若要更改特定 login 登入帳號的 pw 或 cap 可以使用下列 sqlite3 SQL 語法:

update user set pw='mynewpassword' where login='myloginaccount';

update user set cap='s' where login='myloginaccount';

clone

$ fossil clone http://your_domain_name ~/fossils/yourdb.fossil
$ fossil open ~/fossils/foo.fossil

上述 fossil 指令表示要從 http://your_domain_name fossil 伺服器中, clone 倉儲檔案, 然後存在近端的 ~/fossils/yourdb.fossil 檔案中.

接下來則可以選擇適當的目錄, 以 fossil open 將 .fossil 檔案解開, 此所在目錄即為該 .fossil 倉儲的 近端工作目錄.

add a file

$ fossil add yourfile.txt

在上述解開的 .fossil 倉儲對應工作目錄中, 一旦完成 yourfile.txt 的編輯, 可以利用 fossil add 將此檔案納入版次管理.

另外, 使用者必須注意的是, Fossil SCM 設定中, 內定的 autosync 為 on, 表示使用者一旦在工作目錄中 fossil add 與 fossil commit 之後, Fossil 會自動執行後續 fossil push 的動作, 而且此一推送會同時將改版資料送到近端與工作目錄對應的 .fossil 檔案倉儲外, 也會同時將改版資料推送到 .fossil 對應的遠端倉儲中.

換言之, Fossil SCM 針對從 fossil clone 開始的一連串指令執行, 會因為 settings 的差異而有不同的新增, 提交與推送流程, 假如 fossil clone 之後, 在近端以 fossil open 解開到近端工作目錄後, 並非以原 fossil 倉儲內建 autosync 綁定的使用者進行提交推送時, 必須透過 fossil remote-url off 切斷內建倉儲與工作目錄綁定的內建用戶資料, 然後在提交後, 以手動執行 fossil push.

fossil push https://usesid@fossil_server_url

git 分支流程模型

http://nvie.com/posts/a-successful-git-branching-model/

Fossil SCM concept

https://www.fossil-scm.org/xfer/doc/tip/www/concepts.wiki

Why Fossil SCM?

  1. 單一檔案工具與單一檔案倉儲上的簡單便捷

  2. 版本倉儲 (repository) 可以不在工作目錄 (working directory) 中, 因此使用者可以從同一個版本倉儲, 在不同目錄中, 簽出多個版本的工作空間, 因此具有伺服器版本控制系統 (server vcs) 與分散式版次控制系統 (dvcs) 的彈性與優點.

  3. 開發歷程不可變更 (因為不提供 rebase 功能), 是優點, 也是許多人認為的缺點.

  4. 小團隊更適合使用 Fossil SCM

  5. 內建網際伺服器支援團隊間的協同合作, 不僅內建提供 wiki, blog, issue tracking, 而且可以在近端修改這些工具所管理的內容後, 提交推送到遠端.

缺乏 submodule (而是採 nested path 呈現), rebase 與 code review 整合功能

git to fossil:

cd git-repo
git fast-export --all | fossil import --git new-repo.fossil

fossil to git:

git init new-repo
cd new-repo
fossil export --git ../repo.fossil | git fast-import

fossil 與 git 雙向同步:

Bidirectional Synchronization

Fossil also has the ability to synchronize with a Git repository via repeated imports and/or exports. To do this, it uses marks files to store a record of artifacts which are known by both Git and Fossil to exist at a given point in time.

To illustrate, consider the example of a remote Fossil repository that a user wants to import into a local Git repository. First, the user would clone the remote repository and import it into a new Git repository:

fossil clone /path/to/remote/repo.fossil repo.fossil
mkdir repo
cd repo
fossil open ../repo.fossil
mkdir ../repo.git
cd ../repo.git
git init .
fossil export --git --export-marks ../repo/fossil.marks  \
       ../repo.fossil | git fast-import                  \
       --export-marks=../repo/git.marks

Once the import has completed, the user would need to git checkout trunk. At any point after this, new changes can be imported from the remote Fossil repository:

cd ../repo
fossil pull
cd ../repo.git
fossil export --git --import-marks ../repo/fossil.marks  \
       --export-marks ../repo/fossil.marks               \
       ../repo.fossil | git fast-import                  \
       --import-marks=../repo/git.marks                  \
       --export-marks=../repo/git.marks

Changes in the Git repository can be exported to the Fossil repository and then pushed to the remote:

git fast-export --import-marks=../repo/git.marks                  \
    --export-marks=../repo/git.marks --all | fossil import --git  \
    --incremental --import-marks ../repo/fossil.marks             \
    --export-marks ../repo/fossil.marks ../repo.fossil
cd ../repo
fossil push

Fossil SCM 一般操作

http://www.gaia-gis.it/gaia-sins/about-fossil.html

fossil clone https://www.gaia-gis.it/fossil/librasterlite \ librasterlite.fossil

或者

fossil clone https://user:password@www.gaia-gis.it/fossil/librasterlite \ librasterlite.fossil

  1. 將倉儲內容開啟, 放入工作目錄中
$ mkdir librasterlite
$ cd librasterlite
$ fossil open ../librasterlite.fossil
  1. 對工作目錄中的檔案改版後, 查詢改版情形

fossil status

  1. 選擇編輯器, 提交版本至遠端倉儲後關閉
$ export "EDITOR=vi"
$ fossil commit
$ fossil close
  1. 其他 Fossil SCM 指令: http://fossil-scm.org/index.html/help

Fossil SCM 特色:

  1. Integrated Bug Tracking, Wiki, and Technotes
  2. Built-In Web Interface
  3. Self-Contained
  4. Simple Networking
  5. CGI/SCGI Enabled
  6. Autosync
  7. Robust & Reliable
  8. Free and Open-Source

Fossil (4 MB) 只需要 zlib 與 stunnel (4MB), 就可以充分使用, 但是 git 則需要許多程式庫與套件才能執行 (200 MB)

參考資料

http://www.fredshack.com/docs/fossil.html

Fossil SCM 與 Stunnel 啟動整合

下載 tiny2017 可攜程式系統之後, 可以利用下列 start.bat, 在 Windows 環境中自動擷取電腦連外 IP, 自動設定 stunnel.conf 後, 以 https 協定啟動 Fossil SCM 伺服器.

利用下列 start.bat 所啟動的 fossil server 位於 y:\tmp\fossil_repo\vcp.fossil 倉儲:

REM tiny2017 主要針對初學 Python3 與 C 學員所建立
REM 近端使用 fossil 管理資料版本, 並且定時轉為 git 格式後上傳到 github
@echo off
REM 設定 y 硬碟代號與 data 目錄對應
set Disk=y
subst %Disk%: "data"
REM 設定 leo 相關對應 Home 位置
set HomePath=%Disk%:\home
set HomeDrive=%Disk%:\home
set Home=%Disk%:\home
REM 將系統 Python 程式的 io 設為 utf-8
set PYTHONIOENCODING="utf-8"
REM 將後續的指令執行, 以 %Disk% 為主
%Disk%:
REM 設定 PYTHONPATH
set PYTHONPATH=%Disk%:\python-3.5.3-embed-amd64
REM 設定 Leo 所用的編輯器
set LEO_EDITOR=%Disk%:\wscite\SciTE.exe
REM for fossil https 連線設定
set HTTPS=on
REM 指令搜尋路徑設定
set path1=%PATH%;%Disk%:;%Disk%:\python-3.5.3-embed-amd64;%Disk%:\git\bin;%Disk%:\stunnel\bin;%Disk%:\sqlite-tools;%Disk%:\python-3.5.3-embed-amd64\Scripts;%Disk%:\portablegit\bin;
set path2=c:\Windows\Microsoft.NET\Framework\v3.5;%Disk%:\python-3.5.3-embed-amd64\Lib\site-packages;
set path3="C:\Program Files (x86)\Google\Chrome\Application"
path=%path%;%path1%;%path2%;%path3%
start /MIN %Disk%:\wscite\SciTE.exe
start /MIN cmd.exe
start /MIN cmd.exe
start /MIN cmd.exe
REM 啟動 Leo 編輯器
REM %Disk%:\Miniconda3\python.exe %Disk%:\apps\launchLeo.py
REM 啟動 stunnel
start /MIN fossil.exe server -P 127.0.0.1:8080 %Disk%:\tmp\fossil_repo\vcp.fossil
REM 取得電腦 IP, 然後設定 %Disk%:/stunnel/config/stunnel.conf
for /f "delims=[] tokens=2" %%a in ('ping -4 -n 1 %ComputerName% ^| findstr [') do set NetworkIP=%%a
REM echo Network IP: %NetworkIP%
REM Saved in %Disk%:\stunnel\config\stunnel.conf
@echo off
REM 建立 stunnel.conf
@echo [https] > %Disk%:\stunnel\config\stunnel.conf
REM 附加資料
@echo accept = %NetworkIP%:443 >> %Disk%:\stunnel\config\stunnel.conf
@echo connect = 127.0.0.1:8080 >> %Disk%:\stunnel\config\stunnel.conf
@echo TIMEOUTclose = 0 >> %Disk%:\stunnel\config\stunnel.conf
@echo cert = %Disk%:\stunnel\config\localhost.crt >> %Disk%:\stunnel\config\stunnel.conf
@echo key = %Disk%:\stunnel\config\localhost.key >> %Disk%:\stunnel\config\stunnel.conf
REM 啟動 stunnel
start /MIN stunnel.exe
REM set proxy
REG IMPORT setup_proxy.reg
REM 以 chrome 連線到 https://%NetworkIP%:443
REM chrome  --proxy-server="140.130.17.17:3128" --proxy-bypass-list="192.168.1.*;*.edu.tw" https://%NetworkIP%
chrome https://%NetworkIP% http://mde.tw https://mde2a1.kmol.info https://mde2a2.kmol.info https://vimeo.com/user24079973 http://mde.tw/2017springcd/blog/ http://mde.tw/2017springwcm/blog/ http://mde.tw/2017springvcp/blog/ http://service.mde.tw
Exit

setup_proxy.reg 設定 Windows proxy 組態檔案:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings] 
"MigrateProxy"=dword:00000001 
"ProxyEnable"=dword:00000001 
"ProxyHttp1.1"=dword:00000000 
"ProxyServer"="http://140.130.17.17:3128" 
"ProxyOverride"="192.168.1.*;*.edu.tw"

disable_proxy.reg 去除 Windows proxy 設定組態檔案:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings] 
"ProxyEnable"=dword:00000000

與上述設定對應的 stop.bat:

@echo off
set Disk=y
REM 關閉 SciTE
taskkill /IM SciTE.exe /F
REM 關閉 python
taskkill /IM python.exe /F
REM 關閉 stunnel
taskkill /IM stunnel.exe /F
REM 關閉 fossil
taskkill /IM fossil.exe /F
REM 關閉 cmd 指令視窗
taskkill /IM cmd.exe /F
REM disable proxy
%Disk%:
REG IMPORT disable_proxy.reg
REM 清除 log 資料
path=%PATH%;
REM del /Q /F  V:\tmp\*.*
REM 終止虛擬硬碟與目錄的對應
subst %Disk%: /D
REM taskkill /IM mingw32 /F
EXIT

編譯 sqlite3

cc -O3 -DSQLITE_THREADSAFE=0 sqlite3.c shell.c -ldl -o sqlite3

fossil clone 指令

fossil clone https://userid@mde2a2.kmol.info/cdag1 cdag1.fossil

接著輸入與 userid 對應的密碼

If you already have a username and password on the remote repository, you may introduce it in the URL:

$ fossil clone https://userid:password@mde2a2.kmol.info/cdag1 cdag1.fossil

fossil push 指令

fossil remote-url off 之後, 或 autosync

fossil push https://userid@mde2a2.kmol.info/cdag1

接著輸入與 userid 對應的密碼

http://brandon.invergo.net/news/2013-07-11-A-quick-introduction-to-version-control-with-Fossil.html

實際利用 cmsimfly 倉儲操作

fossil clone https://mde2a2.kmol.info/cmsimfly/ cmsimfly.fossil

cd wd

fossil open ./../cmsimfly.fossil

利用 Leo Editor, 進行內容改版.

以遞迴方式納入全部的變更.

fossil add .

假如 fossil clone 後綁定 scrum1 以外的用戶帳號, 利用 fossil remote-url off 切斷此一綁定.

fossil remote-url off

以 fossil commit 進行提交, 並確認綁定 scrum1 帳號.

fossil commit --user-override scrum1 -m "commit message"

內容 fossil commit 將會同時 fossil push 版本到 remote url.

假如 autosync 設為 off, 則以下列指令進行 fossil push.

fossil push https://scrum1@mde2a2.kmol.info/cmsimfly

輸入 scrum1 的對應密碼後完成版本推送.

在 Fossil SCM 系統上的 CMSimfly 倉儲.

實際操作範例

從遠端 clone 倉儲

fossil clone https://userid:password@mde2a2.kmol.info/cmsimfly cmsimfly.fossil

在當下目錄中解開最新的 cmsimfly.fossil 倉儲版本, fossil 仍會指定近端對應帳號的密碼

在近端建立工作目錄

fossil open cmsimfly.fossil

對 cmsimfly 倉儲中的內容改版後, 納入所有的變更

fossil add .

若 autosync 仍為 on, 則 fossil commit -m 後, 會同時 fossil push

fossil commit -m "message"

假如近端工作目錄需要從 remote url 中取下近端沒有的改版內容, 使用 fossil update

fossil update

fossil 改版工作流程

若以 fossil clone https://userid@mde2a2.kmol.info/cmsimfly cmsimfly.fossil

輸入 userid 在 https://mde2a2.kmol.info/cmsimfly 倉儲中的對應密碼.

則隨後都將以 userid 為主體進行改版, 若密碼存在近端, 則可以直接改版後 fossil commim -m, 讓 autosync 將內容 push 到遠端

若在 fossil clone 時沒有指定帳號密碼, 則將取得第一個內建管理者帳號對應之工作環境, 若之後要採用其他帳號提交, 必須先以 fossil remote-url off 切斷目前的連結, 當 fossil commit --user-override another_userid -m 之後, 以手動進行 fossil push https://another_userid@mde2a2.kmol.info/cmsimfly

輸入 another_userid 在 https://mde2a2.kmol.info/cmsimfly 倉儲中的對應密碼後, 即可完成改版推送.

fossil branch

[http://fossil-scm.org/xfer/doc/trunk/www/branching.wiki]

衝突處理

當使用者利用 autosync on 且以 fossil commit -m 進行改版提交時, fossil 會回復 would fork. "update first or use --alow-fork

表示使用者有兩個選擇, 可以在提交後面加上 --alow-fork 從上一個版本長出另外一個 leaf, 也就是建立 fork 版本, 而讓原本產生衝突的版本成為另外一個 leaf.

或者可以使用 fossil update 拉回遠端的版本. 接著 fossil 發現版本內容有衝突, 會顯示

WARNing: 1 merge conflicts. 並且說明可以用 fossil undo 除去 fossil update 所拉回的版本內容.

以下為 README.md 檔案中註記衝突的範例:

# cmsimfly
CMSimfly is a simple CMS in Flask

此一版本以 Fossil SCM 進行管理

透過 Wiindows 7 進行改版
<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<

故意造成衝突
======= COMMON ANCESTOR content follows ============================
======= MERGED IN content follows ==================================

在 Windows 10 中改版>>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

操作者必須手動決定要保留兩個版本內容, 或者取其中一版的內容.

因為衝突產生時, fossil update 拉回衝突內容時會同時新增 -original -baseline -merge 等3個檔案, 若希望使用 fossil add . 新增所有改版內容, 但不要納入某些目錄中的檔案, 可以在 web 介面中的 settings 中的 ignore-glob 中進行註記, 若設定 ignore-glob 後仍希望新增所有改版內容 (包括 ignore-glob 中的註記檔), 則使用 fossil add .

Fossil SCM Server 基本設定

當在 Windows 中以 fossil server, Ubuntu 中以 fossil http 啟動伺服器之後, 首先要在網際介面中以管理者登入, 並在 Admin-Configuration 或 setup_config 中設定 Project Name.

接著則在 Wiki 中建立與 Project Name 相同名稱的首頁 wiki.

之後利用 Admin-Users 建立其他用戶.

假如要修改 Fossil Server 的整體外觀, 利用 Admin-Skins, 可以透過其中的 Headers 增加客製化的內容連結表單.

假如要在 Wiki 頁面中使用較為保守安全的超連結, 編輯時選用 Fossil Wiki 格式, 若要納入 iframe 標註, 則可以改用 Markdown 格式, 若確認各用戶對於網際架構安全有一定認知, 則可以透過 Admin-Configuration 中, 勾選 Use HTML as wiki markup language, 則可以支援全部的 html 語法內容, 包括各式的 Javascript 內容.

純 IPv6 環境下的 Fossil Server

針對只採用 IPv6 協定上網的電腦中啟動 Fossil Server, 使用者可以使用 ssh 協定執行 fossil clone.

例如: ipv6.only.server domain 所屬的伺服器, 其操作系統僅啟用 IPv6 協定上網, 建立 Fossil Server 的模式與 IPv4 上網的伺服器相同, 但是, fossil clone 的指令則可採用 ssh 協定下的絕對倉儲路徑或相對倉儲路徑擷取遠端的倉儲檔案:

以絕對倉儲路徑 fossil clone:

假設 IPv6 主機上的 target.fossil 倉儲檔案位於 /home/account/repository/target.fossil, 則使用者可以利用:

fossil clone ssh://account@your_ipv6_only_server_url//home/account/repository/target.fossil cloned.fossil

將遠端的 target.fossil 複製到近端存為 cloned.fossil 檔案, 其中特別注意到絕對路徑在 server_url 後面必須有兩個斜線.

以相對倉儲路徑 fossil clone:

此時假設 Fossil Server 是以 /home/account 用戶啟動, 則使用者可以利用:

fossil clone ssh://account@your_ipv6_only_server_url/repository/target.fossil cloned.fossil

將遠端的 target.fossil 複製到近端存為 cloned.fossil 檔案, 其中特別注意到, 相對路徑除了在 server_url 後只需一個斜線, 且是以 /home/account 目錄作為相對目錄的根目錄, 使用者必須加入 /repository/target.fossil, 才能正確擷取到倉儲檔案.

上述兩種 fossil clone 指令執行後, 系統會要求輸入與 account 用戶對應的 Fossil Server 密碼, 完成後就可以將遠端的倉儲檔複製到近端.

附帶說明: 截至 fossil 2.2 版, 以 ssh 協定可以 fossil clone 遠端純 IPv6 主機上的倉儲, 但是卻無法以 fossil autosync 或 fossil push 將近端的版本提交推送到遠端. 因此目前的 Fossil Server 仍建議採用 IPv4/IPv6 並存的方式建立.