1package deb
2
3import (
4	"fmt"
5	"strings"
6
7	"github.com/awalterschulze/gographviz"
8)
9
10// BuildGraph generates graph contents from aptly object database
11func BuildGraph(collectionFactory *CollectionFactory, layout string) (gographviz.Interface, error) {
12	var err error
13
14	graph := gographviz.NewEscape()
15	graph.SetDir(true)
16	graph.SetName("aptly")
17
18	var labelStart string
19	var labelEnd string
20
21	switch layout {
22	case "vertical":
23		graph.AddAttr("aptly", "rankdir", "LR")
24		labelStart = ""
25		labelEnd = ""
26	case "horizontal":
27		fallthrough
28	default:
29		labelStart = "{"
30		labelEnd = "}"
31	}
32
33	existingNodes := map[string]bool{}
34
35	err = collectionFactory.RemoteRepoCollection().ForEach(func(repo *RemoteRepo) error {
36		e := collectionFactory.RemoteRepoCollection().LoadComplete(repo)
37		if e != nil {
38			return e
39		}
40
41		graph.AddNode("aptly", repo.UUID, map[string]string{
42			"shape":     "Mrecord",
43			"style":     "filled",
44			"fillcolor": "darkgoldenrod1",
45			"label": fmt.Sprintf("%sMirror %s|url: %s|dist: %s|comp: %s|arch: %s|pkgs: %d%s", labelStart, repo.Name, repo.ArchiveRoot,
46				repo.Distribution, strings.Join(repo.Components, ", "),
47				strings.Join(repo.Architectures, ", "), repo.NumPackages(), labelEnd),
48		})
49		existingNodes[repo.UUID] = true
50		return nil
51	})
52
53	if err != nil {
54		return nil, err
55	}
56
57	err = collectionFactory.LocalRepoCollection().ForEach(func(repo *LocalRepo) error {
58		e := collectionFactory.LocalRepoCollection().LoadComplete(repo)
59		if e != nil {
60			return e
61		}
62
63		graph.AddNode("aptly", repo.UUID, map[string]string{
64			"shape":     "Mrecord",
65			"style":     "filled",
66			"fillcolor": "mediumseagreen",
67			"label": fmt.Sprintf("%sRepo %s|comment: %s|pkgs: %d%s", labelStart,
68				repo.Name, repo.Comment, repo.NumPackages(), labelEnd),
69		})
70		existingNodes[repo.UUID] = true
71		return nil
72	})
73
74	if err != nil {
75		return nil, err
76	}
77
78	collectionFactory.SnapshotCollection().ForEach(func(snapshot *Snapshot) error {
79		existingNodes[snapshot.UUID] = true
80		return nil
81	})
82
83	err = collectionFactory.SnapshotCollection().ForEach(func(snapshot *Snapshot) error {
84		e := collectionFactory.SnapshotCollection().LoadComplete(snapshot)
85		if e != nil {
86			return e
87		}
88
89		description := snapshot.Description
90		if snapshot.SourceKind == SourceRemoteRepo {
91			description = "Snapshot from repo"
92		}
93
94		graph.AddNode("aptly", snapshot.UUID, map[string]string{
95			"shape":     "Mrecord",
96			"style":     "filled",
97			"fillcolor": "cadetblue1",
98			"label": fmt.Sprintf("%sSnapshot %s|%s|pkgs: %d%s", labelStart,
99				snapshot.Name, description, snapshot.NumPackages(), labelEnd),
100		})
101
102		if snapshot.SourceKind == SourceRemoteRepo || snapshot.SourceKind == SourceLocalRepo || snapshot.SourceKind == SourceSnapshot {
103			for _, uuid := range snapshot.SourceIDs {
104				_, exists := existingNodes[uuid]
105				if exists {
106					graph.AddEdge(uuid, snapshot.UUID, true, nil)
107				}
108			}
109		}
110		return nil
111	})
112
113	if err != nil {
114		return nil, err
115	}
116
117	collectionFactory.PublishedRepoCollection().ForEach(func(repo *PublishedRepo) error {
118		graph.AddNode("aptly", repo.UUID, map[string]string{
119			"shape":     "Mrecord",
120			"style":     "filled",
121			"fillcolor": "darkolivegreen1",
122			"label": fmt.Sprintf("%sPublished %s/%s|comp: %s|arch: %s%s", labelStart,
123				repo.Prefix, repo.Distribution, strings.Join(repo.Components(), " "),
124				strings.Join(repo.Architectures, ", "), labelEnd),
125		})
126
127		for _, uuid := range repo.Sources {
128			_, exists := existingNodes[uuid]
129			if exists {
130				graph.AddEdge(uuid, repo.UUID, true, nil)
131			}
132		}
133
134		return nil
135	})
136
137	return graph, nil
138}
139