2006/06/28

台北好吃炭烤店 - 一心堂

曾幾何時林森北路七條通的小巷子成為燒烤店的聚集地。剛回台灣時,第一次去這條林森北路的小巷子吃烤肉就驚艷了。原來只要報育X龍那條巷子,幾乎是無人不知、無人不曉。

第一次去時沒啥概念,那時還是烤肉吃到飽,跟老友兩隻大肚吃了最少十幾盤牛五花,從此也愛上了燒烤店。

約200度的炭火熱烤不到一分鐘,翻個面涮一下火,六分熟的牛五花就可以享用啦。看看那均勻的油花,不用說就知道入口時的那種幸福的甜味啦。

全台比來比去,還是這條巷子的最好吃,尤其推薦一心堂這家比較沒名氣的小店。服務好、東西讚,依照我自己的實際經驗,對面那家人人皆知、更有名的真的是遜掉囉。

每次去一心堂大惦燒烤後,沒啥好說,就是一個爽字可以形容。吃的還是台灣好...

btw, 走回林森公園地下停車場,新生北路上那家新開的黑糖冰店也超讚喔 - 解油剛剛好。

2006/05/26

台中香蕉新樂園

台中香蕉新樂園這家茶館和餐廳 (http://www.vernaldew.com.tw/) 是台中市近來很少見最特別的店家之一,這整棟大型的建築物裡面包含了將60年至80年前的街道重新造景在裡面,有清朝及日據時代的店面,還有其中一位股東收集的數百件古董,包括了老舊的信箱、路牌、海報、四十年的計程車、腳踏車、相片以及設備齊全的寫真館、牙醫診所、甘仔店、理髮店、及電影院。

大約有250個座位可提供顧客沿著這條街道或店面內享用多樣的台式套餐像是牛肉飯、東坡肉飯等,約180元,還有其他的點心及餐點。也提供一般的冰熱各式茶、咖啡、飲料,另外還有四至十人座的包廂。台灣香蕉新樂園人文生活館離孔廟很近,就在對面。

2006/05/04

情感的設計

這幾年來,設計變成了一門顯學。不論是哪個產業,都開始強調設計的重要性。

看看這期IDEO公司的這篇文章,你會發現,設計絕對不像我們刻板印象中所想的一樣,只是視覺或美感的層次而已。

對全球設計界首屈一指的企業IDEO來說,設計是在為使用者解決背後隱藏的問題。這家公司創立十五年來,美國商業週刊的年度產品設計獎首獎,年年都由它包辦。

它把設計的重點從創造產品,擴大到創造經驗上。例如,美國一家醫院希望藉由它的協助,找出節省成本、吸引病患的方法。原來以為可能會需要改建新大樓、配備新科技設備,沒有想到,IDEO帶領醫院工作人員深入觀察病患看病流程後發現,只重新設計病人掛號流程,更新候診室,就能收到很大的成效。

因為要把設計從創造產品擴大到創造經驗,因此IDEO刻意聘用背景多元的員工,設計團隊包含設計師、工程師、心理學家、人類學家等。

在設計的過程中,IDEO所依靠的絕對不只是創意和靈感,還包含更多科學的流程和紀律。例如,它有嚴密的五個步驟,第一個步驟就是好好觀察顧客使用產品的經驗,甚至自己變成顧客。第二個步驟是腦力激盪:它嚴格要求參加的人不能說,「這點子不錯,『但是』……」;而要說「這點子不錯,『還有』……」。


某個程度來說,IDEO已經不是一家設計公司,而是一家管理顧問公司,它所做的很多事情,都是在幫助企業改變思維模式(EMBA雜誌第237期第六八頁)。

關於改變,是另外一門很大的學問。

在公司裡,不論是導入一個資訊系統,或推出一個人力資源方案,往往都會遭遇很大的抗拒。有經驗的經理人都知道,不順利是常態,能夠順利推動,才是奇怪的事情。在變革行動的中期,阻力往往也特別大,也就是當開場的鑼鼓喧天熱度降低,員工開始精神不濟、注意力渙散的時候。

要怎樣才能讓「改變」不偏離軌道,變革之火不熄滅呢?管理顧問Eric Beaudan提醒我們,這個時候,要重新思考變革的目標和期望,並且改變速度。

例如,也許你的變革速度太慢,讓人不耐,或者恰恰相反,你速度太快,讓人員跟不上。此外,也許你必須設法添加刺激,或者創造危機,讓人們重新把注意力投注在這個變革行動上(EMBA雜誌第237期第三六頁)。

畢竟,就像IDEO創辦人凱利所說:「設計代表的是產品的情感層次。」變革處理的,又何嘗不是人的感情層次?

2006/04/11

What Is A Permission, by Keith Brown

http://www.pluralsight.com/wiki/default.aspx/Keith.GuideBook.WhatIsAPermission


Throughout my discussions of access control and ACLs in this book, I will often talk about permissions as numbers. For example, I might talk about 0x1FF as being a set of permissions, or granting "permission 1 and 2" to someone. What I'm doing is being very generic and using literal access masks or numbered permissions. I'm not specifying just what types of objects I'm talking about; I'm just talking about how access control works for all different types of objects.


So let's make this concrete and look at some examples of permissions for some specific types of objects in Windows. Let's start with, oh, a registry key. Peeking at a Win32 header file called winnt.h shows us the following1:

 // excerpt from winnt.h
#define KEY_QUERY_VALUE (0x00000001)
#define KEY_SET_VALUE (0x00000002)
#define KEY_CREATE_SUB_KEY (0x00000004)
#define KEY_ENUMERATE_SUB_KEYS (0x00000008)
#define KEY_NOTIFY (0x00000010)
#define KEY_CREATE_LINK (0x00000020)

Let's also look at the permission definitions for a thread:

 // excerpt from winnt.h
#define THREAD_TERMINATE (0x00000001)
#define THREAD_SUSPEND_RESUME (0x00000002)
#define THREAD_GET_CONTEXT (0x00000008)
#define THREAD_SET_CONTEXT (0x00000010)
#define THREAD_SET_INFORMATION (0x00000020)
#define THREAD_QUERY_INFORMATION (0x00000040)
#define THREAD_SET_THREAD_TOKEN (0x00000080)
#define THREAD_IMPERSONATE (0x00000100)
#define THREAD_DIRECT_IMPERSONATION (0x00000200)

If you wanted to grant Alice permission to create a new registry key under some existing key, you'd edit the existing key's DACL and add an ACE ( What Is An Access Control List ) that grants Alice the KEY_CREATE_SUB_KEY permission. Pretty simple. But look at those permissions again and tell me how you'd grant Alice the permission to delete the key she just created!


That's right, the registry subsystem doesn't bother defining a permission for deleting a key. That's because it's such a common permission (most secure objects can be deleted) that it's included as part of a standard set of permissions that are common across all types of objects. Here are the standard permissions that are allowed to be put in an ACL:

 // excerpt from winnt.h
#define DELETE (0x00010000L)
#define READ_CONTROL (0x00020000L)
#define WRITE_DAC (0x00040000L)
#define WRITE_OWNER (0x00080000L)
#define SYNCHRONIZE (0x00100000L)

Compare the numerical layout of the standard permissions to the specific permissions defined for registry keys. Note how the standard permissions all fall in the upper word of the 32 bit mask, while the specific permissions are defined in the lower word. Notice the same technique is used for the thread permissions. You see, each class of object is allowed to define up to 16 specific permissions, and they must all be in that lower word, so they don't conflict with permissions Microsoft has already defined for all objects, such as the standard permissions shown above.


The standard permissions are really quite straightforward. Let me briefly explain what they mean. READ_CONTROL ("Read Permissions") controls whether you can read the owner and DACL in the object's security descriptor. If you don't have this permission, you're not even allowed to see what permissions you do have! WRITE_DAC ("Write Permissions") and WRITE_OWNER ("Take Ownership") say whether you're allowed to change the object's DACL or take ownership of the object by changing the owner SID to be your own SID (for more detail, see What Is Ownership ). SYNCHRONIZE says whether you can wait on an object (this is most often used with synchronization objects such as a mutex or semaphore). By limiting SYNCHRONIZE access, you can prevent an untrusted user from grabbing a mutex that your program depends on and deadlocking you. And DELETE is pretty obvious.


Let's say you want to grant Alice permission to read a registry key. It'd make sense to grant her a combination of the following:



  • KEY_QUERY_VALUE
  • KEY_ENUMERATE_SUB_KEYS
  • KEY_NOTIFY
  • READ_CONTROL

If you binary OR these values together, you'll end up with 0x00020019. This would be the access mask you'd put into the ACE ( What Is An Access Control List ) to grant Alice read access to the key. For an example of code that modifies an ACL programmatically, check out How To Program ACLs .


Look at the following access mask and try to figure out what it means: 0x00130000. The answer is in the following footnote2. Now try to decode this one: 0x00000001. Surely this one is easier! Oh wait, I didn't tell you what type of object we're talking about. I mean, if it were a registry key, this would be KEY_QUERY_VALUE -a fairly benign permission to grant, at least compared to THREAD_TERMINATE! You see, given a random permission mask, you really can't tell what it means unless you know the type of object to which it applies, unless it simply consists of standard permissions, which are defined centrally for all objects.


With this in mind, think about a permission mask that would be generic enough to grant read permission to any type of object in the system, including registry keys and threads. For a registry key, we'd want 0x00020019, as we calculated earlier for Alice. But for a thread, it'd be 0x00020048. That's a very different mask. As you can see, because no two types of objects can be expected to have the same sorts of permissions, at first glance it'd be impossible to treat objects polymorphically with respect to permissions. But if you look a bit further into winnt.h, you'll find the following rather interesting definitions:

 // excerpt from winnt.h
#define GENERIC_READ (0x80000000L)
#define GENERIC_WRITE (0x40000000L)
#define GENERIC_EXECUTE (0x20000000L)
#define GENERIC_ALL (0x10000000L)

What do you think would happen if you added an ACE to a registry key's DACL that granted Alice GENERIC_READ? Think about it for a moment. If you guessed that the system would convert the access mask from 0x80000000 to 0x00020019 before storing the new DACL in the metadata for the registry key, then you'd be correct. You see, each class of object in Windows defines a mapping from these four generic permissions onto standard and specific permissions. This allows us to make statements like, "By default, I'd like to grant full control to SYSTEM and myself for any object I create. Oh and I'd also like Alice to have read access as well." Here's a text representation of just such a DACL:

 grant SYSTEM 0x10000000
grant Keith 0x10000000
grant Alice 0x80000000

It turns out that Windows makes a statement like this for every process! You see, inside the token ( What Is A Token ) is a default owner and DACL that are used whenever you create new objects3. For example, if you were to create a thread, how would the system know what the DACL for that thread should look like? Well, it looks at this default DACL that's tucked away inside your token.


Here's what a default DACL would look like for me on my laptop4:

 grant SYSTEM 0x10000000
grant Keith 0x10000000

So by default, any new threads that I create, or semaphores, shared memory sections and so on, start life with DACLs that specifically grant my account and SYSTEM full control. Nobody else will be able to touch the objects I create, barring specially privileged users such as administrators ( What Is A Privilege ). Note that hierarchical systems like the file system and registry instead use ACL inheritance to come up with a default DACL; this ensures that permissions remain consistent through the branches of the hierarchy. See What Is ACL Inheritance for the details.


The default DACL is one of the few mutable bits of data in a token. In most cases you shouldn't ever need to change this DACL, as it's already about as tightly secured as it can be. If you ever find the need to adjust it, you'll want to look at the Win32 function SetTokenInformation.




  1. I've omitted three permissions that are specific to 64-bit Windows for brevity.
  2. DELETE, READ_CONTROL, and SYNCHRONIZE.
  3. By "objects" I mean any object that has a security descriptor ( What Is A Security Descriptor ), such as a process, thread, mutex, etc.
  4. If you want to do this experiment, you should download the Token Dump component from my website. I don't know of any built-in tool that shows this information.

2006/04/06

美國富豪唐納川普一手策劃熱門的真人實境秀 - Apprentice (誰是接班人)

2004年美國最熱門的真人實境秀『誰是接班人』,是由經歷金融風暴又鹹魚翻身的美國富豪唐納川普所一手策劃的全新節目。在節目中,川普找來十六位參賽者,每週進行比賽。題目由全美五百大企業提供,包括從路邊賣檸檬汁到廣告企劃,非常多元。

比賽的方式十分簡單,十六位參賽者分成兩組,每星期要想辦法解決川普所出的難題,輸的一方要淘汰一名組員。最後勝利者,可以獲得任職於川普旗下公司的機會,而且年薪高達六位數美金。

繼第一季創造了"You're fired."的名言之後,川普在第二季請出財富雜誌前五百大企業,給予參賽者比第一季更嚴酷、更高難度的行銷挑戰,包括為年營業額上千億的電子公司上電視現場推銷產品、幫知名牙膏大廠在一周內開發出新口味、建立行銷通路等,更多想像不到的商場致勝秘訣從第二季一一登場。這次總計十八人參賽,有長春藤名校的高材生,也有連高中都沒畢業的小老闆。他們每星期想辦法解決川普所出的難題,輸的一方要淘汰一名組員。最後勝利者,同樣可以獲得負責川普旗下公司的機會,年薪高達六位數美金。這些參賽者再度引爆精采的職場爭鬥戰!

Apprentice Theme: "for the love of money"-The O'Jays

The Apprentice Rules: http://www.theapprenticerules.com/

The Apprentice Blog: http://www.theapprenticeblog.com/

Official site for season 2: http://www.nbc.com/nbc/The_Apprentice_2

Official site for season 3: http://www.nbc.com/nbc/The_Apprentice_3

Official site for season 4: http://www.nbc.com/The_Apprentice_4

2006/03/13

Problem:: VS2005 - The current identity does not have write access to temporary file...

I finally powered up again with my newly purchased dual-core laptop, which also enables me to refresh software installations that I've been wanting to do for a long time.  As I'm putting things back together, I kept running into this error with my projects:

The current identity (xxx\ASPNET) does not have write access to 'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files'.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.


Here's a quick fix to the problem (do this only to your dev box):

1. From the framework directory (Usually c:\windows\microsoft.net\framework\v2.0.50727\Config), modify machine.config:

<processModel userName="SYSTEM" password="autoGenerated"/>

2. Execute this command:


> aspnet_regiis -ga "ASPNET"

By applying MS's Web updates (often times including security patches), or putting you box into domain (which I am), the security constriant of your windows install drive got stricted.  If you read the prompt from aspnet_regiis carefully, switch -ga is granting the daemon user access to the IIS metabsae and other directories used by ASP.NET, which is exactly what I'm looking to do..

Further Reading:
Microsoft's KB: http://support.microsoft.com/kb/315158/

2006/02/15

Subversion for Windows 安裝指南

PDF download: Subversion for Windows 安装指南

this post is an updated version from Huanlin Tsai's revision 1.41 (http://huanlin.dyndns.org:8080/techshare/articles/2004061303/svn_install.htm)

摘要: 版本控制在軟體工程的領域中隸屬於軟體建構管理(Configuration Management)的範疇,是軟體開發流程當中相當基本且重要的一環,因此版本控制系統可說是開發人員必備的工具之一。本文將介紹一個開放原始碼的版本控制系統:Subversion,說明相關工具的安裝步驟,並且透過實例操作示範如何在Visual Studio .NET 2003裡面對專案進行版本管理。

Subversion 是一個自由/開放源碼的版本控制系統,也就是說 Subversion 管理著隨時間改變的檔案,這些檔案放置在一個中央檔案庫(repository) 中,這個檔案庫,很像一個尋常的檔案伺服器,不過它會記住每一次檔案的變動。這樣你就可以把檔案回復到舊的版本,或是瀏覽檔案的變動歷程,許多人會把版本控制系統想像成某種“時光機器”。

本文目的:

  • 在 Windows 2003 Server 上安裝及設定 Subversion,以便於團隊成員透過 Internet 協同開發軟體專案,並有版本控管功能。
  • 在用戶端安裝 Subversion 的 Client-side 工具:TortoiseSVN,可以整合與檔案總管整合在一起,利用 GUI 方式提供了建立檔案庫、以及匯入、匯出等功能。

本文提供一個簡易的安裝指南,說明在 Windows 環境下安裝 Subversion 伺服器的步驟,以及 TortoiseSVN 用戶端工具的安裝步驟。


1. 簡介

Subversion 是一個版本控制系統,它是根據 CVS(Concurrent Versions System)的功能為基礎來設計,但是改進了一些 CVS 的缺點,例如:在CVS中搬移檔案目錄很不方便,Subverion 則連目錄的異動都納入版本管理;此外,它也增加了其他的功能,例如:不可分割的送交(如同資料庫交易的概念,送交多個檔案時,若有任何一個檔案失敗,則這次送交的所有檔案都不會進入檔案庫中)、支援多種網路協定、一致的檔案差異比對(不管什麼檔案類型,均使用二進位差異比對方式)等等。

由於目前手邊查到的 Subversion 文件,主要都是針對 Unix用戶來撰寫,所以這份文件特地針對 Windows環境下安裝 Subversion 的步驟來說明,希望透過這份文件,能夠幫助你很快的把Subversion安裝起來。

在安裝過程中,會需要輸入一些命令列的指令,本文不會詳細解釋某些指令的用途和意義,因此你除了要熟悉 DOS 的基本指令,還應該隨時查閱 Subversion 的電子書(有中文版),以了解 Subverion 命令列工具的使用方法。圖形化介面雖然方便,但是熟悉命令列工具的使用,才能讓你得到完全的自由。

1.1 基本觀念

如果你缺乏版本控制系統的基本觀念,就算能夠順利安裝好 Subversion,可能安裝完成後就不知道下一步怎麼做了。這裡只簡單的提一點必要的基礎觀念,記住你最終還是得閱讀 Subversion 的官方文件。

1.2 作業環境與軟體版本

以下是本文件使用的作業環境與軟體版本

  • Windows 2003 Server with SP1
  • Apache HTTP Server v2.0.55
  • Subversion v1.2.3
  • TortoiseSVN 1.2.6 build 4786
2. 安裝與建立 Subversion 伺服器

請準備一台穩定的機器,作為 Subversion 的伺服器。

2.1 安裝 Apache HTTP Server

http://httpd.apache.org/ 下載 Apache HTTP Server 2.0 版 for Windows 的安裝程式,我下載的檔案是 apache_2.0.50-win32-x86-no_ssl.msi。

下載之後直接安裝,安裝過程很簡單,就不贅述了,但安裝之前請先檢查你的電腦是否有安裝 IIS,由於 Apache 預設使用 80 port,會跟 IIS 的網站衝突,你必須把 IIS 的 Web 站台關閉,再安裝 Apache HTTP Server。

安裝完成以後,開啟瀏覽器,瀏覽網址 http://localhost/ 看看有沒有出現安裝成功的網頁。

2.2 安裝 Subversion

1. http://subversion.tigris.org/下載最新版的 Subversion,你可以下載 .zip 或者打包好的自動安裝程式,我下載的是檔案svn-1.2.3-setup.exe。

2. 下載後直接安裝,安裝過程都是下一步,沒什麼特別的。在此Windows安裝版增加了Apache modules的選項,必要的環境變數都幫你設定好了。

2.2.1 手動安裝Apache modules

以下步驟敘述手動安裝Apache modules的程序(如果你下載的是 .zip 檔,就要自行設定)。
  1. 把 $SVN_Install/bin/目錄下的 mod_dav_svn.so、 mod_authz_svn.so複製到 $Apache2_Install/modules/目錄下。
  2. 把 $SVN_Install/bin/目錄下所有的dll檔複製到 $Apache2_Install/bin/。
  3. 接著用文書編輯器開啟 Apache HTTP Server 的 httpd.conf(在 /conf/ 目錄下),尋找一堆 LoadModule 指令,先找到以下兩行:
    #LoadModule dav_module modules/mod_dav.so #LoadModule
    dav_fs_module modules/mod_dav_fs.so 把前面dav_svn_module的 '#' 字元刪除,然後把下面幾行文字加到這群 LoadModule
    指令的後面: LoadModule dav_svn_module modules/mod_dav_svn.so LoadModule authz_svn_module
    modules/mod_authz_svn.so

  4. 重新啟動 Apache HTTP Server。

    問題排除: 如果 Apache HTTP Server 無法啟動,請依下列步驟檢查:
    1. 檢查 Subversion 的路徑是否有在系統的%PATH% 環境變數裡面。
    2. 檢查你加入 httpd.conf 裡的項目是否正確,記住 mod_dav_svn.so 和 mod_authz_svn.so必須在其他 mod_dav*.so 模組之後載入。
    3. 檢查你加入的檔案。若dll檔沒有在正確位置,將無法正常啟動。

2.3 設定 Subversion 檔案庫的路徑

現在要設定Apache http.config檔中 SVN URL 路徑與檔案庫實體路徑的對應關係。對應的方式有兩種,分別是 SVNPath 與 SVNParentPath。

2.3.1 SVNPath

SVNPath 適合用來個別指定檔案庫的路徑,語法是:

DAV svn SVNPath /absolute/path/to/repository

其中 "/svn/repos_name" 就是用戶端存取特定檔案庫的 URI(Uniform Resource Indentifier),SVNPath 後面指定的路徑則是檔案庫的絕對路徑,假設我們的檔案庫實際存放的路徑是 d:\svn\MyProject,並且希望用戶端使用 http://myserver/svn/myprj 的 URL 來存取檔案庫,那麼要加入 httpd.conf 的內容就是:

DAV svn SVNPath d:\svn\MyProject

注意 Location 標籤後面的 /svn/myprj 的第一個斜線不可少!

2.3.2 SVNParentPath

如果你的檔案庫都集中放在某個目錄之下,例如:d:\svn,那你就可以使用 SVNParentPath 的方式指定檔案庫的根路徑,例如:

DAV svn SVNParentPath d:\svn

這表示可以讓任何人都可以透過 http://myserver/svn/<檔案庫名稱> 的方式,存取位於 d:\svn 這個目錄以下的所有檔案庫。也就是說,這個設定動作只需要一次,如果使用SVNPath,你必須為各個檔案庫分別指定對應的路徑。

以上兩種設定方式都可以,方便起見,這裡我用 SVNParentPath 來統一指定所有檔案庫的父層 URL 路徑。

將 的設定加到 Apache HTTP Server 的 httpd.conf 檔尾就行了。接著便可以開始建立檔案庫。


2.4 建立Subversion檔案庫

假設我們要把所有的檔案庫都放在 d:\svn 目錄下,現在要建立一個測試用的檔案庫,名稱叫做 repository,指令為:

md d:\svn svnadmin create d:\svn\repository

命令執行完後,檢查看看 d:\svn\repository 目錄底下產生了哪些目錄和檔案。

警告:檔案庫絕對不可以在建立在任何遠端的儲存媒體上,例如:網路磁碟機。


這時候你已經建立了一個檔案庫,你可以先在本機用瀏覽器測試一下,網址輸入http://localhost/svn/repository,看看能不能看到檔案庫的內容,正常的話應該像下圖一樣。

如果以上的測試可以通過,應該就行了。如果你還想要測試一下能不能從檔案庫取出整個工作複本,可以執行下列指令(非必要):

c: cd\temp svn co http://localhost/svn WholeRepos

上述指令會切換到一個暫時的目錄 c:\temp,然後從檔案庫取出整個工作複本。最後一行指令是要 svn.exe 執行 check out 動作(縮寫 co),如果正確的話,應該會顯示 "Checked out revision 0." 的訊息,此時 /svn/
這個檔案庫底下的所有檔案目錄都已經取出,並且複製一份到c:\temp\WholeRepos 目錄下了。

問題排除 : 如果顯示的錯誤訊息是:svn: PROPFIND request failed on '/svn/repository'

svn: PROPFIND of '/svn/repository': 405 Method Not Allowed (http://localhost)

請檢查 Apache HTTP Server 的 httpd.conf 檔案裡面的 標籤所定義的位置是否跟你指定的URL
樣式相同,注意一定要完全相同,以上面的例子而言,你的 httpd.conf 的最後面應該會有以下文字:


DAV svn SVNPath 指向檔案庫的絕對路徑

如果顯示的錯誤訊息是: svn: PROPFIND request failed on '/svn svn: Could not open the requested SVN filesystem

那表示在 /svn 對應的實體目錄(即 d:/svn)下找不到所指定的目錄。

註:PROPFIND 是給 WebDAV 用的 HTTP method,用來從資源中取得屬性。


測試完畢就可以把 WholeRepos 這個目錄整個刪掉了。

到目前為止,可以確定檔案庫已經建立完成,接下來就可以匯入專案了。

2.4.1 匯入專案

不用急著把你現有的正式專案匯入檔案庫,先建立一個用來測試的專案目錄就好了。我們先在 c:/temp 底下建一個 ProjectA 的專案目錄結構,參考下面的指令:

c:\
md temp
cd\temp
md ProjectA
md ProjectA\trunk
md ProjectA\branches
md ProjectA\tags
svn import . http://localhost/svn
-m "Initial repository layout"

提示: 本文在執行 svn 命令時,都是使用 http 協定的方式,這樣我們可以確知 Subversion 與 Apache HTTP Server 的設定無誤,其他人就可以透過 Internet 存取檔案庫。當然你也可以用其他的協定,例如:file:///,如果使用 file 協定,最後一行指令就變成:

svn import . file:///d:/svn -m "Initial repository layout"


命令執行無誤的話,應會看到如下的畫面:

這時候 ProjectA 這個專案已經匯入檔案庫了,也就是說,其他使用者可以開始存取這個檔案庫的專案取出文件和程式碼了。你可以參考 Subversion 的官方手冊中關於 svn.exe 這個用戶端命令列工具的使用方法,多練習一下取出檔案、加入檔案、以及存入檔案等指令。萬一練習的過程中發生錯誤,或者檔案庫弄亂了,你可以把整個檔案庫的目錄砍掉,回到 2.4 節重新做一遍。

以下會進一步討論檔案庫和專案目錄結構的安排方式,如果你急著想試試看用戶端如何存取 Subversion 檔案庫,可以先跳到2.6 節或第 3 節。

2.5 檔案庫與專案的配置方式

延續前面的範例,如果你再匯入其他專案,例如 ProjectB,那麼整個檔案庫的結構會變成這樣:

/svn/repository/ +-- ProjectA/ +-- ProjectB/

也就是說 repository 這個檔案庫裡面包含了兩個專案。

如果你希望為每個專案建立一個檔案庫,那麼在 2.4 節中建立檔案庫的指令就變成:

md d:\svn svnadmin create d:\svn\ProjectA
svnadmin create d:\svn\ProjectB

這樣就變成有兩個檔案庫了,檔案庫名稱分別是 ProjectA 與 ProjectB。


提示 : 如果專案之間有共享的檔案,建議把這些相關的專案放進同一個檔案庫;如果專案之間彼此毫無關係,那就採用一個檔案庫放一個專案的方式,這種方式等於專案就是檔案庫。

第一種方式有個比較奇怪的「功能」你應該要知道,就是一個專案的 check in 動作,也會令其他專案的檔案的修訂版次遞增 ,如果這不是你想要的,請選擇第二種方式,即一個檔案庫只存放一個專案。

2.5.1 專案的目錄結構

這裡補充說明一下 ProjectA 的目錄結構。在 ProjectA 專案的根目錄下建立的 trunk、branches、和 tags 這三個目錄是有特別意義的,它們的作用分別是:

  • trunk 目錄用來存份目前專案正在進行開發的程式檔案和文件 (又稱為主線,即 mainline)
  • branches 用來存放主線的各個仍在發展中的分支;
  • tags 則用來存放已經不再變動的分支,也就是其中的檔案不會再修改了。

這是 Subverion 官方手冊建議的目錄結構安排方式,你可以自己決定要不要用這種配置方式,詳細說明請參考官方手冊的第五章,子標題為 "Choosing a Repository Layout"。

提示 : 目錄名稱建議盡量不要用中文名稱,這樣在使用命令列時比較方便,也比較不會有問題。


2.6 使用 Windows 網域帳戶驗證

照著前面的步驟做,你會發現存取檔案庫時都不用輸入帳號密碼,這是因為我們之前的設定沒有啟用身分驗證的功能。但是我們通常不希望所有人都能任意存取你的檔案庫,免得重要資產外洩,或者資料被破壞,因此了解如何加入身分驗證也是必要的。

Serversion 提供了多種驗證使用者身份的方式,這裡只介紹 Windows 身分驗證的方式,這種方式很適合用在開發團隊成員都在區域網路內的情況。請依下列步驟進行:


  1. 取得 SSPI 模組,下載網址為 http://tortoisesvn.tigris.org/mod_auth_sspi.zip
    英文說明在此:http://tortoisesvn.sourceforge.net/node/137
    http://tortoisesvn.sourceforge.net/docs/release/TortoiseSVN_en/ch03.html#tsvn-serversetup-apache-5
  2. 把 zip 裡面的 mod_auth_sspi.so 解壓縮到 modules 目錄下。
  3. 把下面這行加入到 Apache 的 httpd.conf 裡面:LoadModule sspi_auth_module modules/mod_auth_sspi.so
    注意上面加入的這行一定要放在下面這行的前面:LoadModule auth_module modules/mod_auth.so

  4. 修改httpd.conf 的設定如下:
    <Location /svn> DAV
    svn SVNParentPath d:/svn
    AuthType SSPI AuthName "Subversion 檔案庫"
    Require valid-user
    SSPIAuth On
    SSPIAuthoritative On
    SSPIDomain
    SSPIOfferBasic On

    其中 就是你的 Windows 網域控制器的電腦名稱(例如:WIN2KDC),注意兩邊的括號不用保留。如果你的環境沒有網域控制器,就維持原來的就行了。在我的環境下,我發現即使有網域控制器,但是這裡不去設定它,還是能夠正常的驗證使用者身分。
  5. 重新啟動 Apache。

現在開啟瀏覽器,輸入網址 http://127.0.0.1/svn/repository 看看,你預期應該會看到如下的驗證畫面:

若沒有出現這個畫面,而是直接顯示檔案庫內容,怎麼回事?

因為我們現在是使用 Windows 帳戶驗證,你目前已經登入這台機器了,而你要存取的也是本機的資源,換句話說,你的身分已經被驗證過了,所以就不會再要求你輸入帳號跟密碼,這是採用
SSPI 網域驗證的好處。

那麼,如果你的同事 John 的電腦有加入網域,但是他平時都是登入本機,而非登入網域,在存取檔案庫時會不會要求輸入帳號密碼?答案是如果 John 登入他本機的帳號和密碼跟他在網域使用者的帳號密碼完全一樣的話,就無需再輸入密碼;相反的,如果登入本機的使用者帳號和密碼與網域使用者帳號密碼不同,第一次存取時就必須輸入密碼。

你可以在別台機器上,用一個網域裡沒有的使用者帳號去存取 Subverion 檔案庫,如果正確的話,應該就會出現要求輸入帳號密碼的視窗。

以上還只是最基本的設定,如果你希望做些進階的設定,例如允許所有人都可以檢視檔案庫的內容,但是不能修改;或者要加入 SSL 加密機制,建議您參考 [TortoiseSVN 官方文件] 的第三章。


提示 : 啟用身分驗證之後,你會發現用命令列工具 svn.exe 存取檔案庫時,如果是用 http:// 協定,有些子命令(subcommand)執行時會出現 "authorization failed" 的錯誤,這時候你可以在
svn 命令中加入 --username 和 --password 來提供使用者名稱和密碼,例如:


svn co http://myserver/svn/ --username michael --password guesswhat

或者你也可以改用 file:/// 協定。

3. 安裝用戶端:TortoiseSVN

現在你已經有一個可以在http存取Subversion 的伺服器,可以試著在其他電腦上存取檔案庫了。如果你習慣使用命令列工具,那就只要在用戶端電腦上安裝 Subversion 就行了,存取檔案庫都是透過命令列工具(主要是 svn.exe)。這裡要介紹的是一個專門為 Windows 作業系統設計的 Subversion 用戶端:TortoiseSVN(以下簡稱 TSVN)。

3.1 安裝 TortoiseSVN

  1. 到 http://tortoisesvn.tigris.org 下載最新的安裝程式,下載後直接安裝。安裝過程大都是按下一步,只有在問你安裝完成後會要求你重新開機。
  2. 到 http://tortoisesvn.tigris.org 下載繁體中文的語言包(language pack),請注意語言包的版本應該要跟你安裝的 TSVN 版本相同,否則最好不要安裝。語言包裝完之後,用檔案總管在 Windows 桌面上或任何一個資料夾上點一下滑鼠右鍵,選擇 TortoiseSVN -> Settings 以開啟設定視窗,在 "Main" 頁夾中更改 Language 設定為「中文(繁體)」,再按「確定」鈕即可。
  3. 如果你是透過 proxy server 存取 Internet,請在 TSVN 的設定視窗中,切到「網路」頁夾,然後輸入你的 proxy server 相關資訊,否則你將無法存取位於 Internet 上的檔案庫。

安裝完成之後,在任何目錄名稱上點一下滑鼠右鍵都可以看到 TSVN 的功能選項,這也是 TSVN 方便的地方,它不用跟開發工具整合,而是跟作業系統整合在一起,這樣不管你用什麼開發工具,都可以輕鬆的使用 TSVN 來存取檔案庫。

接下來你可以用 TSVN 練習一下存取之前建立好的檔案庫,試著把你現有的專案匯入檔案庫中,並且在用戶端使用 TSVN 執行取出、存入、更新等動作。

TSVN 雖然是用戶端工具,不過它也提供了建立檔案庫、以及匯入、匯出等功能,因此安裝在伺服器端也挺方便的。

4. 結語

按照本文說明的安裝步驟,希望能讓你順利在 Windows 環境下把 Subversion 安裝起來。但是安裝成功以後,真正的工作要才開始,如果你沒有花點時間閱讀 Subversion 的相關文件,在使用版本控制系統的過程中,一定會碰到許多問題。

在正式將你的專案加入 Subversion 檔案庫之前,建議您多考慮一下:

  • 檔案庫的配置方式。究竟要為每一個專案建立一個檔案庫,還是把多個專案放進同一個檔案庫裡?
  • 專案目錄的結構。你要依照官方手冊的方式,在專案的根目錄下建立 trunk、branches、和 tags 嗎?
  • 哪些東西要放進檔案庫裡?

前兩個問題你可以參考 [Subversion電子書第五章] 的建議,再衡量自己的需求來決定。你不見得要依照官方的建議,第一次也許採用最單純的配置方式會比較好,例如:一個檔案庫就只放一個專案,而且只把程式的原始碼 放進檔案庫,也不去分主線支線了,因此專案的目錄結構可以很單純,程式原始碼的根目錄就是專案的根目錄。自己動手做過幾次以後,再去觀察檔案庫的內容,就會比較有感覺了,然後再來考慮自己團隊的需求,自然就能找到最適合自己團隊的配置方式了。

後記

原始發表人:蔡煥麟

延伸閱讀:

Mercury簡易改裝

有同好有一樣的困擾 - 如何使用自己的data logging軟體,因此寫了這篇來分享我的簡易改裝。 Background 雲豆子 MERCURY roaster 烘豆機的設計是使用自行開發的軟體,來:1. 操控風門/火力; 2. data logging/自動烘焙。 ...