Perforce P4 .NET API GetFileMetaData() 返回 NullReferenceException

发布于 2024-12-27 18:38:45 字数 2703 浏览 1 评论 0原文

我运行了从 P4 下载的 P4api.net 示例 C# 代码,以遍历我拥有的本地 P4 /depot 存储库。当示例代码尝试读取 //depot/subdirA 中的子目录和文件时,对 API 函数 GetFileMetaData() 的调用会遇到空指针异常。当 //depot/subdirA 只有子目录且其中没有文件时,会发生这种情况。如果 //depot/subdirA 有一个或多个文件,则 GetFileMetaData() 可以正常工作。我一定错过了一些东西,因为我假设 GetFileMetaData() 应该适用于存在或不存在文件的目录。

以下是 P4 示例代码 - 请参阅代码注释以了解异常位置:

// if we have the depot path, get a list of the subdirectories from the depot
if (!String.IsNullOrEmpty(depotPath))
{
    IList<string> subdirs = _repository.GetDepotDirs(null, String.Format("{0}/*", depotPath));
    if ((subdirs != null) && (subdirs.Count >0))
    {
        subdirectories = P4DirectoryMap.FromDirsOutput(_repository, Workspace, this, subdirs);
        foreach (P4Directory dir in subdirectories.Values)
        {
            dir.InDepot = true;
        }
    }

    IList<FileMetaData> fileList = _repository.GetFileMetaData(null, FileSpec.DepotSpec(String.Format("{0}/*", depotPath)));
    // get a list of the files in the directory - debugger hit Null Exception within this call.

    if (fileList != null)
    {
        files = P4FileMap.FromFstatOutput(fileList);

        // if the directory contains files from the depot, we can use 
        // the local path of one of those files to determine the local 
        // path for this directory
        if ((String.IsNullOrEmpty(localPath)) && (files != null) && (files.Count > 0))
        {

我下载了 P4api.net API 源代码,并在 GetFileMetaData() 中观察到 r.TaggedOutput == null 当主题目录中不包含文件,只有更多子目录时。这可能是我对源代码的误解,但我认为代码应该在运行 FOR 循环之前检查 r.TaggedOutput == null ,请参阅代码注释以了解异常位置:

public IList<FileMetaData> GetFileMetaData(Options options, params FileSpec[] filespecs ) 
{
    P4.P4Command fstatCmd = new P4.P4Command(_connection._p4server, "fstat", true, FileSpec.ToStrings(filespecs));
    P4.P4CommandResult r = fstatCmd.Run(options);
    if (r.Success != true)
    {
        P4Exception.Throw(r.ErrorList);
        return null;
    }
    List<FileMetaData> value = new List<FileMetaData>();
        
    foreach (P4.TaggedObject obj in r.TaggedOutput)
    // Null Exception was caused by r.TaggedOutput=null when the sub dir has no file.
    {
         FileMetaData fmd = new FileMetaData();
         fmd.FromFstatCmdTaggedData(obj);
         value.Add(fmd);
    }
    return value;
}

我如何解决这个问题,因为人们可以期望仓库目录包含目录或文件或两者,但 GetFileMetaData() 似乎期望目录中始终包含文件?我是否必须为传入的“选项”参数指定一个可以防止此异常的选项?或者是否有另一个 API 调用来检查目录中是否存在文件,代码可以在调用 GetFileMetaData() 之前调用该文件?

I ran a P4api.net sample C# code downloaded from P4 to traverse a local P4 /depot repository that I have. When the sample code attempts to read the //depot/subdirA for sub directories and files, the call to API function GetFileMetaData() hits a null pointer exception. This happens when //depot/subdirA has only sub directories with no file in it. If //depot/subdirA has one or more files then GetFileMetaData() works properly. I must be missing something as I assume that GetFileMetaData() should work for directory with or without files existing.

Following is the P4 sample code - please see code comment for exception location:

// if we have the depot path, get a list of the subdirectories from the depot
if (!String.IsNullOrEmpty(depotPath))
{
    IList<string> subdirs = _repository.GetDepotDirs(null, String.Format("{0}/*", depotPath));
    if ((subdirs != null) && (subdirs.Count >0))
    {
        subdirectories = P4DirectoryMap.FromDirsOutput(_repository, Workspace, this, subdirs);
        foreach (P4Directory dir in subdirectories.Values)
        {
            dir.InDepot = true;
        }
    }

    IList<FileMetaData> fileList = _repository.GetFileMetaData(null, FileSpec.DepotSpec(String.Format("{0}/*", depotPath)));
    // get a list of the files in the directory - debugger hit Null Exception within this call.

    if (fileList != null)
    {
        files = P4FileMap.FromFstatOutput(fileList);

        // if the directory contains files from the depot, we can use 
        // the local path of one of those files to determine the local 
        // path for this directory
        if ((String.IsNullOrEmpty(localPath)) && (files != null) && (files.Count > 0))
        {

I downloaded the P4api.net API source code and observed within GetFileMetaData() that the r.TaggedOutput == null when the subject directory contains no file in it, just more sub directories. It could be my misunderstanding of the source code but I would think that the code should check for r.TaggedOutput == null before running the FOR loop thereafter, please see code comment for exception location:

public IList<FileMetaData> GetFileMetaData(Options options, params FileSpec[] filespecs ) 
{
    P4.P4Command fstatCmd = new P4.P4Command(_connection._p4server, "fstat", true, FileSpec.ToStrings(filespecs));
    P4.P4CommandResult r = fstatCmd.Run(options);
    if (r.Success != true)
    {
        P4Exception.Throw(r.ErrorList);
        return null;
    }
    List<FileMetaData> value = new List<FileMetaData>();
        
    foreach (P4.TaggedObject obj in r.TaggedOutput)
    // Null Exception was caused by r.TaggedOutput=null when the sub dir has no file.
    {
         FileMetaData fmd = new FileMetaData();
         fmd.FromFstatCmdTaggedData(obj);
         value.Add(fmd);
    }
    return value;
}

How do I get around this problem as one can expect a depot directory to have either directories or files or both but GetFileMetaData() seems to expect the dir always have files in it? Is there an option I have to specify for the passed-in "options" param that can prevent this exception? Or is there another API call to check for the existence of files within a directory that code can call before calling GetFileMetaData()?

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

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

发布评论

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

评论(1

久而酒知 2025-01-03 18:38:45

此错误已报告并已在 P4API.NET GA 版本中修复。我不确定何时发布,但您可以致电 Perforce 支持并询问。

同时,这里有一个可能的解决方法来查看目录是否为空。

String[] cmdargs = new String[1];
cmdargs[0] = depotPath + "/*";
P4Command cmd = new P4Command(rep, "files", true, cmdargs);
P4CommandResult results = cmd.Run(null);
if (results != null && results.TaggedOutput != null)
{
    foreach (TaggedObject obj in results.TaggedOutput)
    {
        // do something with file list if you want
    }
}
else
{                        
    Console.WriteLine("No files in this directory!");                        
}

基本上它使用与 GetFileMetaData 类似的逻辑,但使用较低级别的命令直接从服务器获取标记输出。然后,您可以在调用其他方法之前检查结果集是否存在目录中的任何文件。

This bug was reported and already fixed for the GA release of P4API.NET. I'm not sure when that is being released, but you can call Perforce Support and ask about it.

In the meantime, here's a possible work-around to see if a directory is empty or not.

String[] cmdargs = new String[1];
cmdargs[0] = depotPath + "/*";
P4Command cmd = new P4Command(rep, "files", true, cmdargs);
P4CommandResult results = cmd.Run(null);
if (results != null && results.TaggedOutput != null)
{
    foreach (TaggedObject obj in results.TaggedOutput)
    {
        // do something with file list if you want
    }
}
else
{                        
    Console.WriteLine("No files in this directory!");                        
}

Basically it's using similar logic as GetFileMetaData, but using a lower level command to get tagged output from the server directly. Then you can check the result set for the existence of any files in the directory before you call the other methods.

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