Skip to content

Commit a325c52

Browse files
committed
Made Resolver state variables as fields
1 parent 00b3516 commit a325c52

File tree

1 file changed

+37
-24
lines changed

1 file changed

+37
-24
lines changed

Diff for: resolver.go

+37-24
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ func (set Releases[R, D]) SortDescent() {
4848
// dependency resolution
4949
type Resolver[R Release[D], D Dependency] struct {
5050
releases map[string]Releases[R, D]
51+
52+
// resolver state
53+
solution map[string]R
54+
depsToProcess []D
55+
problematicDeps map[dependencyHash]int
5156
}
5257

5358
// NewResolver creates a new archive
@@ -75,9 +80,9 @@ func (ar *Resolver[R, D]) AddReleases(rels ...R) {
7580
// arguent using a backtracking algorithm. This function is NOT thread-safe.
7681
func (ar *Resolver[R, D]) Resolve(release R) Releases[R, D] {
7782
// Initial empty state of the resolver
78-
solution := map[string]R{}
79-
depsToProcess := []D{}
80-
problematicDeps := map[dependencyHash]int{}
83+
ar.solution = map[string]R{}
84+
ar.depsToProcess = []D{}
85+
ar.problematicDeps = map[dependencyHash]int{}
8186

8287
// Check if the release is in the archive
8388
if len(ar.releases[release.GetName()].FilterBy(&Equals{Version: release.GetVersion()})) == 0 {
@@ -86,9 +91,9 @@ func (ar *Resolver[R, D]) Resolve(release R) Releases[R, D] {
8691

8792
// Add the requested release to the solution and proceed
8893
// with the dependencies resolution
89-
solution[release.GetName()] = release
90-
depsToProcess = append(depsToProcess, release.GetDependencies()...)
91-
return ar.resolve(solution, depsToProcess, problematicDeps)
94+
ar.solution[release.GetName()] = release
95+
ar.depsToProcess = append(ar.depsToProcess, release.GetDependencies()...)
96+
return ar.resolve()
9297
}
9398

9499
type dependencyHash string
@@ -97,39 +102,45 @@ func hashDependency[D Dependency](dep D) dependencyHash {
97102
return dependencyHash(dep.GetName() + "/" + dep.GetConstraint().String())
98103
}
99104

100-
func (ar *Resolver[R, D]) resolve(solution map[string]R, depsToProcess []D, problematicDeps map[dependencyHash]int) Releases[R, D] {
101-
debug("deps to process: %s", depsToProcess)
102-
if len(depsToProcess) == 0 {
105+
func (ar *Resolver[R, D]) resolve() Releases[R, D] {
106+
debug("deps to process: %s", ar.depsToProcess)
107+
if len(ar.depsToProcess) == 0 {
103108
debug("All dependencies have been resolved.")
104109
var res Releases[R, D]
105-
for _, v := range solution {
110+
for _, v := range ar.solution {
106111
res = append(res, v)
107112
}
108113
return res
109114
}
110115

111116
// Pick the first dependency in the deps to process
112-
dep := depsToProcess[0]
117+
dep := ar.depsToProcess[0]
113118
depName := dep.GetName()
114119
debug("Considering next dep: %s", depName)
115120

116121
// If a release is already picked in the solution check if it match the dep
117-
if existingRelease, has := solution[depName]; has {
122+
if existingRelease, has := ar.solution[depName]; has {
118123
if dep.GetConstraint().Match(existingRelease.GetVersion()) {
119124
debug("%s already in solution and matching", existingRelease)
120-
return ar.resolve(solution, depsToProcess[1:], problematicDeps)
125+
oldDepsToProcess := ar.depsToProcess
126+
ar.depsToProcess = ar.depsToProcess[1:]
127+
if res := ar.resolve(); res != nil {
128+
return res
129+
}
130+
ar.depsToProcess = oldDepsToProcess
131+
return nil
121132
}
122133
debug("%s already in solution do not match... rollingback", existingRelease)
123134
return nil
124135
}
125136

126137
// Otherwise start backtracking the dependency
127-
releases := ar.releases[dep.GetName()].FilterBy(dep.GetConstraint())
138+
releases := ar.releases[depName].FilterBy(dep.GetConstraint())
128139

129140
// Consider the latest versions first
130141
releases.SortDescent()
131-
132142
debug("releases matching criteria: %s", releases)
143+
133144
backtracking_loop:
134145
for _, release := range releases {
135146
releaseDeps := release.GetDependencies()
@@ -142,21 +153,23 @@ backtracking_loop:
142153
}
143154
}
144155

145-
solution[depName] = release
146-
newDepsToProcess := append(depsToProcess[1:], deps...)
156+
ar.solution[depName] = release
157+
oldDepsToProcess := ar.depsToProcess
158+
ar.depsToProcess = append(ar.depsToProcess[1:], releaseDeps...)
147159
// bubble up problematics deps so they are processed first
148-
sort.Slice(newDepsToProcess, func(i, j int) bool {
149-
ci := hashDependency(newDepsToProcess[i])
150-
cj := hashDependency(newDepsToProcess[j])
151-
return problematicDeps[ci] > problematicDeps[cj]
160+
sort.Slice(ar.depsToProcess, func(i, j int) bool {
161+
ci := hashDependency(ar.depsToProcess[i])
162+
cj := hashDependency(ar.depsToProcess[j])
163+
return ar.problematicDeps[ci] > ar.problematicDeps[cj]
152164
})
153-
if res := ar.resolve(solution, newDepsToProcess, problematicDeps); res != nil {
165+
if res := ar.resolve(); res != nil {
154166
return res
155167
}
168+
ar.depsToProcess = oldDepsToProcess
156169
debug("%s did not work...", release)
157-
delete(solution, depName)
170+
delete(ar.solution, depName)
158171
}
159172

160-
problematicDeps[hashDependency(dep)]++
173+
ar.problematicDeps[hashDependency(dep)]++
161174
return nil
162175
}

0 commit comments

Comments
 (0)