Skip to content

Commit

Permalink
Move conflict checking to its own file
Browse files Browse the repository at this point in the history
  • Loading branch information
Morganamilo committed Mar 22, 2018
1 parent 804bd45 commit 4a8ec94
Show file tree
Hide file tree
Showing 2 changed files with 362 additions and 354 deletions.
362 changes: 362 additions & 0 deletions conflicts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,362 @@
package main

import (
"fmt"
"strings"
"sync"

alpm "github.com/jguer/go-alpm"
gopkg "github.com/mikkeloscar/gopkgbuild"
)

func checkInnerConflict(name string, conflict string, conflicts map[string]stringSet, dc *depCatagories) {
add := func(h map[string]stringSet, n string, v string) {
_, ok := h[n]
if !ok {
h[n] = make(stringSet)
}
h[n].set(v)
}


deps, err := gopkg.ParseDeps([]string{conflict})
if err != nil {
return
}
dep := deps[0]

for _, pkg := range dc.Aur {
if name == pkg.Name {
continue
}

version, err := gopkg.NewCompleteVersion(pkg.Version)
if err != nil {
return
}
if dep.Name == pkg.Name && version.Satisfies(dep) {
add(conflicts, name, pkg.Name)
continue
}

for _, provide := range pkg.Provides {
// Provides are not versioned unless explicitly defined as
// such. If a conflict is versioned but a provide is
// not it can not conflict.
if (dep.MaxVer != nil || dep.MinVer != nil) && !strings.ContainsAny(provide, "><=") {
continue
}

var version *gopkg.CompleteVersion
var err error

pname, pversion := splitNameFromDep(provide)

if dep.Name != pname {
continue
}

if pversion != "" {
version, err = gopkg.NewCompleteVersion(provide)
if err != nil {
return
}
}

if version != nil && version.Satisfies(dep) {
add(conflicts, name, pkg.Name)
break
}

}
}

for _, pkg := range dc.Repo {
if name == pkg.Name() {
continue
}

version, err := gopkg.NewCompleteVersion(pkg.Version())
if err != nil {
return
}

if dep.Name == pkg.Name() && version.Satisfies(dep) {
add(conflicts, name, pkg.Name())
continue
}

pkg.Provides().ForEach(func(provide alpm.Depend) error {
// Provides are not versioned unless explicitly defined as
// such. If a conflict is versioned but a provide is
// not it can not conflict.
if (dep.MaxVer != nil || dep.MinVer != nil) && provide.Mod == alpm.DepModAny {
return nil
}

if dep.Name != pkg.Name() {
return nil
}

if provide.Mod == alpm.DepModAny {
add(conflicts, name, pkg.Name())
return fmt.Errorf("")
}

version, err := gopkg.NewCompleteVersion(provide.Version)
if err != nil {
return nil
}

if version.Satisfies(dep) {
add(conflicts, name, pkg.Name())
return fmt.Errorf("")
}

return nil
})
}
}

func checkForInnerConflicts(dc *depCatagories) (map[string]stringSet) {
conflicts := make(map[string]stringSet)

for _, pkg := range dc.Aur {
for _, cpkg := range pkg.Conflicts {
checkInnerConflict(pkg.Name, cpkg, conflicts, dc)
}
}

for _, pkg := range dc.Repo {
pkg.Conflicts().ForEach(func(conflict alpm.Depend) error {
checkInnerConflict(pkg.Name(), conflict.String(), conflicts, dc)
return nil
})
}

return conflicts
}

func checkReverseConflict(name string, provide string, conflicts map[string]stringSet) error {
add := func(h map[string]stringSet, n string, v string) {
_, ok := h[n]
if !ok {
h[n] = make(stringSet)
}
h[n].set(v)
}

var version *gopkg.CompleteVersion
var err error

localDb, err := alpmHandle.LocalDb()
if err != nil {
return err
}

pname, pversion := splitNameFromDep(provide)
if pversion != "" {
version, err = gopkg.NewCompleteVersion(pversion)
if err != nil {
return nil
}
}


localDb.PkgCache().ForEach(func(pkg alpm.Package) error {
if name == pkg.Name() {
return nil
}

pkg.Conflicts().ForEach(func(conflict alpm.Depend) error {
deps, err := gopkg.ParseDeps([]string{conflict.String()})
if err != nil {
return nil
}

dep := deps[0]
// Provides are not versioned unless explicitly defined as
// such. If a conflict is versioned but a provide is
// not it can not conflict.
if (dep.MaxVer != nil || dep.MinVer != nil) && version == nil {
return nil
}

if dep.Name != pname {
return nil
}

if version == nil || version.Satisfies(dep) {
// Todo
add(conflicts, name, pkg.Name() + " (" + provide + ")")
return fmt.Errorf("")
}

return nil
})

return nil
})

return nil
}

