123 lines
4.5 KiB
C#
123 lines
4.5 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using Microsoft.Build.Framework;
|
|
using Microsoft.Build.Utilities;
|
|
|
|
namespace RepoTasks
|
|
{
|
|
public class JoinItems : Task
|
|
{
|
|
[Required]
|
|
public ITaskItem[] Left { get; set; }
|
|
|
|
[Required]
|
|
public ITaskItem[] Right { get; set; }
|
|
|
|
// The metadata to use as the new item spec. If not specified, LeftKey is used.
|
|
public string LeftItemSpec { get; set; }
|
|
|
|
// LeftKey and RightKey: The metadata to join on. If not set, then use the ItemSpec
|
|
public string LeftKey { get; set; }
|
|
|
|
public string RightKey { get; set; }
|
|
|
|
|
|
// LeftMetadata and RightMetadata: The metadata names to include in the result. Specify "*" to include all metadata
|
|
public string[] LeftMetadata { get; set; }
|
|
|
|
public string[] RightMetadata { get; set; }
|
|
|
|
|
|
[Output]
|
|
public ITaskItem[] JoinResult { get; private set; }
|
|
|
|
public override bool Execute()
|
|
{
|
|
bool useAllLeftMetadata = LeftMetadata != null && LeftMetadata.Length == 1 && LeftMetadata[0] == "*";
|
|
bool useAllRightMetadata = RightMetadata != null && RightMetadata.Length == 1 && RightMetadata[0] == "*";
|
|
var newItemSpec = string.IsNullOrEmpty(LeftItemSpec)
|
|
? LeftKey
|
|
: LeftItemSpec;
|
|
|
|
JoinResult = Left.Join(Right,
|
|
item => GetKeyValue(LeftKey, item),
|
|
item => GetKeyValue(RightKey, item),
|
|
(left, right) =>
|
|
{
|
|
// If including all metadata from left items and none from right items, just return left items directly
|
|
if (useAllLeftMetadata &&
|
|
string.IsNullOrEmpty(LeftKey) &&
|
|
string.IsNullOrEmpty(LeftItemSpec) &&
|
|
(RightMetadata == null || RightMetadata.Length == 0))
|
|
{
|
|
return left;
|
|
}
|
|
|
|
// If including all metadata from right items and none from left items, just return the right items directly
|
|
if (useAllRightMetadata &&
|
|
string.IsNullOrEmpty(RightKey) &&
|
|
string.IsNullOrEmpty(LeftItemSpec) &&
|
|
(LeftMetadata == null || LeftMetadata.Length == 0))
|
|
{
|
|
return right;
|
|
}
|
|
|
|
var ret = new TaskItem(GetKeyValue(newItemSpec, left));
|
|
|
|
// Weird ordering here is to prefer left metadata in all cases, as CopyToMetadata doesn't overwrite any existing metadata
|
|
if (useAllLeftMetadata)
|
|
{
|
|
// CopyMetadata adds an OriginalItemSpec, which we don't want. So we subsequently remove it
|
|
left.CopyMetadataTo(ret);
|
|
ret.RemoveMetadata("OriginalItemSpec");
|
|
}
|
|
|
|
if (!useAllRightMetadata && RightMetadata != null)
|
|
{
|
|
foreach (string name in RightMetadata)
|
|
{
|
|
ret.SetMetadata(name, right.GetMetadata(name));
|
|
}
|
|
}
|
|
|
|
if (!useAllLeftMetadata && LeftMetadata != null)
|
|
{
|
|
foreach (string name in LeftMetadata)
|
|
{
|
|
ret.SetMetadata(name, left.GetMetadata(name));
|
|
}
|
|
}
|
|
|
|
if (useAllRightMetadata)
|
|
{
|
|
// CopyMetadata adds an OriginalItemSpec, which we don't want. So we subsequently remove it
|
|
right.CopyMetadataTo(ret);
|
|
ret.RemoveMetadata("OriginalItemSpec");
|
|
}
|
|
|
|
return (ITaskItem)ret;
|
|
},
|
|
StringComparer.OrdinalIgnoreCase).ToArray();
|
|
|
|
return true;
|
|
}
|
|
|
|
static string GetKeyValue(string key, ITaskItem item)
|
|
{
|
|
if (string.IsNullOrEmpty(key))
|
|
{
|
|
return item.ItemSpec;
|
|
}
|
|
else
|
|
{
|
|
return item.GetMetadata(key);
|
|
}
|
|
}
|
|
}
|
|
}
|