基於python開發pre-commit hook達到對git提交時間的控制
近期公司開發使用的版本控制工具由svn轉向git,由於開發需求,經常會更改本地的時間,從而暴漏出一個原先使用svn不會出現的問題:commit的時間經常會不對。主要是因為git提交到遠端伺服器需要兩部曲commit-push,而commit時使用的是本地的系統時間,這樣就導致在修改本地時間之後,commit的時間就與正常時間對不上。現在希望開發一個指令碼實現在提交的時候檢查本地的時間是否正常,如果異常就阻止此次提交,以此來控制提交時間。
在定位好問題之後,確定使用git中pre-commit這個hook達到本地提交的時候檢查本地時間的目的。由於hook支援python,我對python又比較熟,所以決定使用python實現。
確定好以上問題之後,需要解決的問題是如何獲取到遠端伺服器的時間。由於公司統一在內網開發,所以開發機是無法連線到外網的,所以是無法直接獲取到外網的時間,於是考慮在內網搭建一臺ntp伺服器。搭建伺服器的教程參考:
#!/usr/bin/env python
#coding=utf-8
import time
import ntplib
import sys
import math
max_diff = 20 * 60 # 最大允許相差20分鐘
url = "time.windows.com" # 獲取時間的ntp伺服器
def STD(s_time):
return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(s_time))
def get_server_time():
try:
client = ntplib.NTPClient()
return client.request('time.windows.com').tx_time
except:
return -1
def judge_commit_time():
now = time.time()
server_time = get_server_time()
if (server_time <= 0):
print "遠端伺服器不可用,請確認當前系統時間!"
sys.exit(0)
elif (math.fabs(now - server_time) > max_diff):
print ("遠端伺服器時間: " + STD(server_time) + " 與 本地時間: " + STD(now) + " 相差太遠,無法提交!")
sys.exit(1) # 返回1,代表無法成功提交
else:
print ("遠端伺服器時間: " + STD(server_time) + " 與 本地時間: " + STD(now) + " 相近, 可以提交!")
sys.exit(0)
judge_commit_time()
本地簡單的進行了測試,是ok的。當將該程式共享給小夥伴的時候出現問題了,大家都沒有ntplib這個庫。所以只好只使用python的基礎庫重寫。。。。
由於搭建ntp的伺服器提供nginx服務,於是就想到寫了簡單的網頁輸出系統時間,在nginx配置一個埠指向這個網頁,然後在python中直接curl該網頁。網頁如下:
<script type="text/javascript">
var date = new Date();
document.write(Date.parse(date));
</script>
nginx配置如下:
server {
listen 30303;
server_name localhost;
location / {
root `path`; # 網頁所在的路徑
index index.html
}
.....
.....
}
當我妄圖通過urllib.urlopen(url)獲取到時間的時候傻眼了,直接獲取到的是網頁的原始碼,也就是script那一段,我不需要啊!!!!正在我百愁莫展之際,我突然發現,urllib的返回是攜帶時間資訊的,這給了我靈感,我就直接取返回的網頁中攜帶的時間資訊當做遠端伺服器的時間,經過修改後的程式碼如下:
#!/usr/bin/env python
#coding=utf-8
import time
import urllib
import sys
import math
max_diff = 20 * 60 # 最大允許相差20分鐘
url = "http://www.baidu.com" # 獲取時間的ntp伺服器
def STD(s_time):
return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(s_time))
def DTS(d_time):
gmt_time = time.mktime(time.strptime(d_time, "%a, %d %b %Y %H:%M:%S GMT")) # 返回的時間是GMT時間,需要轉化為UTC8的時間
utc8_time = gmt_time + 8 * 60 * 60
return utc8_time
def get_server_time():
try:
page = urllib.urlopen(url)
stime = float(DTS(page.headers.dict.get("date")))
return stime
except:
return -1
def judge_commit_time():
now = time.time()
server_time = get_server_time()
if (server_time <= 0):
print "遠端伺服器不可用,請確認當前系統時間!"
sys.exit(0)
elif (math.fabs(now - server_time) > max_diff):
print ("遠端伺服器時間: " + STD(server_time) + " 與 本地時間: " + STD(now) + " 相差太遠,無法提交!")
sys.exit(1) # 返回1,代表無法成功提交
else:
print ("遠端伺服器時間: " + STD(server_time) + " 與 本地時間: " + STD(now) + " 相近, 可以提交!")
sys.exit(0)
judge_commit_time()
經過投機取巧,終於解決了,各位如果有什麼更好的想法,歡迎留言討論!