2010-01-29 45 views
13

我有一個頑固堅持提交他的二進制文件(可執行文件,DLL)到我們的Subversion存儲庫的任性用戶。我會去刪除它們,但是當然沒有任何東西真的從Subversion中刪除。如何防止用戶將二進制文件提交到subversion中?

雖然有時我們需要提交二進制文件,但我不希望用戶將其作爲例行程序來處理。我可以設置一個忽略屬性,但這並不妨礙用戶如果真的確定就提交二進制文件。我想要做的就是能夠控制提供指定文件類型的能力,特別是.exe和.dll文件,以逐個目錄爲基礎。

有沒有辦法在SVN中做到這一點?如果它有所不同,我們使用VisualSVN服務器和TortoiseSVN。

+0

那麼,有三個答案如此之間的選擇是非常迅速和不可能的,我相信一個示例腳本可以確保'接受'狀態:) – 2010-01-29 22:53:01

+2

如何規範你的用戶?並非每種解決方案都是技術性的, – 2010-01-29 22:56:53

+0

@Lasse:我同意,但實際上我發現這有助於防止*自己*意外*將二進制文件夾入SVN存儲庫(即在新機器上設置Tortoise並忘記添加「bin」和「 obj「例外) – Aaronaught 2010-01-29 23:01:28

回答

5

Tim:

您可以試試這個python鉤子腳本。它是(鬆散地)基於上述一個,但允許正則表達式模式的拒絕路徑,並允許通過具有開始

在此改變的線重寫檢查:在日誌消息

。它使用新的Python打印語法,因此它需要一個相當新的Python版本(2.6+?)。

from __future__ import print_function 

import sys,os 
import subprocess 
import re 

#this is a list of illegal patterns: 
illegal_patterns = [ 
    '\.exe$', 
    '\.dll$', 
    '[\^|/]bin/', 
    '[\^|/]obj/', 
] 

# Path to svnlook command: 
cmdSVNLOOK=r"{}bin\svnlook.exe".format(os.environ["VISUALSVN_SERVER"]) 

print(illegal_patterns, file=sys.stderr) 

print("cmdSVNLook={}".format(cmdSVNLOOK), file=sys.stderr) 

def runSVNLook(subCmd, transact, repoPath): 
    svninfo = subprocess.Popen([cmdSVNLOOK, subCmd, '-t', transact, repoPath], 
          stdout = subprocess.PIPE, stderr=subprocess.PIPE) 
    (stdout, stderr) = svninfo.communicate() 

    if len(stderr) > 0: 
     print("svnlook generated stderr: " + stderr, file=sys.stderr) 
     sys.exit(1) 

    return [ line.strip() for line in stdout.split("\n") ] 

def findIllegalPattern(fileName): 
    for pattern in illegal_patterns: 
     if re.search(pattern, fileName): 
      print("pattern: {} matched filename:{}".format(pattern, fileName)) 
      return pattern 
    return None 

def containsOverRide(logOutput): 
    retVal = False 
    for line in logOutput: 
     print("log line: {}".format(line), file=sys.stderr) 
     if re.match("^override:", line.lower()): 
      retVal = True 
      break 
    print("contiansOverRide={}".format(retVal), file=sys.stderr) 
    return retVal 

def findIllegalNames(changeOutput): 
    illegalNames = [] 
    prog = re.compile('(^[ACUDRM_])[ACUDRM]*\s+(.+)') # regex for svnlook output 
    for line in changeOutput: 
     print("processing:{}".format(line), file=sys.stderr) 
     if (line != ""): 
      match=re.search(prog, line.strip()) 
      if match: 
       mode = match.group(1) 
       ptFilename = match.group(2) 
       if mode == 'A': 
        pattern = findIllegalPattern(ptFilename) 
        if pattern: 
         illegalNames.append((pattern, ptFilename)) 
      else: 
       print("svnlook output parsing failed!", file=sys.stderr) 
       sys.exit(1) 
    return illegalNames 

