Как я могу запретить пользователям вводить двоичные файлы в Subversion? - PullRequest
13 голосов
/ 30 января 2010

У меня есть упрямый пользователь, который упорно настаивает на совершение своих двоичные файлы (исполняемых файлов, DLL) в наши диверсионных хранилища. Я бы зашел и удалил их, но, конечно, ничего не удалялось из Subversion.

Хотя бывают случаи, когда нам нужно фиксировать двоичные файлы, я не хочу, чтобы пользователи делали это как обычную процедуру. Я могу установить свойство игнорировать, но это не мешает пользователям фиксировать двоичные файлы, если они действительно определены. То, что я хотел бы сделать, это иметь возможность контролировать возможность фиксации назначенных типов файлов, в частности, файлов .exe и .dll, на основе каталога за каталогом.

Есть ли способ сделать это в SVN? Если что-то изменится, мы используем сервер VisualSVN и TortoiseSVN.

Ответы [ 7 ]

5 голосов
/ 11 января 2012

Тим:

Вы могли бы попробовать этот скрипт ловушки Python. Он (свободно) основан на приведенном выше, но допускает шаблоны регулярных выражений для путей отклонения и позволяет переопределить проверку, имея строку, которая начинается

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)
5 голосов
/ 30 января 2010

Вот небольшой скрипт хуков, который делает то, что вы хотите: Вы должны настроить 2 вещи:

  • invalid_suffixes : список питонов со всеми суффиксами, которые должны прервать фиксацию
  • 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)
3 голосов
/ 30 января 2010

В TortoiseSVN пользователь может добавить .dll, .exe и т. Д. В список игнорируемых. Таким образом, пользователь не сможет их случайно зарегистрировать. Подробнее см. Здесь:

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

На стороне сервера, как уже говорили другие, вы можете использовать скрипт-ловушку.

3 голосов
/ 30 января 2010

Вы можете использовать pre-commit hook. Вам придется написать простую программу (на любом языке), которая возвращает ненулевое значение, если файл является двоичным.

См. здесь для общей документации о перехватах репозитория и здесь для примера Python из Apache.

Вы можете посмотреть имена файлов или использовать file , чтобы посмотреть их типы.

3 голосов
/ 30 января 2010

Напишите хук перед фиксацией, который проверяет добавленные файлы, соответствуют ли они вашим критериям.

Вы можете использовать pre-commit-check.py в качестве отправной точки.

1 голос
/ 28 августа 2013

Вы можете использовать команду 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)

0 голосов
/ 30 января 2010

Вы можете использовать скрипт ловушки перед фиксацией, который проверяет, является ли файл двоичным или текстовым.

...