Files
UnrealEngine/Engine/Source/Programs/Shared/EpicGames.Perforce/PerforceChangeView.cs
2025-05-18 13:04:45 +08:00

106 lines
2.8 KiB
C#

// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text.RegularExpressions;
namespace EpicGames.Perforce
{
/// <summary>
/// Represents a change view from a clientspec or stream
/// </summary>
public class PerforceChangeView
{
/// <summary>
/// List of entries for this change view
/// </summary>
public List<PerforceChangeViewEntry> Entries { get; } = new List<PerforceChangeViewEntry>();
/// <summary>
/// Determines if a file revision is visible
/// </summary>
/// <param name="depotFile">Path to the depot file</param>
/// <param name="change">Change number of the file</param>
public bool IsVisible(string depotFile, int change)
{
bool visible = true;
foreach (PerforceChangeViewEntry entry in Entries)
{
if (entry.Matches(depotFile))
{
visible = change <= entry.Change;
}
}
return visible;
}
/// <summary>
/// Parse a change view from a specification
/// </summary>
/// <param name="lines">Lines for the change view</param>
/// <param name="ignoreCase">Whether this will be evaluated in the context of a case-insensitive server</param>
public static PerforceChangeView Parse(IEnumerable<string> lines, bool ignoreCase)
{
PerforceChangeView changeView = new PerforceChangeView();
foreach (string line in lines)
{
if (!String.IsNullOrWhiteSpace(line))
{
// Skip over lines with unsupported formatting (generally @label instead of @changenumber)
try
{
changeView.Entries.Add(new PerforceChangeViewEntry(line, ignoreCase));
}
catch (FormatException)
{
// don't do anything
}
}
}
return changeView;
}
}
/// <summary>
/// Entry for a change view
/// </summary>
public class PerforceChangeViewEntry
{
/// <summary>
/// Pattern to match
/// </summary>
public string Path { get; }
/// <summary>
/// Change to be imported at
/// </summary>
public long Change { get; }
readonly Regex _pathRegex;
/// <summary>
/// Constructor
/// </summary>
public PerforceChangeViewEntry(string pattern, bool ignoreCase)
{
int atIdx = pattern.LastIndexOf('@');
Path = pattern.Substring(0, atIdx);
Change = Int64.Parse(pattern.AsSpan(atIdx + 1), NumberStyles.None);
string regexPattern = Regex.Escape(Path);
regexPattern = regexPattern.Replace(@"\?", ".", StringComparison.Ordinal);
regexPattern = regexPattern.Replace(@"\.\.\.", ".*", StringComparison.Ordinal);
_pathRegex = new Regex($"^{regexPattern}$", ignoreCase ? RegexOptions.IgnoreCase : RegexOptions.None);
}
/// <summary>
/// Determine
/// </summary>
/// <param name="depotPath"></param>
/// <returns></returns>
public bool Matches(string depotPath) => _pathRegex.IsMatch(depotPath);
}
}