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  }