2012-09-24 18 views
2

我想添加到我們現有的預先提交SVN掛鉤,以便它將檢查並阻止文件的文件大小的增加在特定的目錄下。在預先提交鉤子 - 如何訪問/比較當前和以前版本的文件

我已經寫了一個python腳本來比較兩個文件大小,這需要兩個文件作爲參數,並使用sys.exit(0)或(1)返回結果,這部分似乎工作正常。

我的問題是從批處理文件調用python腳本,如何引用每個文件的新承諾和以前的版本?現有的代碼對我來說是新的,並且%REPOS%,%TXN%s等混亂,我不知道如何去使用它們。有沒有一個簡單,標準的方法來做到這一點?

它也已包含代碼來循環使用svnlook更改的已更改的文件,以便該部分不應該是一個問題。

非常感謝

回答

4

如果比較的文件大小是所有你需要做的,沒有進一步看比svnlook filesize命令。默認的調用 - svnlook filesize repo path - 會給你path的HEAD版本的大小。要獲取傳入提交中路徑的大小,請使用svnlook filesize repo path -t argv[2]

儘管如此,還是列出版本化路徑的所有版本(除了傳入路徑之外,因爲這是預掛鉤鉤子)的示例。

#!/usr/bin/env python 

from sys import argv, stderr, exit 
from subprocess import check_output 

repo = argv[1] 
transaction = argv[2] 

def path_history(path, limit=5): 
    path = '/%s' % path 
    cmd = ('svnlook', 'history', '-l', str(limit), repo, path) 
    out = check_output(cmd).splitlines()[2:] 

    for rev, _path in (i.split() for i in out): 
     if _path == path: 
      yield rev 

def commit_changes(): 
    cmd = ('svnlook', 'changed', repo, '-t', transaction) 
    out = check_output(cmd).splitlines() 

    for line in out: 
     yield line.split() 

def filesize(path, rev=None, trans=None): 
    cmd = ['svnlook', 'filesize', repo, path] 
    if rev:  cmd.extend(('-r', str(rev))) 
    elif trans: cmd.extend(('-t', str(trans))) 

    out = check_output(cmd) 
    return out.rstrip() 

def filesize_catwc(path, rev=None, trans=None): 
    '''A `svnlook filesize` substitute for older versions of svn. 
    Uses `svnlook cat ... | wc -c` and should be very inefficient 
    for large files.''' 

    arg = '-r %s' % rev if rev else '-t %s' % trans 
    cmd = 'svnlook cat %s %s %s | wc -c' % (arg, repo, path) 

    out = check_output(cmd, shell=True) 
    return out.rstrip() 


for status, path in commit_changes(): 
    if status in ('A', 'M', 'U'): 
     # get the last 5 revisions of the added/modified path 
     revisions = list(path_history(path)) 
     headrev = revisions[0] 

     oldsize = filesize(path, rev=headrev) 
     newsize = filesize(path, trans=transaction) 
+0

非常感謝您的好評。我可以問一下,參考 「svnlook filesize repo path -t argv [2]」,這是什麼最後一個參數,它應該從哪裏傳入? – EthanML

+0

等待 - 太好了,我剛剛發現運行的服務器使用的是舊版SVN,不包含filesize命令-_-任何良好的解決方法? – EthanML

+0

Ethan,'sys.argv [2]'是第二個命令行參數,對於預提交鉤子,它對應於事務ID(大多數'svnlook'命令接受修訂或事務)。嗯,我想你可以使用'svnadmin cat'來獲取文件內容並自己計算字節數 - 我會添加回答。 – gvalkov

1

在Python中編寫整個pre-commit腳本可能更容易。根據subversion handbook,有三個輸入到pre-commit;

  • 兩個命令行參數
    • 庫路徑
    • 提交事務名
  • 標準輸入

如果你想知道哪些文件已更改鎖定令牌信息,我建議你使用subprocess.check_output()函數來調用svnlook changed。對於內容已更改的文件,您應該調用svnlook filesize以獲取文件的大小,因爲它在存儲庫中的上一次修訂中是這樣。您必須使用os.stat()查詢工作目錄中等效文件的大小,如函數getsizes()所示。

import subprocess 
import sys 
import os 

repo = sys.argv[1] 
commit_name = sys.argv[2] 

def getsizes(rname, rfile): 
    '''Get the size of the file in rfile from the repository rname. 
    Derive the filename in the working directory from rfile, and use 
    os.stat to get the filesize. Return the two sizes. 
    ''' 
    localname = rfile[10:].strip() # 'U trunk/foo/bar.txt' -> 'foo/bar.txt' 
    reposize = subprocess.check_output(['svnlook', 'filesize', rname, rfile]) 
    reposize = int(reposize) 
    statinfo = os.stat(localname) 
    return (reposize, statinfo.st_size) 

lines = subprocess.check_output(['svnlook', 'changed', repo]).splitlines() 
for line in lines: 
    if line.startswith('U ') or line.startswith('UU'): 
     # file contents have changed 
     reposize, wdsize = getsizes(repo, line) 
     # do something with the sizes here... 
    elif line.startswith('_U'): 
     # properties have changed 
     pass 
相關問題