mirror of https://github.com/databricks/cli.git
101 lines
2.5 KiB
Go
101 lines
2.5 KiB
Go
package sync
|
|
|
|
import (
|
|
"path"
|
|
)
|
|
|
|
type diff struct {
|
|
delete []string
|
|
rmdir []string
|
|
mkdir []string
|
|
put []string
|
|
}
|
|
|
|
func (d diff) IsEmpty() bool {
|
|
return len(d.put) == 0 && len(d.delete) == 0
|
|
}
|
|
|
|
// groupedMkdir returns a slice of slices of paths to create.
|
|
// Because the underlying mkdir calls create intermediate directories,
|
|
// we can group them together to reduce the total number of calls.
|
|
// This returns a slice of a slice for parity with [groupedRmdir].
|
|
func (d diff) groupedMkdir() [][]string {
|
|
// Compute the set of prefixes of all paths to create.
|
|
prefixes := make(map[string]bool)
|
|
for _, name := range d.mkdir {
|
|
dir := path.Dir(name)
|
|
for dir != "." && dir != "/" {
|
|
prefixes[dir] = true
|
|
dir = path.Dir(dir)
|
|
}
|
|
}
|
|
|
|
var out []string
|
|
|
|
// Collect all paths that are not a prefix of another path.
|
|
for _, name := range d.mkdir {
|
|
if !prefixes[name] {
|
|
out = append(out, name)
|
|
}
|
|
}
|
|
|
|
return [][]string{out}
|
|
}
|
|
|
|
// groupedRmdir returns a slice of slices of paths to delete.
|
|
// The outer slice is ordered such that each inner slice can be
|
|
// deleted in parallel, as long as it is processed in order.
|
|
// The first entry will contain leaf directories, the second entry
|
|
// will contain intermediate directories, and so on.
|
|
func (d diff) groupedRmdir() [][]string {
|
|
// Compute the number of times each directory is a prefix of another directory.
|
|
prefixes := make(map[string]int)
|
|
for _, dir := range d.rmdir {
|
|
prefixes[dir] = 0
|
|
}
|
|
for _, dir := range d.rmdir {
|
|
dir = path.Dir(dir)
|
|
for dir != "." && dir != "/" {
|
|
// Increment the prefix count for this directory, only if it
|
|
// it one of the directories we are deleting.
|
|
if _, ok := prefixes[dir]; ok {
|
|
prefixes[dir]++
|
|
}
|
|
dir = path.Dir(dir)
|
|
}
|
|
}
|
|
|
|
var out [][]string
|
|
|
|
for len(prefixes) > 0 {
|
|
var toDelete []string
|
|
|
|
// Find directories which are not a prefix of another directory.
|
|
// These are the directories we can delete.
|
|
for dir, count := range prefixes {
|
|
if count == 0 {
|
|
toDelete = append(toDelete, dir)
|
|
delete(prefixes, dir)
|
|
}
|
|
}
|
|
|
|
// Remove these directories from the prefixes map.
|
|
for _, dir := range toDelete {
|
|
dir = path.Dir(dir)
|
|
for dir != "." && dir != "/" {
|
|
// Decrement the prefix count for this directory, only if it
|
|
// it one of the directories we are deleting.
|
|
if _, ok := prefixes[dir]; ok {
|
|
prefixes[dir]--
|
|
}
|
|
dir = path.Dir(dir)
|
|
}
|
|
}
|
|
|
|
// Add these directories to the output.
|
|
out = append(out, toDelete)
|
|
}
|
|
|
|
return out
|
|
}
|