【问题标题】:In a pre-commit hook - how to access/compare current and previous versions of files在预提交挂钩中 - 如何访问/比较当前和以前版本的文件
【发布时间】:2012-09-24 16:11:27
【问题描述】:

我正在尝试添加到我们现有的预提交 SVN 挂钩,以便它检查并阻止特定目录中文件的文件大小增加。

我写了一个 python 脚本来比较两个文件的大小,它接受两个文件作为参数,并使用 sys.exit(0) 或 (1) 返回结果,这部分似乎工作正常。

我的问题是从批处理文件中调用 python 脚本,如何引用每个文件的新提交和以前的版本?现有代码对我来说是新的,还有一堆 %REPOS%、%TXN%s 等,我不知道如何使用它们。有没有一种简单、标准的方法来做到这一点?

它还已经包含使用 svnlook 循环遍历更改文件的代码,因此该部分不应该成为问题。

非常感谢

【问题讨论】:

    标签: python svn pre-commit-hook


    【解决方案1】:

    如果您只需要比较文件大小,只需查看svnlook filesize 命令即可。默认调用 - svnlook filesize repo path - 将为您提供 HEAD 修订版的大小 path。要获取传入提交中路径的大小,请使用svnlook filesize repo path -t argv[2]

    不过,这里是列出版本化路径的所有修订的示例(传入的除外,因为这是 pre-commit 挂钩)。

    #!/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)
    

    【讨论】:

    • 非常感谢您的出色回答。我可以问一下,关于“svnlook filesize repo path -t argv[2]”,最后一个参数是什么,应该从哪里传入?
    • 等等 - 太好了,我刚刚发现将运行它的服务器正在使用不包含文件大小命令的旧版本 SVN -_- 有什么好的解决方法吗?
    • Ethan,sys.argv[2] 是第二个命令行参数,对于预提交挂钩,它对应于事务 ID(大多数 svnlook 命令接受修订或事务)。嗯,我想你可以使用 svnadmin cat 来获取文件内容并自己计算字节数 - 我会添加它来回答。
    【解决方案2】:

    在 python 中编写整个pre-commit 脚本可能更容易。根据subversion handbookpre-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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-13
      • 2015-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多