在VS項目中通過GIT生成版本號作為編譯版本號


上一篇博客寫了如何在 .Net 項目使用 SVN 作為版本控制工具時生成與代碼對應的組件版本號。雖然在公司一直使用 SVN ,但我卻對 GIT 情有獨鍾(可能要歸功於那段搗鼓 ROM 的時光),但少有文章提及如何具體在 Windows 平台來獲得版本號。這讓我有了迫切得到方法的希望。

上篇博客《在VS項目中使用SVN版本號作為編譯版本號

經過測試,該方法是可行的,以前驗證失敗的原因主要是打開了 AssemblyInfo.cs  文件,造成占用不可替換!

本文提供的方法還不完善,寫出來的目的是為了得到更多人的關注,也希望有大牛能指點一二。

將 GIT 的 commit 作為 . Net 項目編譯后生成dll的文件版本號主要有以下幾個困難。

1GIT 沒有一個數字的序號,而是一個SHA散列碼;

2GIT 提供的命令在 linux 十分方便,在 Windows 下需要額外的工具。

第一個問題好解決,我們取當前文件夾 commit 的次數加上截取一段 SHA 碼就可以作為文件版本號的最后一位。第二個問題目前想到的方法是調用 msysgit 提供的 Git Bash 來執行命令。

好了,首先我們依舊得找到 msysgit 的安裝目錄,一查之下頭就大了,各個地方的路徑都感覺不靠譜,最后還是選用了

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Git_is1InstallLocation 

(本來是想通過 temp 環境變量來取值的,查看 GIT 源代碼好像也有寫入,后來在自己電腦里卻找不到)

注:經驗證,與安裝選項有關,如果希望簡單的話在安裝時選擇一下可以省很多事情!

然后參照 Git Bash 的快捷方式拼接了下 call 的語句。

然后寫了一個 sh 文件來獲得版本號,並保存到文件:

1 # file name: git_ver.sh
2 #!/bin/bash 
3 VER_FILE=git_version.tmp
4 LOCALVER=`git rev-list HEAD | wc -l | awk '{print $1}'`
5 VER=r$LOCALVER
6 VER="$VER $(git rev-list HEAD -n 1 | cut -c 1-7)"
7 GIT_VERSION=$VER
8 echo $GIT_VERSION>$VER_FILE
View Code

 

在批處理里取出剛保存文件的值,接下來的工作就和使用 SVN 里的差不多了,唯一的區別是我們要自己實現關鍵字的替換。

上篇博客《在VS項目中使用SVN版本號作為編譯版本號

我們建立以一個 AssemblyInfo.tpl 作為替換使用的模板,由於 AssemblyInfo.cs 中除了固定的值外還有類似 GUID 變化的值,所以我們不能全部替換,因此僅將需要修改的部分放在 tpl 中,內容如下:

[assembly: AssemblyVersion("1.0.0.0")]

[assembly: AssemblyFileVersion("1.0.0.GITVERSION")]

自己替換 GITVERSION 字段為前面取到的版本號。

接下來使用批處理替換原來的 AssemblyInfo.cs 文件,為了在每次編譯時都自動替換,我們把調用批處理的命令卸載項目生成事件的生成前事件中:

"$(TargetDir)BeforeBuildProject.bat" $(ProjectDir) $(TargetDir)

批處理代碼:

 1 ::-------------------------------------------------
 2 :: <sunmary>
 3 :: 根據指定工作目錄信息和模板生成目標文件
 4 :: </sunmary>
 5 :: <param name="WorkDir">工作目錄路徑</param>
 6 :: <param name="Template">模板文件路徑</param>
 7 :: <param name="target">生成目標文件的路徑</param>
 8 :: <returns>執行結果</returns>
 9 ::=================================================
