如何防止用户将二进制文件提交到 subversion 中?

发布于 2024-08-19 20:05:05 字数 276 浏览 16 评论 0原文

我有一个任性的用户,他顽固地坚持将他的二进制文件(可执行文件、DLL)提交到我们的颠覆存储库中。我会进去删除它们,但当然,颠覆中没有真正删除任何内容。

虽然有时我们需要提交二进制文件,但我不希望用户将其视为例行公事。我可以设置一个忽略属性,但这并不能阻止用户提交二进制文件(如果他们真的确定了)。我想要做的是能够逐个目录地控制提交指定文件类型的能力,特别是 .exe 和 .dll 文件。

在SVN中有没有办法做到这一点?如果有什么区别的话,我们使用 VisualSVN 服务器和 TortoiseSVN。

I have a headstrong user who stubbornly insists on committing his binaries (executables, DLLs) into our subversion repositories. I'd go in and delete them, but of course nothing is ever really deleted from subversion.

While there are times when we need to commit binaries, I don't want users doing it as a matter of routine. I can set an ignore property but that doesn't prevent users from committing binaries if they are really determined. What I'd like to do is be able to control the ability to commit nominated file types, particularly .exe and .dll files, on a directory-by-directory basis.

Is there a way to do that in SVN? If it makes any differentce, we are using VisualSVN server and TortoiseSVN.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

手心的温暖 2024-08-26 20:05:05

Tim:

你可以尝试这个 python hook 脚本。它(松散地)基于上面的,但允许拒绝路径的正则表达式模式,并允许通过

包含以Overide:

在日志消息中 开头的行来覆盖检查。它使用新的 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)

Tim:

You might try this python hook script. It is (loosely) based on the one above, but allows regular expression patterns for the reject paths and allows overriding the check by having a line that begins

Overide:

in the log message. It uses the new python print syntax, so it requires a fairly recent version of 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)
夏末染殇 2024-08-26 20:05:05

这是一个小钩子脚本,它正在执行您想要的操作:
你必须配置两件事:

  • 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)

Here is a small hooks script which is doing what you want:
You have to configure 2 things:

  • illegal_suffixes: a python list with all suffixes which should abort the commit
  • cmdSVNLOOK: the path to svnlook program

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)
爱格式化 2024-08-26 20:05:05

编写一个预提交挂钩来检查添加的文件是否符合您的标准。

您可以使用 预提交-check.py 作为起点。

Write a pre-commit hook that checks added files whether they fit your criteria.

You could use pre-commit-check.py as a starting point.

分开我的手 2024-08-26 20:05:05

在 TortoiseSVN 上,您可以让用户将 .dll、.exe 等添加到忽略列表中。这样,用户就不会意外签入。请参阅此处了解更多信息:

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

在服务器端,正如其他人所说,您可以使用挂钩脚本。

On TortoiseSVN you can have the user add .dll, .exe, etc to the ignore list. That way, they user won't accidentally check them in. See here for more info:

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

On the server side, as others have stated, you can use a hook script.

生死何惧 2024-08-26 20:05:05

您可以使用预提交 钩子。您必须编写一个简单的程序(用任何语言),如果文件是二进制文件,它会返回非零值。

请参阅此处有关存储库挂钩的通用文档,以及 此处 查看来自 Apache 的 Python 示例。

您可以查看文件名,或使用 file 查看其类型。

You can use a pre-commit hook. You'll have to write a simple program (in any language) which returns a non-zero value if the file is binary.

See here for generic documentation about repository hooks, and here for a python example from Apache.

You could look at the files names, or use file to look at their types.

差↓一点笑了 2024-08-26 20:05:05

您可以使用 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'}, 
}

您将需要库 python-magic (https://github.com/ahupp/python-magic)

You can use svnlook command. Here is a python class that do this job:

    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() method returns a map with info like this:

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

You will need the library python-magic (https://github.com/ahupp/python-magic)

往昔成烟 2024-08-26 20:05:05

您可以使用预提交挂钩脚本来检查文件是二进制文件还是文本文件。

You could use a pre-commit hook script that checks if the file is binary or textual.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文