/
utils.go
66 lines (61 loc) · 1.59 KB
/
utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package nix
import (
"path/filepath"
"sort"
"strings"
)
type Node struct {
inTar bool
children map[string]*Node
}
// addPathInGraph adds a file and all missing file parents file
// in the graph.
// It also marks nodes that are in the tar.
func addPathInGraph(root *Node, path string) {
var current *Node
var exist bool
components := strings.Split(filepath.Clean(path), "/")
if components[0] == "" {
components[0] = "/"
}
node := root
for _, component := range components {
current, exist = node.children[component]
if !exist {
current = &Node{
children: make(map[string]*Node),
}
node.children[component] = current
}
node = current
}
// This node exists in the tar
current.inTar = true
}
func collectPathsNotInTar(root *Node, base string) []string {
collected := []string{}
for name, child := range root.children {
path := filepath.Join(base, name)
if !child.inTar {
collected = append(collected, path)
}
collected = append(collected, collectPathsNotInTar(child, path)...)
}
return collected
}
// pathsNotInTar returns all paths that have not been explicitly
// created. If the paths list only contains "/nix/store/hash", this
// function returns ["/nix", "/nix/store"]. Note we don't want to
// just create "/nix" and "/nix/store" directories because we want to be
// "nix" specific (think of guix for instance).
func pathsNotInTar(paths []string) []string {
root := Node{
children: make(map[string]*Node),
}
for _, path := range paths {
addPathInGraph(&root, path)
}
collected := collectPathsNotInTar(&root, "")
sort.Strings(collected)
return collected
}