-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- refactor: readStratumFIle()に関数抽出 - feat: supports dependencies installation - build: go mod tidy - feat: add progress UI - feat: すでに有効な依存はノータッチ
- Loading branch information
Showing
7 changed files
with
330 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package qpm | ||
|
||
import ( | ||
"context" | ||
"slices" | ||
"sync" | ||
) | ||
|
||
// dependencies stratumの依存しているstratumを再帰的に取得する | ||
func dependencies(c Config, a Action, os OS, stratumName string, knownDeps map[string][]string) error { | ||
if _, ok := knownDeps[stratumName]; ok { | ||
return nil | ||
} | ||
|
||
var deps []string | ||
if installed, error := IsAlreadyInstalled(stratumName); error != nil { | ||
return error | ||
} else if !installed { | ||
sf, err := readStratumFile(c.AquiferPath, stratumName) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for _, v := range sf[a.String()] { | ||
if slices.Contains(v.OS, os.String()) { | ||
deps = v.Dependency | ||
break | ||
} | ||
} | ||
} | ||
|
||
knownDeps[stratumName] = deps | ||
|
||
for _, v := range deps { | ||
if err := dependencies(c, a, os, v, knownDeps); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
type task struct { | ||
pkg string | ||
deps []string | ||
} | ||
|
||
type multiTaskExec struct { | ||
wg *sync.WaitGroup | ||
started bool | ||
tasks []task | ||
packages *sync.Map | ||
} | ||
|
||
func (m *multiTaskExec) add(pkg string, deps []string) { | ||
if m.started { | ||
panic("already started") | ||
} | ||
|
||
m.wg.Add(1) | ||
|
||
m.tasks = append(m.tasks, task{pkg: pkg, deps: deps}) | ||
|
||
if m.packages == nil { | ||
m.packages = &sync.Map{} | ||
} | ||
if _, ok := m.packages.Load(pkg); !ok { | ||
m.packages.Store(pkg, make(chan struct{})) | ||
} | ||
} | ||
|
||
func (*multiTaskExec) waitAllChans(chans []chan struct{}) { | ||
for _, c := range chans { | ||
for { | ||
if _, ok := <-c; !ok { | ||
break | ||
} | ||
} | ||
} | ||
} | ||
|
||
func (m *multiTaskExec) execTask(ctx context.Context, t task, f func(string)) { | ||
depChans := make([]chan struct{}, 0) | ||
for _, dep := range t.deps { | ||
c, ok := m.packages.Load(dep) | ||
if ok { | ||
depChans = append(depChans, c.(chan struct{})) | ||
} | ||
} | ||
|
||
m.waitAllChans(depChans) | ||
|
||
f(t.pkg) | ||
|
||
c, ok := m.packages.Load(t.pkg) | ||
if ok { | ||
close(c.(chan struct{})) | ||
m.packages.Delete(t.pkg) | ||
} | ||
} | ||
|
||
func (m *multiTaskExec) wait(f func(string)) { | ||
if m.started { | ||
panic("already started") | ||
} | ||
|
||
m.started = true | ||
|
||
for _, t := range m.tasks { | ||
go func(t task) { | ||
defer m.wg.Done() | ||
m.execTask(context.TODO(), t, f) | ||
}(t) | ||
} | ||
|
||
m.wg.Wait() | ||
} | ||
|
||
func newMultiTaskExec() *multiTaskExec { | ||
var wg sync.WaitGroup | ||
return &multiTaskExec{wg: &wg} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package qpm | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
) | ||
|
||
func TestQPM_dependencies(t *testing.T) { | ||
t.Parallel() | ||
|
||
c := Config{ | ||
AquiferPath: "./testdata/", | ||
} | ||
|
||
got := make(map[string][]string) | ||
|
||
// Act | ||
err := dependencies(c, Install, OS("linux"), "a", got) | ||
|
||
// Assert | ||
if cmp.Diff(nil, err) != "" { | ||
t.Errorf("%+v\n", err) | ||
} | ||
want := map[string][]string{ | ||
"a": {"b", "c"}, | ||
"b": {"c", "d", "e", "f"}, | ||
"c": {"f"}, | ||
"d": {"g"}, | ||
"e": {}, | ||
"f": {}, | ||
"g": {}, | ||
} | ||
if diff := cmp.Diff(want, got); diff != "" { | ||
t.Errorf("mismatch (-want +got):\n%s", diff) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.