UGS: Add a command for listing submitted changes ("ugs changes -count=123 -lines=3")

#preflight none

[CL 18559173 by Ben Marsh in ue5-main branch]
This commit is contained in:
Ben Marsh
2022-01-10 09:33:30 -05:00
parent 7b50b4950e
commit 4974dfe934
4 changed files with 152 additions and 58 deletions
@@ -18,59 +18,6 @@ using System.Threading.Tasks;
namespace UnrealGameSync
{
class PerforceChangeDetails
{
/// <summary>
/// Set of extensions to treat as code
/// </summary>
static readonly HashSet<string> CodeExtensions = new HashSet<string>
{
".c",
".cc",
".cpp",
".m",
".mm",
".rc",
".cs",
".csproj",
".h",
".hpp",
".inl",
".usf",
".ush",
".uproject",
".uplugin",
".sln"
};
public string Description;
public bool bContainsCode;
public bool bContainsContent;
public PerforceChangeDetails(DescribeRecord DescribeRecord)
{
Description = DescribeRecord.Description;
// Check whether the files are code or content
foreach(DescribeFileRecord File in DescribeRecord.Files)
{
if(CodeExtensions.Any(Extension => File.DepotFile.EndsWith(Extension, StringComparison.OrdinalIgnoreCase)))
{
bContainsCode = true;
}
else
{
bContainsContent = true;
}
if (bContainsCode && bContainsContent)
{
break;
}
}
}
}
interface IArchiveInfoSource
{
IReadOnlyList<IArchiveInfo> AvailableArchives { get; }
@@ -66,6 +66,10 @@ namespace UnrealGameSyncCmd
"ugs switch [project name|project path|stream]",
"Changes the active project to the one in the workspace with the given name, or switches to a new stream."
),
new CommandInfo("changes", typeof(ChangesCommand),
"ugs changes",
"List recently submitted changes to the current branch."
),
new CommandInfo("config", typeof(ConfigCommand),
"ugs config",
"Updates the configuration for the current workspace."
@@ -580,6 +584,71 @@ namespace UnrealGameSyncCmd
}
}
class ChangesCommand : Command
{
public override async Task ExecuteAsync(CommandContext Context)
{
ILogger Logger = Context.Logger;
int Count = Context.Arguments.GetIntegerOrDefault("-Count=", 10);
int LineCount = Context.Arguments.GetIntegerOrDefault("-Lines=", 3);
Context.Arguments.CheckAllArgumentsUsed(Context.Logger);
UserWorkspaceSettings Settings = ReadRequiredUserWorkspaceSettings();
using IPerforceConnection PerforceClient = await ConnectAsync(Settings, Context.LoggerFactory);
List<ChangesRecord> Changes = await PerforceClient.GetChangesAsync(ChangesOptions.None, Count, ChangeStatus.Submitted, $"//{Settings.ClientName}/...");
foreach(IEnumerable<ChangesRecord> ChangesBatch in Changes.Batch(10))
{
List<DescribeRecord> DescribeRecords = await PerforceClient.DescribeAsync(ChangesBatch.Select(x => x.Number).ToArray());
Logger.LogInformation(" Change Type Author Description");
foreach (DescribeRecord DescribeRecord in DescribeRecords)
{
PerforceChangeDetails Details = new PerforceChangeDetails(DescribeRecord);
string Type;
if (Details.bContainsCode)
{
if (Details.bContainsContent)
{
Type = "Both";
}
else
{
Type = "Code";
}
}
else
{
if (Details.bContainsContent)
{
Type = "Content";
}
else
{
Type = "None";
}
}
string Author = StringUtils.Truncate(DescribeRecord.User, 15);
List<string> Lines = StringUtils.WordWrap(Details.Description, Math.Max(ConsoleUtils.WindowWidth - 40, 10)).ToList();
if (Lines.Count == 0)
{
Lines.Add(String.Empty);
}
Logger.LogInformation(" {Change,-9} {Type,-8} {Author,-15} {Description}", DescribeRecord.Number, Type, Author, Lines[0]);
for (int LineIndex = 1; LineIndex < LineCount; LineIndex++)
{
Logger.LogInformation(" {Description}", Lines[LineIndex]);
}
}
}
}
}
class ConfigCommand : Command
{
public override Task ExecuteAsync(CommandContext Context)
@@ -30,6 +30,59 @@ namespace UnrealGameSync
}
}
public class PerforceChangeDetails
{
/// <summary>
/// Set of extensions to treat as code
/// </summary>
static readonly HashSet<string> CodeExtensions = new HashSet<string>
{
".c",
".cc",
".cpp",
".m",
".mm",
".rc",
".cs",
".csproj",
".h",
".hpp",
".inl",
".usf",
".ush",
".uproject",
".uplugin",
".sln"
};
public string Description;
public bool bContainsCode;
public bool bContainsContent;
public PerforceChangeDetails(DescribeRecord DescribeRecord)
{
Description = DescribeRecord.Description;
// Check whether the files are code or content
foreach (DescribeFileRecord File in DescribeRecord.Files)
{
if (CodeExtensions.Any(Extension => File.DepotFile.EndsWith(Extension, StringComparison.OrdinalIgnoreCase)))
{
bContainsCode = true;
}
else
{
bContainsContent = true;
}
if (bContainsCode && bContainsContent)
{
break;
}
}
}
}
public static class Utility
{
static JsonSerializerOptions GetDefaultJsonSerializerOptions()