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}");
|
$"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 renameStamp = DateTime.UtcNow.ToString("yyyyMMdd-HHmmss");
|
||||||
var resolutions = preview.Items.Select(item => new ImportResolution(
|
var resolutionsMap = new Dictionary<(string, string), ImportResolution>();
|
||||||
item.EntityType,
|
foreach (var item in preview.Items)
|
||||||
item.Name,
|
{
|
||||||
item.Kind switch
|
var action = item.Kind switch
|
||||||
{
|
{
|
||||||
ConflictKind.New => ResolutionAction.Add,
|
ConflictKind.New => ResolutionAction.Add,
|
||||||
ConflictKind.Identical => ResolutionAction.Skip,
|
ConflictKind.Identical => ResolutionAction.Skip,
|
||||||
ConflictKind.Modified => policy,
|
ConflictKind.Modified => policy,
|
||||||
_ => ResolutionAction.Skip,
|
_ => ResolutionAction.Skip,
|
||||||
},
|
};
|
||||||
(item.Kind == ConflictKind.Modified && policy == ResolutionAction.Rename)
|
var renameTo = (item.Kind == ConflictKind.Modified && policy == ResolutionAction.Rename)
|
||||||
? $"{item.Name}-imported-{renameStamp}"
|
? $"{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)
|
private static byte[] DecodeBundle(string base64)
|
||||||
|
|||||||
Reference in New Issue
Block a user