【问题标题】:Strange Behaviour of Hook Script commit-mime-type-check.pl on windowsWindows 上 Hook 脚本 commit-mime-type-check.pl 的奇怪行为
【发布时间】:2012-01-03 03:46:57
【问题描述】:

我已经从svn.apache.org 下载了预提交钩子脚本“commit-mime-type-check.pl” 我在 Windows 上工作,只有两件事可以更改 svnlook 二进制文件的路径和临时目录的路径。我做到了。但我收到以下错误

Error: Commit failed (details follow):  
Error: Commit blocked by pre-commit hook (exit code 1) with output:  
Error: '-' is not recognized as an internal or external command,  
Error: operable program or batch file.  
Error: C:\vsvn\Repositories\myproj\hooks\local_commit_mime_eol_check.pl:   
Error: `C:\vsvn\bin\svnlook.exe changed C:\vsvn\Repositories\myproj -t 16-1l' failed   
Error: with no output.  
Finished!: 

我自己调试了一下,发现哪里出错了。

my $pid = open(SAFE_READ, '-|');

我阅读了关于用“-|”打开的解释在 [_http://perldoc.perl.org/perlipc.html#Using-open()-for-IPC] 下安全管道打开

安全管道打开 另一个有趣的 IPC 方法是让您的单个程序成为多进程并在您自己之间(甚至在彼此之间)进行通信。 open() 函数将接受“-|”的文件参数或 "|-" 来做一件非常有趣的事情:它派生一个连接到您打开的文件句柄的孩子。孩子正在运行与父母相同的程序。例如,这对于在假定的 UID 或 GID 下运行时安全打开文件很有用。如果您打开一个减号管道,您可以写入您打开的文件句柄,您的孩子会在他的 STDIN 中找到它。如果您从减号打开管道,您可以从您打开的文件句柄中读取您的孩子写入他的 STDOUT 的任何内容。

我无法理解的原因是不兼容或什么。因为它最初是在 linux box 上编写的,对于管道和内部进程通信非常丰富。我总是觉得窗户很差。(没有冒犯任何人。这是我个人的感受。让我们回到主题。我正在寻找所有疯狂的建议。不寻求修复,但如果我得到了,我将不胜感激

我尝试了所有方法,但最后失败了,我尝试用谷歌搜索是否有人也面临同样的问题。链接不多,但找到了this one,有趣的部分是这个,它没有解决。那我没办法,只能在这里问了。

下面是脚本代码供大家参考

#!/usr/bin/env perl

# ====================================================================
# commit-mime-type-check.pl: check that every added file has the
# svn:mime-type property set and every added file with a mime-type
# matching text/* also has svn:eol-style set. If any file fails this
# test the user is sent a verbose error message suggesting solutions and
# the commit is aborted.
#
# Usage: commit-mime-type-check.pl REPOS TXN-NAME
# ====================================================================
# Most of commit-mime-type-check.pl was taken from
# commit-access-control.pl, Revision 9986, 2004-06-14 16:29:22 -0400.
# ====================================================================
# Copyright (c) 2000-2004 CollabNet.  All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution.  The terms
# are also available at http://subversion.tigris.org/license.html.
# If newer versions of this license are posted there, you may use a
# newer version instead, at your option.
#
# This software consists of voluntary contributions made by many
# individuals.  For exact contribution history, see the revision
# history and logs, available at http://subversion.tigris.org/.
# ====================================================================

# Turn on warnings the best way depending on the Perl version.
BEGIN {
  if ( $] >= 5.006_000)
    { require warnings; import warnings; }
  else
    { $^W = 1; }
}

use strict;
use Carp;


######################################################################
# Configuration section.

# Svnlook path.
my $svnlook = "/usr/bin/svnlook";

# Since the path to svnlook depends upon the local installation
# preferences, check that the required program exists to insure that
# the administrator has set up the script properly.
{
  my $ok = 1;
  foreach my $program ($svnlook)
    {
      if (-e $program)
        {
          unless (-x $program)
            {
              warn "$0: required program `$program' is not executable, ",
                   "edit $0.\n";
              $ok = 0;
            }
        }
      else
        {
          warn "$0: required program `$program' does not exist, edit $0.\n";
          $ok = 0;
        }
    }
  exit 1 unless $ok;
}

######################################################################
# Initial setup/command-line handling.

&usage unless @ARGV == 2;

my $repos        = shift;
my $txn          = shift;

unless (-e $repos)
  {
    &usage("$0: repository directory `$repos' does not exist.");
  }
unless (-d $repos)
  {
    &usage("$0: repository directory `$repos' is not a directory.");
  }

# Define two constant subroutines to stand for read-only or read-write
# access to the repository.
sub ACCESS_READ_ONLY  () { 'read-only' }
sub ACCESS_READ_WRITE () { 'read-write' }


######################################################################
# Harvest data using svnlook.

# Change into /tmp so that svnlook diff can create its .svnlook
# directory.
my $tmp_dir = '/tmp';
chdir($tmp_dir)
  or die "$0: cannot chdir `$tmp_dir': $!\n";

# Figure out what files have added using svnlook.
my @files_added;
foreach my $line (&read_from_process($svnlook, 'changed', $repos, '-t', $txn))
  {
        # Add only files that were added to @files_added
    if ($line =~ /^A.  (.*[^\/])$/)
      {
        push(@files_added, $1);
      }
  }

