Repository: exercism/cli
Pull request #440 (2017-08-10 12:19:30)

[nextercism] Tweak solution implementation to better support download command
I realized as I was working on the download command that once we write the `solution` to a directory, we want to refer back to the directory.

I changed it so the methods for Solution are defined on the pointer rather than the value.


Patch:
diff --git a/cmd/open.go b/cmd/open.go
index 3414400..5448928 100644
--- a/cmd/open.go
+++ b/cmd/open.go
@@ -33,7 +33,7 @@ the solution you want to see on the website.
 		paths, err := ws.Locate(args[0])
 		BailOnError(err)
 
-		var solutions []workspace.Solution
+		var solutions []*workspace.Solution
 
 		for _, path := range paths {
 			solution, err := workspace.NewSolution(path)
@@ -49,7 +49,7 @@ the solution you want to see on the website.
 		}
 
 		if len(solutions) > 1 {
-			var mine []workspace.Solution
+			var mine []*workspace.Solution
 			for _, s := range solutions {
 				if s.IsRequester {
 					mine = append(mine, s)
diff --git a/workspace/solution.go b/workspace/solution.go
index 1a2ca0a..519ccbf 100644
--- a/workspace/solution.go
+++ b/workspace/solution.go
@@ -27,28 +27,28 @@ type Solution struct {
 }
 
 // NewSolution reads solution metadata from a file in the given directory.
-func NewSolution(dir string) (Solution, error) {
+func NewSolution(dir string) (*Solution, error) {
 	path := filepath.Join(dir, solutionFilename)
 	b, err := ioutil.ReadFile(path)
 	if err != nil {
-		return Solution{}, err
+		return &Solution{}, err
 	}
 	var s Solution
 	if err := json.Unmarshal(b, &s); err != nil {
-		return Solution{}, err
+		return &Solution{}, err
 	}
 	s.Dir = dir
-	return s, nil
+	return &s, nil
 }
 
 // Suffix is the serial numeric value appended to an exercise directory.
 // This is appended to avoid name conflicts, and does not indicate a particular
 // iteration.
-func (s Solution) Suffix() string {
+func (s *Solution) Suffix() string {
 	return strings.Trim(strings.Replace(filepath.Base(s.Dir), s.Exercise, "", 1), "-.")
 }
 
-func (s Solution) String() string {
+func (s *Solution) String() string {
 	str := fmt.Sprintf("%s/%s", s.Track, s.Exercise)
 	if s.Suffix() != "" {
 		str = fmt.Sprintf("%s (%s)", str, s.Suffix())
@@ -60,7 +60,7 @@ func (s Solution) String() string {
 }
 
 // Write stores solution metadata to a file.
-func (s Solution) Write(dir string) error {
+func (s *Solution) Write(dir string) error {
 	b, err := json.Marshal(s)
 	if err != nil {
 		return err
@@ -69,5 +69,6 @@ func (s Solution) Write(dir string) error {
 	if err := ioutil.WriteFile(path, b, os.FileMode(0644)); err != nil {
 		return err
 	}
+	s.Dir = dir
 	return visibility.HideFile(path)
 }
diff --git a/workspace/solutions.go b/workspace/solutions.go
index 4c5c4ba..5b97709 100644
--- a/workspace/solutions.go
+++ b/workspace/solutions.go
@@ -11,10 +11,10 @@ import (
 )
 
 // Solutions is a collection of solutions to interactively choose from.
-type Solutions []Solution
+type Solutions []*Solution
 
 // Pick lets a user interactively select a solution from a list.
-func (sx Solutions) Pick(prompt string) (Solution, error) {
+func (sx Solutions) Pick(prompt string) (*Solution, error) {
 	// If there's just one, then we're done here.
 	if len(sx) == 1 {
 		return sx[0], nil
@@ -24,12 +24,12 @@ func (sx Solutions) Pick(prompt string) (Solution, error) {
 
 	n, err := sx.ReadSelection(os.Stdin)
 	if err != nil {
-		return Solution{}, err
+		return &Solution{}, err
 	}
 
 	s, err := sx.Get(n)
 	if err != nil {
-		return Solution{}, err
+		return &Solution{}, err
 	}
 	return s, nil
 }
@@ -57,9 +57,9 @@ func (sx Solutions) ReadSelection(r io.Reader) (int, error) {
 
 // Get returns the solution corresponding to the number.
 // The list starts at 1, since that seems better in a user interface.
-func (sx Solutions) Get(n int) (Solution, error) {
+func (sx Solutions) Get(n int) (*Solution, error) {
 	if n <= 0 || n > len(sx) {
-		return Solution{}, errors.New("can't do that")
+		return &Solution{}, errors.New("can't do that")
 	}
 	return sx[n-1], nil
 }


Test patch:
diff --git a/workspace/solution_test.go b/workspace/solution_test.go
index f7ee793..fb62109 100644
--- a/workspace/solution_test.go
+++ b/workspace/solution_test.go
@@ -14,7 +14,7 @@ func TestSolution(t *testing.T) {
 	assert.NoError(t, err)
 	defer os.RemoveAll(dir)
 
-	s1 := Solution{
+	s1 := &Solution{
 		Track:       "a-track",
 		Exercise:    "bogus-exercise",
 		ID:          "abc",
diff --git a/workspace/solutions_test.go b/workspace/solutions_test.go
index 3c1cb04..27175d4 100644
--- a/workspace/solutions_test.go
+++ b/workspace/solutions_test.go
@@ -7,7 +7,7 @@ import (
 )
 
 func TestSolutions(t *testing.T) {
-	solutions := []Solution{
+	solutions := []*Solution{
 		{Track: "a", Exercise: "foo"},
 		{Track: "b", Exercise: "foo"},
 		{Track: "c", Exercise: "foo"},