github.com/comcast/canticle@v0.0.0-20161108184242-c53cface56e8/canticles/conflictresolver.go (about) 1 package canticles 2 3 import "fmt" 4 5 type ConflictResolver interface { 6 ResolveConflicts(deps *DependencySources) ([]*CanticleDependency, error) 7 } 8 9 type PreferLocalResolution struct { 10 } 11 12 func (pl *PreferLocalResolution) ResolveConflicts(deps *DependencySources) ([]*CanticleDependency, error) { 13 cdeps := make([]*CanticleDependency, 0, len(deps.Sources)) 14 for _, source := range deps.Sources { 15 if source.Err != nil { 16 return cdeps, fmt.Errorf("cant resolve error saving dep %s", source.Err.Error()) 17 } 18 cd := &CanticleDependency{ 19 Root: source.Root, 20 SourcePath: source.OnDiskSource, 21 Revision: source.OnDiskRevision, 22 } 23 cdeps = append(cdeps, cd) 24 } 25 return cdeps, nil 26 } 27 28 type PromptResolution struct { 29 Printf func(format string, a ...interface{}) (n int, err error) 30 Scanf func(format string, a ...interface{}) (n int, err error) 31 } 32 33 func (pr PromptResolution) ResolveConflicts(deps *DependencySources) ([]*CanticleDependency, error) { 34 cdeps := make([]*CanticleDependency, 0, len(deps.Sources)) 35 for _, dep := range deps.Sources { 36 cd, err := pr.ResolveConflict(dep) 37 if err != nil { 38 return nil, err 39 } 40 cdeps = append(cdeps, cd) 41 } 42 return cdeps, nil 43 } 44 45 func (pr PromptResolution) ResolveConflict(dep *DependencySource) (*CanticleDependency, error) { 46 cd := &CanticleDependency{Root: dep.Root} 47 var err error 48 size := dep.Revisions.Size() 49 switch { 50 case size > 1: 51 cd.Revision, err = pr.SelectRevision(dep) 52 if err != nil { 53 return cd, err 54 } 55 case size == 1: 56 cd.Revision = dep.Revisions.Array()[0] 57 } 58 size = dep.Sources.Size() 59 switch { 60 case size > 1: 61 cd.SourcePath, err = pr.SelectSource(dep) 62 case size == 1: 63 cd.SourcePath = dep.Sources.Array()[0] 64 } 65 return cd, err 66 } 67 68 func (pr PromptResolution) SelectRevision(dep *DependencySource) (string, error) { 69 return pr.ResolvePrompt(dep.Root, "revisions", dep.OnDiskRevision, dep.Revisions.Array()) 70 } 71 72 func (pr PromptResolution) SelectSource(dep *DependencySource) (string, error) { 73 return pr.ResolvePrompt(dep.Root, "sources", dep.OnDiskSource, dep.Sources.Array()) 74 } 75 76 // ResolvePrompt is used to prompt a user for a resolution between 77 // multiple alternates, wth ondisk marking the currently select 78 // option. 79 // TODO: Add some sort of auto completion here 80 func (pr PromptResolution) ResolvePrompt(pkg, conflict, ondisk string, alts []string) (string, error) { 81 pr.Printf("\nPackage %s has conflicting %s:\n", pkg, conflict) 82 for _, rev := range alts { 83 if rev == ondisk { 84 pr.Printf("%s %s\n", rev, "(current)") 85 continue 86 } 87 pr.Printf("%s\n", rev) 88 } 89 pr.Printf("Selection %s: ", conflict) 90 var choice string 91 _, err := pr.Scanf("%s", &choice) 92 return choice, err 93 }