-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FEATURE] Introduces homebrew task #67
Changes from 8 commits
bdfd9ca
0974600
26d919d
541d75e
10a54e3
3df181d
de3628e
1cbea86
ec40903
55fbb18
56037c7
fbf4a50
6ec2001
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package helpers | ||
|
||
import ( | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/devbuddy/devbuddy/pkg/utils" | ||
) | ||
|
||
type caskroom struct { | ||
prefix string | ||
} | ||
|
||
type cellar struct { | ||
prefix string | ||
} | ||
|
||
// Homebrew represent an homebrew installation | ||
type Homebrew struct { | ||
caskroom *caskroom | ||
cellar *cellar | ||
} | ||
|
||
// NewHomebrew is returning a new Cellar | ||
func NewHomebrew() *Homebrew { | ||
prefix := "/usr/local" | ||
|
||
return &Homebrew{ | ||
cellar: &cellar{prefix: prefix}, | ||
caskroom: &caskroom{prefix: prefix}, | ||
} | ||
} | ||
|
||
// NewHomebrewWithPrefix is returning a new Cellar at prefix | ||
func NewHomebrewWithPrefix(prefix string) *Homebrew { | ||
return &Homebrew{ | ||
cellar: &cellar{prefix: prefix}, | ||
caskroom: &caskroom{prefix: prefix}, | ||
} | ||
} | ||
|
||
// IsInstalled returns true if `pkg` is installed in cellar or in caskroom | ||
func (h *Homebrew) IsInstalled(formula string) (installed bool) { | ||
path := buildFormulaPath(formula) | ||
|
||
return h.cellar.IsInstalled(path) || h.caskroom.IsInstalled(path) | ||
} | ||
|
||
func buildFormulaPath(filename string) string { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The logic doesn't seem so obvious, I feel like we should explain what happens here. |
||
results := strings.Split(filename, "/") | ||
formula := results[len(results)-1] | ||
return strings.TrimSuffix(formula, filepath.Ext(formula)) | ||
} | ||
|
||
// IsInstalled returns true if formulua was installed in Caskrook | ||
func (c *caskroom) IsInstalled(formula string) bool { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Those methods (also on cellar) looks like they should be private. |
||
path := "/opt/homebrew-cask/Caskroom" | ||
|
||
if !utils.PathExists(path) { | ||
path = filepath.Join(c.prefix, "Caskroom") | ||
} | ||
|
||
return utils.PathExists(filepath.Join(path, formula)) | ||
} | ||
|
||
// IsInstalled returns true if formulua was installed in cellar | ||
func (c *cellar) IsInstalled(formula string) bool { | ||
path := filepath.Join(c.prefix, "Cellar") | ||
|
||
path = filepath.Join(path, formula) | ||
return utils.PathExists(path) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package helpers | ||
|
||
import ( | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestIsInCellar(t *testing.T) { | ||
prefix, err := ioutil.TempDir("/tmp", "dad-brew") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
But all that is annoying, let's use Filet (it's already used in this project): |
||
require.NoError(t, err, "ioutil.TempDir() failed") | ||
|
||
cellarPath := filepath.Join(prefix, "Cellar") | ||
|
||
caskroomPath := filepath.Join(prefix, "Caskroom") | ||
|
||
os.MkdirAll(filepath.Join(cellarPath, "curl", "1.2.3"), os.ModePerm) | ||
os.MkdirAll(filepath.Join(caskroomPath, "emacs", "26.1"), os.ModePerm) | ||
|
||
h := NewHomebrewWithPrefix(prefix) | ||
|
||
require.Truef(t, h.IsInstalled("curl"), "Curl is properly installed in Cellar %s", cellarPath) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I missed those |
||
require.Falsef(t, h.IsInstalled("vim"), "vim is missing from Homebrew %s", prefix) | ||
require.True(t, h.IsInstalled("emacs"), "Emacs is properly installed in caskroom %s", caskroomPath) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package tasks | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/devbuddy/devbuddy/pkg/helpers" | ||
) | ||
|
||
func init() { | ||
allTasks["homebrew"] = newHomebrew | ||
} | ||
|
||
type Homebrew struct { | ||
formulas []string | ||
} | ||
|
||
func newHomebrew(config *taskConfig) (Task, error) { | ||
task := &Homebrew{} | ||
|
||
for _, value := range config.payload.([]interface{}) { | ||
if v, ok := value.(string); ok { | ||
task.formulas = append(task.formulas, v) | ||
} else { | ||
return nil, fmt.Errorf("invalid homebrew formulas") | ||
} | ||
} | ||
|
||
if len(task.formulas) == 0 { | ||
return nil, fmt.Errorf("no homebrew formulas specified") | ||
} | ||
|
||
return task, nil | ||
} | ||
|
||
func (h *Homebrew) name() string { | ||
return "Homebrew" | ||
} | ||
|
||
func (h *Homebrew) header() string { | ||
return strings.Join(h.formulas, ", ") | ||
} | ||
|
||
func (h *Homebrew) actions(ctx *context) (actions []taskAction) { | ||
for _, f := range h.formulas { | ||
actions = append(actions, &brewInstall{formula: f}) | ||
} | ||
return | ||
} | ||
|
||
type brewInstall struct { | ||
formula string | ||
success bool | ||
} | ||
|
||
func (b *brewInstall) description() string { | ||
return fmt.Sprintf("installing %s", b.formula) | ||
} | ||
|
||
func (b *brewInstall) needed(ctx *context) (bool, error) { | ||
return !b.success, nil | ||
} | ||
|
||
func (b *brewInstall) run(ctx *context) error { | ||
brew := helpers.NewHomebrew() | ||
|
||
if !brew.IsInstalled(b.formula) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This condition should be in the |
||
err := command(ctx, "brew", "install", b.formula).AddOutputFilter("already satisfied").Run() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah not really cause anyway we should just display those informations |
||
|
||
if err != nil { | ||
return fmt.Errorf("Homebrew failed: %s", err) | ||
} | ||
} | ||
b.success = true | ||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package tasks | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestHomebrew(t *testing.T) { | ||
task := ensureLoadTestTask(t, ` | ||
homebrew: | ||
- file1 | ||
- file2 | ||
`) | ||
require.Equal(t, task.(*Homebrew).formulas, []string{"file1", "file2"}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: do we need this to be public in the end?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really...