10 
11 ::-------------------------------------------------
12 :: * Initialize *
13 @ECHO OFF
14 ::SetLocal EnableExtensions
15 setlocal enabledelayedexpansion
16 
17 Rem Initialize Script arguments
18 SET WorkDir=%1
19 SET target=%2
20 
21 Rem Initialize Constants
22 SET AssemblyInfo=ASSEMBLY_INFO.tmp
23 
24 Rem GoTo Main Entry
25 GOTO Main
26 ::=================================================
27 
28 ::-------------------------------------------------
29 :: * Main Entry *
30 :Main
31 Rem Check arguments
32 IF %WorkDir%=="" GOTO ARGUNENT_ERROR
33 IF %target%=="" GOTO ARGUNENT_ERROR
34 PushD %WorkDir%
35 
36 Rem Search TSVN Path
37 
38 For /f "tokens=1* delims=_" %%1 in ('reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Git_is1" /v "InstallLocation"^| findstr /i "InstallLocation"') Do (
39   For /f "tokens=1*" %%3  in ("%%~2") Do (
40     SET GIT_PATH=%%4
41   )
42 )
43 
44 COPY /y "%target%git_ver" "%WorkDir%git_ver"
45 
46 SET GIT_PATH="%GIT_PATH%bin\sh.exe" --login -i
47 call %GIT_PATH% %WorkDir%git_ver
48 
49 for /f "delims=" %%i in (%WorkDir%\git_version.tmp) do (set VERSION=%%i)&(goto :next)
50 :next
51 DEL /Q "%WorkDir%\git_ver">NUL
52 DEL /Q "%WorkDir%\git_version.tmp">NUL
53 
54 Rem Generate a template file
55 
56 COPY /y "%WorkDir%\Properties\AssemblyInfo.cs" "%WorkDir%\Properties\AssemblyInfo.cs.bak">NUL
57 SET FILESTR="%WorkDir%\Properties\AssemblyInfo.cs"
58 FindStr /v "AssemblyVersion AssemblyFileVersion" %FILESTR%>%AssemblyInfo%
59 
60 For /f "delims=" %%k In (%target%\AssemblyInfo.tpl) do (
61   set str=%%k
62   set str=!str:GITVERSION=%VERSION%!
63   echo !str! >> "%AssemblyInfo%"
64 )
65 
66 COPY /y "%AssemblyInfo%" "%WorkDir%\Properties\AssemblyInfo.cs"
67 GOTO SUCCESS
68 ::=================================================
69 
70 ::-------------------------------------------------
71 :: * Error Handlers *
72 :ARGUNENT_ERROR
73 ECHO 傳入的參數無效。
74 GOTO FAIL
75 
76 :UNKNOE_ERROR
77 ECHO 未知錯誤。
78 GOTO FAIL
79 ::=================================================
80 
81 ::-------------------------------------------------
82 :: * Program Exit *
83 :FAIL
84 DEL /Q "%AssemblyInfo%">NUL
85 ::IF EXIST "%WorkDir%Properties\AssemblyInfo.cs.bak" (COPY /y "%WorkDir%Properties\AssemblyInfo.cs.bak" "%WorkDir%Properties\AssemblyInfo.cs"&DEL /q "%WorkDir%Properties\AssemblyInfo.cs.bak")>NUL
86 ECHO "error"
87 popd
88 EXIT 1
89 
90 :SUCCESS
91 DEL /Q "%AssemblyInfo%">NUL
92 ECHO "success"
93 popd
94 EXIT 0
95 ::=================================================
View Code

 

如果一切順利的話,應該就可以得到想要的結果了,可是……

替換文件竟然發生在生成后,也就是說 VS 在批處理執行結束前就已經編譯生成了,這樣文件版本號就只能在下次生成才會生效。上篇文章說的每次版本號都會增加的缺陷就無法那樣解決了。

當然你也可以為每個 AssemblyInfo.cs 文件生成備份,批處理通過備份文件產生 AssemblyInfo.cs ,這樣可以把 AssemblyInfo.cs 排除到項目外。版本號也就不會因此迭代增加了。

對於疑問的一個猜想是:因為我在批處理中調用了 Git Bash ,導致 VS 以為批處理執行結束而繼續了生成。

希望大家能提出其它想法或者驗證我的猜想,有解決方案那就再好不過了。

慣例附上所有代碼:點擊下載

 

本文來自 NewIdea 的博客,作者 Carey Tzou 。

原文地址:http://www.cnblogs.com/NewIdea/p/GITVersion.html

轉載請注明出處,否則拒絕轉載!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM