github.com/mutagen-io/mutagen@v0.18.0-rc1/pkg/synchronization/safety.go (about) 1 package synchronization 2 3 import ( 4 "github.com/mutagen-io/mutagen/pkg/synchronization/core" 5 ) 6 7 // oneEndpointEmptiedRoot determines whether or not one endpoint (but not both) 8 // transitioned from a directory root with a non-trivial amount of content to a 9 // directory root without any content. 10 func oneEndpointEmptiedRoot(ancestor, alpha, beta *core.Entry) bool { 11 // Check that all three entries are directories. If not, then this check 12 // doesn't apply. 13 if ancestor == nil || ancestor.Kind != core.EntryKind_Directory { 14 return false 15 } else if alpha == nil || alpha.Kind != core.EntryKind_Directory { 16 return false 17 } else if beta == nil || beta.Kind != core.EntryKind_Directory { 18 return false 19 } 20 21 // Check whether or not the ancestor has a non-trivial amount of content. 22 // We define a non-trivial amount of content as two or more entries that are 23 // immediate children of the synchronization root. If that's not the case, 24 // then this check doesn't apply. 25 if len(ancestor.Contents) < 2 { 26 return false 27 } 28 29 // Check if alpha deleted all content within the root. 30 alphaEmptied := len(alpha.Contents) == 0 31 32 // Check if beta deleted all content within the root. 33 betaEmptied := len(beta.Contents) == 0 34 35 // Determine whether one (and only one) endpoint emptied root content. 36 return (alphaEmptied || betaEmptied) && !(alphaEmptied && betaEmptied) 37 } 38 39 // containsRootDeletion determines whether or not any of the specified changes 40 // is a root deletion change. 41 func containsRootDeletion(changes []*core.Change) bool { 42 // Look for root deletions. 43 for _, change := range changes { 44 if change.IsRootDeletion() { 45 return true 46 } 47 } 48 49 // Done. 50 return false 51 } 52 53 // containsRootTypeChange determines whether or not any of the specified changes 54 // is a root type change. 55 func containsRootTypeChange(changes []*core.Change) bool { 56 // Look for root type changes. 57 for _, change := range changes { 58 if change.IsRootTypeChange() { 59 return true 60 } 61 } 62 63 // Done. 64 return false 65 } 66 67 // filteredPathsAreSubset checks whether or not a slice of filtered paths is a 68 // subset of a larger slice of unfiltered paths. The paths in the filtered slice 69 // must share the same relative ordering as in the original slice. 70 func filteredPathsAreSubset(filteredPaths, originalPaths []string) bool { 71 // Loop over the list of filtered paths. 72 for _, filtered := range filteredPaths { 73 // Track whether or not we find a match for this path in what remains of 74 // the original path list. 75 matched := false 76 77 // Loop over what remains of the original paths. 78 for o, original := range originalPaths { 79 if original == filtered { 80 originalPaths = originalPaths[o+1:] 81 matched = true 82 break 83 } 84 } 85 86 // Check if we found a match. 87 if !matched { 88 return false 89 } 90 } 91 92 // Success. 93 return true 94 }