my @errors;
foreach my $path ( @files_added )
    {
        my $mime_type;
        my $eol_style;

        # Parse the complete list of property values of the file $path to extract
        # the mime-type and eol-style
        foreach my $prop (&read_from_process($svnlook, 'proplist', $repos, '-t',
                          $txn, '--verbose', $path))
            {
                if ($prop =~ /^\s*svn:mime-type : (\S+)/)
                    {
                        $mime_type = $1;
                    }
                elsif ($prop =~ /^\s*svn:eol-style : (\S+)/)
                    {
                        $eol_style = $1;
                    }
            }

        # Detect error conditions and add them to @errors
        if (not $mime_type)
            {
                push @errors, "$path : svn:mime-type is not set";
            }
        elsif ($mime_type =~ /^text\// and not $eol_style)
            {
                push @errors, "$path : svn:mime-type=$mime_type but svn:eol-style is not set";
            }
    }

# If there are any errors list the problem files and give information
# on how to avoid the problem. Hopefully people will set up auto-props
# and will not see this verbose message more than once.
if (@errors)
  {
    warn "$0:\n\n",
         join("\n", @errors), "\n\n",
                 <<EOS;

    Every added file must have the svn:mime-type property set. In
    addition text files must have the svn:eol-style property set.

    For binary files try running
    svn propset svn:mime-type application/octet-stream path/of/file

    For text files try
    svn propset svn:mime-type text/plain path/of/file
    svn propset svn:eol-style native path/of/file

    You may want to consider uncommenting the auto-props section
    in your ~/.subversion/config file. Read the Subversion book
    (http://svnbook.red-bean.com/), Chapter 7, Properties section,
    Automatic Property Setting subsection for more help.
EOS
    exit 1;
  }
else
  {
    exit 0;
  }

sub usage
{
  warn "@_\n" if @_;
  die "usage: $0 REPOS TXN-NAME\n";
}

sub safe_read_from_pipe
{
  unless (@_)
    {
      croak "$0: safe_read_from_pipe passed no arguments.\n";
    }
  print "Running @_\n";
  my $pid = open(SAFE_READ, '-|');
  unless (defined $pid)
    {
      die "$0: cannot fork: $!\n";
    }
  unless ($pid)
    {
      open(STDERR, ">&STDOUT")
        or die "$0: cannot dup STDOUT: $!\n";
      exec(@_)
        or die "$0: cannot exec `@_': $!\n";
    }
  my @output;
  while (<SAFE_READ>)
    {
      chomp;
      push(@output, $_);
    }
  close(SAFE_READ);
  my $result = $?;
  my $exit   = $result >> 8;
  my $signal = $result & 127;
  my $cd     = $result & 128 ? "with core dump" : "";
  if ($signal or $cd)
    {
      warn "$0: pipe from `@_' failed $cd: exit=$exit signal=$signal\n";
    }
  if (wantarray)
    {
      return ($result, @output);
    }
  else
    {
      return $result;
    }
}

sub read_from_process
  {
  unless (@_)
    {
      croak "$0: read_from_process passed no arguments.\n";
    }
  my ($status, @output) = &safe_read_from_pipe(@_);
  if ($status)
    {
      if (@output)
        {
          die "$0: `@_' failed with this output:\n", join("\n", @output), "\n";
        }
      else
        {
          die "$0: `@_' failed with no output.\n";
        }
    }
  else
    {
      return @output;
    }
}

【问题讨论】:

    标签: svn pre-commit-hook


    【解决方案1】:

    我一直在看这个 Perl 语法,我对自己说:“哇,这太旧了”。

    如果您查看 open function 的 Perldoc,您会发现两个参数参数没有提及您的钩子脚本正在做什么。然而,正如你所指出的,perlipc 确实提到了它。

    看起来你的 Perl 解释器正在解释 |-,如 Perldoc 开放函数描述中所述:

    • 这是函数的两个参数形式。因此:
      • 第一个参数是文件句柄的名称。
      • 第二个参数是文件名。
    • 由于文件名以管道结尾,因此文件名的其余部分是当您从管道读取时要通过 STDIN 管道执行的命令的名称。

    由于第二个参数是-|,它正在寻找一个名为- 的命令。没有名为- 的命令,open 函数失败。

    不确定你能做什么,但你可以借用我的Pre-commit Kitchen Sink Hook,它可以做各种各样的事情。

    它可以做的一件事是根据文件名强制执行属性类型和值。例如,您可以强制所有以.sh 后缀结尾的文件将svn:eol-type 设置为LF,或者将.pdf 后缀的文件设置为svn:mime-type 设置为application/pdf,这是我所相信的这个钩子应该做什么。

    我将详细介绍这个钩子脚本,看看我是否可以准确地弄清楚它在做什么以及它是如何工作的。我会向 Apache 提交一个 fixed 版本的钩子脚本,但他们不再维护钩子脚本了。

    我以前从未使用过open SAFE_READ, "-|" 语法,但你每天都能学到一些东西。我将不得不玩弄它。

    【讨论】:

    • 显然,这是一个派生进程的 Perlism。发生这种情况时,子级和父级具有相同的环境($pid 除外,并且在 Perl 脚本中执行同一行。Windows 不会分叉,因此这在 Windows 上不起作用。
    猜你喜欢
    • 1970-01-01
    • 2021-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-19
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    相关资源
    最近更新 更多