######### main program ################ 
def main(args): 
    repopath = args[1] 
    transact = args[2] 

    retVal = 0 

    overRidden = containsOverRide(runSVNLook("log", transact, repopath)) 
    illegalFiles = findIllegalNames(runSVNLook("changed", transact, repopath)) 

    if len(illegalFiles): 
     msg = "****************************************************************************\n" 

     if len(illegalFiles) == 1: 
      msg += "* This commit contains a file which matches a forbidden pattern   *\n" 
     else: 
      msg += "* This commit contains files which match a forbidden pattern    *\n" 

     if overRidden: 
      msg += "* and contains an Override line so the checkin will be allowed   *\n" 
     else: 
      retVal = 1 

      msg += "* and is being rejected.             *\n" 
      msg += "*                   *\n" 
      msg += "* Files which match these patterns are genreraly created by the   *\n" 
      msg += "* built process and should not be added to svn.       *\n" 
      msg += "*                   *\n" 
      msg += "* If you intended to add this file to the svn repository, you neeed to  *\n" 
      msg += "* modify your commit message to include a line that looks like:   *\n" 
      msg += "*                   *\n" 
      msg += "* OverRide: <reason for override>           *\n" 
      msg += "*                   *\n" 
     msg += "****************************************************************************\n" 

     print(msg, file=sys.stderr) 

     if len(illegalFiles) == 1: 
      print("The file and the pattern it matched are:", file=sys.stderr) 
     else: 
      print("The files and the patterns they matched are:", file=sys.stderr) 

     for (pattern, fileName) in illegalFiles: 
       print('\t{}\t{}'.format(fileName, str(pattern)), file=sys.stderr) 

    return retVal 

if __name__ == "__main__": 
    ret = main(sys.argv) 
    sys.exit(ret) 
+0

這是完美的。我在服務器上安裝了IronPython,這個腳本完全可以滿足我的需求。我喜歡讓用戶能夠覆蓋hookscript的概念。 VisualSVN需要一個批處理文件,所以我不得不創建一個簡單的命令來調用Python腳本。 – 2012-01-11 03:59:21

3

編寫一個預先提交的鉤子,檢查添加的文件是否符合您的標準。

您可以使用pre-commit-check.py作爲起點。

+0

你會如何建議我在每個目錄的基礎上控制它?我需要一些目錄來允許二進制文件被檢入,而另一些則不允許。我寧願不必將這些信息硬編碼爲腳本。 – 2010-01-29 22:55:35

+0

您的腳本可以從文件中讀取允許的路徑列表(您可能希望將文件存儲在服務器上,而不是存儲庫中,以便用戶無法更改) 如果要將信息存儲在存儲庫中,您可以改爲使用目錄中的屬性。這使信息更加本地化,​​並且會自動處理新的分支/標籤。 – oefe 2010-01-29 23:19:23

3

您可以使用pre-commit鉤子。你必須編寫一個簡單的程序(用任何語言),如果該文件是二進制文件,它將返回一個非零值。

請參閱here以獲取有關存儲庫鉤子的通用文檔,以及here針對Apache的python示例。

您可以查看文件名,或使用file來查看它們的類型。

+0

這 - 一般來說,你可能也想檢查.dll,.exe等等......文件名給這個用戶的頑固持久性。 – 2010-01-29 22:51:43

0

您可以使用預先提交鉤子腳本來檢查文件是二進制文件還是文本文件。

+0

壞主意,你不能爲網站添加圖片。擴展檢查要好得多 – 2011-05-21 07:41:33

3

在TortoiseSVN上,您可以讓用戶將.dll,.exe等添加到忽略列表中。 。這樣一來,他們的用戶會不小心檢查他們在這裏看到更多的信息:

http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-dug-ignore.html

在服務器端,如其他人所說,你可以用一個鉤子腳本。

+2

好吧,這是我在這裏處理的一個任性用戶。他被問了幾次不要犯二進制文件,但仍然如此。我不認爲這是一個記憶的問題。這就是爲什麼我需要加強這項政策。 – 2010-01-29 23:02:05

+0

說句實話,解決這個問題的一個辦法就是解僱他。我不是說這是你處理它的第一種方法,但是如果推動推進,非球隊球員就無法在球隊中佔有一席之地。 – 2010-01-29 23:14:09

+0

您也可以拒絕任何提交訪問。所以他只能將他的差異作爲補丁發送給他的同事。這就是Subversion本身限制其對存儲庫的寫入訪問的方式:你必須證明你通過發送補丁到郵件列表來編寫正確的代碼 – 2010-01-30 17:36:59