func checkConflict(name string, conflict string, conflicts map[string]stringSet) error {
add := func(h map[string]stringSet, n string, v string) {
_, ok := h[n]
if !ok {
h[n] = make(stringSet)
}
h[n].set(v)
}

localDb, err := alpmHandle.LocalDb()
if err != nil {
return err
}

deps, err := gopkg.ParseDeps([]string{conflict})
if err != nil {
return nil
}

dep := deps[0]

localDb.PkgCache().ForEach(func(pkg alpm.Package) error {
if name == pkg.Name() {
return nil
}

version, err := gopkg.NewCompleteVersion(pkg.Version())
if err != nil {
return nil
}

if dep.Name == pkg.Name() && version.Satisfies(dep) {
add(conflicts, name, pkg.Name())
return nil
}

pkg.Provides().ForEach(func(provide alpm.Depend) error {
if dep.Name != provide.Name {
return nil
}

// Provides arent version unless explicitly defined as
// such. If a conflict is versioned but a provide is
// not it can not conflict.
if (dep.MaxVer != nil || dep.MinVer != nil) && provide.Mod == alpm.DepModAny {
return nil
}

if provide.Mod == alpm.DepModAny {
add(conflicts, name, pkg.Name() + " (" + provide.Name + ")")
return fmt.Errorf("")
}

version, err := gopkg.NewCompleteVersion(provide.Version)
if err != nil {
return nil
}

if version.Satisfies(dep) {
add(conflicts, name, pkg.Name() + " (" + provide.Name + ")")
return fmt.Errorf("")
}

return nil
})

return nil
})

return nil
}


func checkForConflicts(dc *depCatagories) (map[string]stringSet, error) {
conflicts := make(map[string]stringSet)

for _, pkg := range dc.Aur {
for _, cpkg := range pkg.Conflicts {
checkConflict(pkg.Name, cpkg, conflicts)
}
}

for _, pkg := range dc.Repo {
pkg.Conflicts().ForEach(func(conflict alpm.Depend) error {
checkConflict(pkg.Name(), conflict.String(), conflicts)
return nil
})
}

for _, pkg := range dc.Aur {
checkReverseConflict(pkg.Name, pkg.Name, conflicts)
for _, ppkg := range pkg.Provides {
checkReverseConflict(pkg.Name, ppkg, conflicts)
}
}

for _, pkg := range dc.Repo {
checkReverseConflict(pkg.Name(), pkg.Name(), conflicts)
pkg.Provides().ForEach(func(provide alpm.Depend) error {
checkReverseConflict(pkg.Name(), provide.String(), conflicts)
return nil
})
}

return conflicts, nil
}

func checkForAllConflicts(dc *depCatagories) error {
var err error
var conflicts map[string]stringSet
var innerConflicts map[string]stringSet
var wg sync.WaitGroup
wg.Add(2)

fmt.Println(bold(cyan("::")+ " Checking for conflicts..."))
go func() {
conflicts, err = checkForConflicts(dc)
wg.Done()
}()

fmt.Println(bold(cyan("::")+ " Checking for inner conflicts..."))
go func() {
innerConflicts = checkForInnerConflicts(dc)
wg.Done()
}()

wg.Wait()
if len(innerConflicts) != 0 {
fmt.Println(
red("\nInner conflicts found:"))
for name, pkgs := range innerConflicts {
str := "\t" + name + ":"
for pkg := range pkgs {
str += " " + magenta(pkg)
}

fmt.Println(str)
}

return fmt.Errorf("Aborting")
}

if len(conflicts) != 0 {
fmt.Println(
red("\nPackage conflicts found:"))
for name, pkgs := range conflicts {
str := "\tInstalling " + magenta(name) + " will remove:"
for pkg := range pkgs {
str += " " + magenta(pkg)
}

fmt.Println(str)
}

fmt.Println()
}

return nil
}
Loading

0 comments on commit 4a8ec94

Please sign in to comment.