Add --clear-duplicate-external-refs flag to bd import
Fixes GH-234 by providing automatic resolution for duplicate external_ref values instead of forcing manual JSONL editing. Changes: - Add ClearDuplicateExternalRefs option to importer.Options - Modify validateNoDuplicateExternalRefs to clear duplicates when enabled - Keep first occurrence, clear rest when flag is set - Enhanced error message to suggest the flag - Add comprehensive tests for the new behavior Usage: bd import -i issues.jsonl --clear-duplicate-external-refs Amp-Thread-ID: https://ampcode.com/threads/T-932dcf45-76f2-4994-9b5c-a6eb20a86036 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -33,6 +33,7 @@ Behavior:
|
||||
dryRun, _ := cmd.Flags().GetBool("dry-run")
|
||||
renameOnImport, _ := cmd.Flags().GetBool("rename-on-import")
|
||||
dedupeAfter, _ := cmd.Flags().GetBool("dedupe-after")
|
||||
clearDuplicateExternalRefs, _ := cmd.Flags().GetBool("clear-duplicate-external-refs")
|
||||
orphanHandling, _ := cmd.Flags().GetString("orphan-handling")
|
||||
|
||||
// Open input
|
||||
@@ -95,11 +96,12 @@ Behavior:
|
||||
|
||||
// Phase 2: Use shared import logic
|
||||
opts := ImportOptions{
|
||||
DryRun: dryRun,
|
||||
SkipUpdate: skipUpdate,
|
||||
Strict: strict,
|
||||
RenameOnImport: renameOnImport,
|
||||
OrphanHandling: orphanHandling,
|
||||
DryRun: dryRun,
|
||||
SkipUpdate: skipUpdate,
|
||||
Strict: strict,
|
||||
RenameOnImport: renameOnImport,
|
||||
ClearDuplicateExternalRefs: clearDuplicateExternalRefs,
|
||||
OrphanHandling: orphanHandling,
|
||||
}
|
||||
|
||||
result, err := importIssuesCore(ctx, dbPath, store, allIssues, opts)
|
||||
@@ -265,6 +267,7 @@ func init() {
|
||||
importCmd.Flags().Bool("dedupe-after", false, "Detect and report content duplicates after import")
|
||||
importCmd.Flags().Bool("dry-run", false, "Preview collision detection without making changes")
|
||||
importCmd.Flags().Bool("rename-on-import", false, "Rename imported issues to match database prefix (updates all references)")
|
||||
importCmd.Flags().Bool("clear-duplicate-external-refs", false, "Clear duplicate external_ref values (keeps first occurrence)")
|
||||
importCmd.Flags().String("orphan-handling", "", "How to handle missing parent issues: strict/resurrect/skip/allow (default: use config or 'allow')")
|
||||
importCmd.Flags().BoolVar(&jsonOutput, "json", false, "Output import statistics in JSON format")
|
||||
rootCmd.AddCommand(importCmd)
|
||||
|
||||
@@ -158,12 +158,13 @@ func issueDataChanged(existing *types.Issue, updates map[string]interface{}) boo
|
||||
|
||||
// ImportOptions configures how the import behaves
|
||||
type ImportOptions struct {
|
||||
DryRun bool // Preview changes without applying them
|
||||
SkipUpdate bool // Skip updating existing issues (create-only mode)
|
||||
Strict bool // Fail on any error (dependencies, labels, etc.)
|
||||
RenameOnImport bool // Rename imported issues to match database prefix
|
||||
SkipPrefixValidation bool // Skip prefix validation (for auto-import)
|
||||
OrphanHandling string // Orphan handling mode: strict/resurrect/skip/allow (empty = use config)
|
||||
DryRun bool // Preview changes without applying them
|
||||
SkipUpdate bool // Skip updating existing issues (create-only mode)
|
||||
Strict bool // Fail on any error (dependencies, labels, etc.)
|
||||
RenameOnImport bool // Rename imported issues to match database prefix
|
||||
SkipPrefixValidation bool // Skip prefix validation (for auto-import)
|
||||
ClearDuplicateExternalRefs bool // Clear duplicate external_ref values instead of erroring
|
||||
OrphanHandling string // Orphan handling mode: strict/resurrect/skip/allow (empty = use config)
|
||||
}
|
||||
|
||||
// ImportResult contains statistics about the import operation
|
||||
@@ -210,12 +211,13 @@ func importIssuesCore(ctx context.Context, dbPath string, store storage.Storage,
|
||||
|
||||
// Convert ImportOptions to importer.Options
|
||||
importerOpts := importer.Options{
|
||||
DryRun: opts.DryRun,
|
||||
SkipUpdate: opts.SkipUpdate,
|
||||
Strict: opts.Strict,
|
||||
RenameOnImport: opts.RenameOnImport,
|
||||
SkipPrefixValidation: opts.SkipPrefixValidation,
|
||||
OrphanHandling: importer.OrphanHandling(orphanHandling),
|
||||
DryRun: opts.DryRun,
|
||||
SkipUpdate: opts.SkipUpdate,
|
||||
Strict: opts.Strict,
|
||||
RenameOnImport: opts.RenameOnImport,
|
||||
SkipPrefixValidation: opts.SkipPrefixValidation,
|
||||
ClearDuplicateExternalRefs: opts.ClearDuplicateExternalRefs,
|
||||
OrphanHandling: importer.OrphanHandling(orphanHandling),
|
||||
}
|
||||
|
||||
// Delegate to the importer package
|
||||
|
||||
Reference in New Issue
Block a user