使用@INC中的子程序从Perforce中获取模块

时间:2013-11-05 22:31:12

标签: perl perl-module

我遇到了包含必须从Perforce存储库获取的Perl模块的问题。我通过使用P4 print从Perforce中读取文本来包含模块。

对于不熟悉Perforce的人来说,它是一个代码版本控制工具。我不能直接从该路径读取文件,就像它是映射驱动器一样,所以我需要运行此命令。

p4 print等同于cat,但路径是特殊的,只有命令p4可以从Perforce工作区访问文件。

BEGIN {
  push @INC, (
    sub {
      open my $fh, "p4 print -q //sw/pvt/shashikanths/perl/mylib/ReadElf.pm |";
      return $fh;
    },
    sub {
      open my $fh1, "p4 print -q //sw/pvt/shashikanths/perl/mylib/SimpleLogger.pm |";
      return $fh1;
    },
  );
}

BEGIN {
  push @INC, sub {
    open my $fh2, "p4 print -q //sw/pvt/shashikanths/perl/mylib/Table.pm |";
    return $fh2;
  }
}

use ReadElf;
use SimpleLogger;
use Table;

始终只包含第一个文件ReadElf.pm。我尝试将所有三个文件连接到一个文件,并且还为每个文件单独使用BEGIN块。它们都不起作用。

因此,当我尝试从SimpleLogger访问模块时,我得到了未定义的子程序错误。

1 个答案:

答案 0 :(得分:7)

我道歉,我只是明白你在做什么。将子程序引用推送到@INC是Perl功能的一个神秘部分,很少有人知道。

documentation for require说:

  

您还可以通过将Perl代码直接放入@INC数组中,将挂钩插入导入工具。钩子有三种形式:子程序引用,数组引用和祝福对象。

     

子程序引用是最简单的情况。当包含系统遍历@INC并遇到子程序时,将使用两个参数调用此子例程,第一个是对自身的引用,第二个是要包含的文件的名称(例如,“Foo / Bar.pm”) 。子例程应按以下顺序返回任何内容或最多返回三个值的列表:

     

1 - 文件句柄,将从中读取文件。

     

2 - 对子程序的引用。如果没有文件句柄(前一项),那么这个子程序应该每次调用生成一行源代码,将行写入$ _并返回1,最后在文件末尾返回0.如果有文件句柄,然后调用子程序作为一个简单的源过滤器,该行在$ _中读取。同样,为每个有效行返回1,并在返回所有行后返回0。

     

3 - 子程序的可选状态。州以$ _ [1]的形式传递。子例程本身的引用作为$ _ [0]传递。

问题在于您忽略了要推送到@INC的子程序的参数。第二个参数是perl尝试加载的模块文件的名称,即ReadElf.pmSimpleLogger.pmTable.pm。 Perl在@INC中找到返回任何内容的第一个条目,它始终是第一个子例程,它提取ReadElf.pm并返回一个文件句柄以便从中读取。

要加载其中任何一个,只要它们都在Perforce存储库中的相同位置,您就可以编写

BEGIN {
  push @INC, sub {
    my ($self, $module) = @_;
    my $file = "//sw/pvt/shashikanths/perl/mylib/$module";
    open my $fh, "p4 print -q $file |";
    return $fh;
  }
}

这可以通过构建模块的Perforce副本的完整路径并返回一个允许Perl读取它的文件句柄来实现。

您确实应首先检查$file指定的文件是否存在,如果不存在,则不返回任何内容。否则p4正在被不必要地运行,子程序返回一个文件句柄,无论模块是否被成功提取。