fix(cli): dedupe import resolutions before ApplyAsync
PreviewAsync can emit multiple ImportPreviewItem rows for the same (EntityType, Name) -- one per modified member of a template, for example. ApplyAsync internally calls .ToDictionary() on the resolutions list and throws ArgumentException on duplicate keys. The Central UI's BuildDefaultResolutions already dedupes via a dictionary assignment (last-write-wins). Mirror that in the CLI handler so 'bundle import' tolerates the duplicate-rows shape the preview returns.
This commit is contained in:
@@ -1838,22 +1838,29 @@ public class ManagementActor : ReceiveActor
|
||||
$"Bundle has {blockers.Count} blocker(s); import aborted. {details}");
|
||||
}
|
||||
|
||||
// Dedupe by (EntityType, Name) -- the preview can emit multiple rows per
|
||||
// entity (e.g. one row per modified member of a template), but ApplyAsync
|
||||
// requires a unique resolution per key. Last-write-wins matches the
|
||||
// Central UI's TransportImport.BuildDefaultResolutions behavior.
|
||||
var renameStamp = DateTime.UtcNow.ToString("yyyyMMdd-HHmmss");
|
||||
var resolutions = preview.Items.Select(item => new ImportResolution(
|
||||
item.EntityType,
|
||||
item.Name,
|
||||
item.Kind switch
|
||||
var resolutionsMap = new Dictionary<(string, string), ImportResolution>();
|
||||
foreach (var item in preview.Items)
|
||||
{
|
||||
var action = item.Kind switch
|
||||
{
|
||||
ConflictKind.New => ResolutionAction.Add,
|
||||
ConflictKind.Identical => ResolutionAction.Skip,
|
||||
ConflictKind.Modified => policy,
|
||||
_ => ResolutionAction.Skip,
|
||||
},
|
||||
(item.Kind == ConflictKind.Modified && policy == ResolutionAction.Rename)
|
||||
};
|
||||
var renameTo = (item.Kind == ConflictKind.Modified && policy == ResolutionAction.Rename)
|
||||
? $"{item.Name}-imported-{renameStamp}"
|
||||
: null)).ToList();
|
||||
: null;
|
||||
resolutionsMap[(item.EntityType, item.Name)] = new ImportResolution(
|
||||
item.EntityType, item.Name, action, renameTo);
|
||||
}
|
||||
|
||||
return await importer.ApplyAsync(session.SessionId, resolutions, username);
|
||||
return await importer.ApplyAsync(session.SessionId, resolutionsMap.Values.ToList(), username);
|
||||
}
|
||||
|
||||
private static byte[] DecodeBundle(string base64)
|
||||
|
||||
Reference in New Issue
Block a user