5

這裏是一個正在做一個小鉤子腳本,你想要什麼: 您必須配置2兩件事:

  • illegal_suffixes:所有後綴Python列表應該取消提交
  • cmdSVNLOOK:路徑svnlook的程序

import sys 
import subprocess 
import re 

#this is a list of illegal suffixes: 
illegal_suffixes = ['.exe','.dll'] 

# Path to svnlook command: 
cmdSVNLOOK="/usr/bin/svnlook"; 

def isIllegalSuffix(progname): 
    for suffix in illegal_suffixes: 
     if (ptFilename.endswith(suffix)): 
      return True 
    return False 

######### main program ################ 
repopath = sys.argv[1] 
transact = sys.argv[2] 

retVal = 0 
svninfo = subprocess.Popen([cmdSVNLOOK, 'changed', '-t', transact, repopath], 
                 stdout = subprocess.PIPE, stderr=subprocess.PIPE) 
(stdout, stderr) = svninfo.communicate(); 

prog = re.compile('(^[ACUDRM_])[ACUDRM]*\s+(.+)') # regex for svnlook output 
for line in stdout.split("\n"): 
    if (line.strip()!=""): 
     match=re.search(prog, line.strip()) 
     if match: 
      mode = match.group(1) 
      ptFilename = match.group(2) 
      if mode == 'A' and isIllegalSuffix(ptFilename): 
       retVal = 1 
       sys.stderr.write("Please do not add the following ") 
       sys.stderr.write("filetypes to repository:\n") 
       sys.stderr.write(str(illegal_suffixes)+"\n") 
       break 
     else: 
      sys.stderr.write("svnlook output parsing failed!\n") 
      retVal = 1 
      break 
    else: 
     # an empty line is fine! 
     retVal = 0 
sys.exit(retVal) 
+0

謝謝,我感謝您花時間發佈 - 很不幸,我們使用的VisualSVN服務器在Windows上運行。我需要VBScript,JScript或DOS批處理文件。儘管如此,+1發佈腳本。 – 2010-02-01 03:36:37

+0

你可以在windows下使用python,而svnlook可以使用visual svn:https://www.visualsvn。com/support/svnbook/ref/svnlook/ – 2010-02-01 06:55:41

+0

我在windwos下開發了它;-)它在linux和windows上進行了測試。你當然可以使用python作爲鉤子,而svnlook是VisualSVN的一部分,否則你可以(也應該)安裝svn-commandline – 2010-02-01 19:54:04

1

您可以使用svnlook命令。下面是一個python類,做好這項工作:

SVNTransactionParser(object): 
     def __init__(self, repos, txn): 
      self.repos = repos 
      self.txn = txn 
      self.ms = magic.open(magic.MAGIC_NONE) 
      self.ms.load() 

     def tx_files(self): 
      files_to_analyze = list() 
      for l in self.__svnlook('changed')[0].readlines(): 
       l = l.replace('\n', ''); 
       if not l.endswith('/') and l[0] in ['A', 'U']: 
        files_to_analyze.append(l.split(' ')[-1:][0]) 

      files = dict()   
      for file_to_analyze in files_to_analyze: 
       files[file_to_analyze] = { 
           'size': self.__svnlook('filesize', file_to_analyze)[0].readlines()[0].replace('\n', ''), 
           'type': self.ms.buffer(self.__svnlook('cat', file_to_analyze)[0].readline(4096)), 
           'extension': os.path.splitext(file_to_analyze)[1]} 

      return files 

     def __svnlook(self, command, extra_args=""): 
      cmd = '%s %s %s -t "%s" %s' % (SVNLOOK, command, self.repos, self.txn, extra_args) 
      out = popen2.popen3(cmd) 
      return (out[0], out[2]) 

tx_files()方法返回一個地圖信息是這樣的:

{ 
    '/path/to/file1.txt': {'size': 10, 'type': 'ASCII', 'extension': '.txt'}, 
    '/path/to/file2.pdf': {'size': 10134, 'type': 'PDF', 'extension': '.dpf'}, 
} 

您需要的庫蟒蛇魔(https://github.com/ahupp/python-magic

相關問題