diff options
| author | Joel Klinghed <the_jk@spawned.biz> | 2024-11-09 17:47:54 +0100 |
|---|---|---|
| committer | Joel Klinghed <the_jk@spawned.biz> | 2024-11-09 17:47:54 +0100 |
| commit | 3f6024d20ccca7afcd4b0612fad6271c38540bf0 (patch) | |
| tree | d5ee2a45b02aed82334a3ce22a4c895a52be66a5 /libs/io/src/main/java/org/the_jk/cleversync | |
| parent | b5d99dd596a67e185414d65507b23541e016daed (diff) | |
single merge: Avoid loops
If a symlink points to a directory already visited in parent path,
don't visit. Otherwise you will get a stack overflow.
Diffstat (limited to 'libs/io/src/main/java/org/the_jk/cleversync')
| -rw-r--r-- | libs/io/src/main/java/org/the_jk/cleversync/io/SingleMerge.kt | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/libs/io/src/main/java/org/the_jk/cleversync/io/SingleMerge.kt b/libs/io/src/main/java/org/the_jk/cleversync/io/SingleMerge.kt index 9869993..3fd73b4 100644 --- a/libs/io/src/main/java/org/the_jk/cleversync/io/SingleMerge.kt +++ b/libs/io/src/main/java/org/the_jk/cleversync/io/SingleMerge.kt @@ -5,7 +5,7 @@ import java.time.Instant object SingleMerge { fun calculate(target: Directory, source: Directory, options: Options = Options()): List<Action> { - return visit(target, source.list(), Context(source, options), "/") + return visit(target, source.list(), Context(source, options), "/", setOf(source)) } private fun visit( @@ -13,6 +13,7 @@ object SingleMerge { source: Directory.Content, context: Context, path: String, + visited: Set<Directory>, ) : List<Action> { val targetContent = target?.list() val targetNames = if (targetContent != null && context.options.deleteFilesOnlyInTarget) { @@ -32,6 +33,7 @@ object SingleMerge { this@buildList, context, path, + visited union setOf(sourceDir), ) } source.files.forEach { sourceFile -> @@ -40,7 +42,7 @@ object SingleMerge { } source.links.forEach { sourceLink -> targetNames?.remove(sourceLink.name) - visitLink(targetContent, sourceLink, this@buildList, context, path) + visitLink(targetContent, sourceLink, this@buildList, context, path, visited) } targetNames?.forEach { (name, type) -> when (type) { @@ -60,13 +62,14 @@ object SingleMerge { actions: MutableList<Action>, context: Context, path: String, + visited: Set<Directory>, ) { val sourcePath = PathUtils.join(path, sourceName) if (targetContent == null) { actions.add( Action.ChangeDir( sourceName, - visit(null, sourceContent, context, sourcePath), + visit(null, sourceContent, context, sourcePath, visited), create = true, ), ) @@ -76,7 +79,7 @@ object SingleMerge { actions.add( Action.ChangeDir( sourceName, - visit(targetDir, sourceContent, context, sourcePath), + visit(targetDir, sourceContent, context, sourcePath, visited), ), ) } else { @@ -88,7 +91,7 @@ object SingleMerge { actions.add( Action.ChangeDir( sourceName, - visit(null, sourceContent, context, sourcePath), + visit(null, sourceContent, context, sourcePath, visited), create = true, ), ) @@ -132,6 +135,7 @@ object SingleMerge { actions: MutableList<Action>, context: Context, path: String, + visited: Set<Directory>, ) { val linkTarget = sourceLink.resolve() if (!context.options.resolveLinks && insideRoot(context.root, path, linkTarget.path)) { @@ -162,14 +166,17 @@ object SingleMerge { } else { when (linkTarget) { is Link.DirectoryTarget -> { - visitDir( - targetContent, - sourceLink.name, - linkTarget.directory.list(), - actions, - context, - path, - ) + if (!visited.contains(linkTarget.directory)) { + visitDir( + targetContent, + sourceLink.name, + linkTarget.directory.list(), + actions, + context, + path, + visited union setOf(linkTarget.directory), + ) + } } is Link.FileTarget -> { |
