##// END OF EJS Templates
dirstate-v2: fix infinite loop in pure packer...
Raphaël Gomès -
r49614:46d12f77 stable
parent child Browse files
Show More
@@ -316,17 +316,17 b' def pack_dirstate(map, copy_map, now):'
316 # Determine if the next entry is in the same sub-tree, if so don't
316 # Determine if the next entry is in the same sub-tree, if so don't
317 # pack yet
317 # pack yet
318 next_path = sorted_map[index][0]
318 next_path = sorted_map[index][0]
319 should_pack = not get_folder(next_path).startswith(current_folder)
319 should_pack = not is_ancestor(next_path, current_folder)
320 if should_pack:
320 if should_pack:
321 pack_directory_children(current_node, copy_map, data, stack)
321 pack_directory_children(current_node, copy_map, data, stack)
322 while stack and current_node.path != b"":
322 while stack and current_node.path != b"":
323 # Go up the tree and write until we reach the folder of the next
323 # Go up the tree and write until we reach the folder of the next
324 # entry (if any, otherwise the root)
324 # entry (if any, otherwise the root)
325 parent = current_node.parent
325 parent = current_node.parent
326 in_parent_folder_of_next_entry = next_path is not None and (
326 in_ancestor_of_next_path = next_path is not None and (
327 get_folder(next_path).startswith(get_folder(stack[-1].path))
327 is_ancestor(next_path, get_folder(stack[-1].path))
328 )
328 )
329 if parent is None or in_parent_folder_of_next_entry:
329 if parent is None or in_ancestor_of_next_path:
330 break
330 break
331 pack_directory_children(parent, copy_map, data, stack)
331 pack_directory_children(parent, copy_map, data, stack)
332 current_node = parent
332 current_node = parent
@@ -357,13 +357,34 b' def get_folder(path):'
357 return path.rsplit(b'/', 1)[0] if b'/' in path else b''
357 return path.rsplit(b'/', 1)[0] if b'/' in path else b''
358
358
359
359
360 def is_ancestor(path, maybe_ancestor):
361 """Returns whether `maybe_ancestor` is an ancestor of `path`.
362
363 >>> is_ancestor(b"a", b"")
364 True
365 >>> is_ancestor(b"a/b/c", b"a/b/c")
366 False
367 >>> is_ancestor(b"hgext3rd/__init__.py", b"hgext")
368 False
369 >>> is_ancestor(b"hgext3rd/__init__.py", b"hgext3rd")
370 True
371 """
372 if maybe_ancestor == b"":
373 return True
374 if path <= maybe_ancestor:
375 return False
376 path_components = path.split(b"/")
377 ancestor_components = maybe_ancestor.split(b"/")
378 return all(c == o for c, o in zip(path_components, ancestor_components))
379
380
360 def move_to_correct_node_in_tree(target_folder, current_node, stack):
381 def move_to_correct_node_in_tree(target_folder, current_node, stack):
361 """
382 """
362 Move inside the dirstate node tree to the node corresponding to
383 Move inside the dirstate node tree to the node corresponding to
363 `target_folder`, creating the missing nodes along the way if needed.
384 `target_folder`, creating the missing nodes along the way if needed.
364 """
385 """
365 while target_folder != current_node.path:
386 while target_folder != current_node.path:
366 if target_folder.startswith(current_node.path):
387 if is_ancestor(target_folder, current_node.path):
367 # We need to go down a folder
388 # We need to go down a folder
368 prefix = target_folder[len(current_node.path) :].lstrip(b'/')
389 prefix = target_folder[len(current_node.path) :].lstrip(b'/')
369 subfolder_name = prefix.split(b'/', 1)[0]
390 subfolder_name = prefix.split(b'/', 1)[0]
@@ -103,3 +103,21 b' coherent (issue4353)'
103 1
103 1
104 $ hg status
104 $ hg status
105 ? a
105 ? a
106
107 #if dirstate-v2
108 Check that folders that are prefixes of others do not throw the packer into an
109 infinite loop.
110
111 $ cd ..
112 $ hg init infinite-loop
113 $ cd infinite-loop
114 $ mkdir hgext3rd hgext
115 $ touch hgext3rd/__init__.py hgext/zeroconf.py
116 $ hg commit -Aqm0
117
118 $ hg st -c
119 C hgext/zeroconf.py
120 C hgext3rd/__init__.py
121
122 $ cd ..
123 #endif
@@ -132,6 +132,7 b' expected_mods_tested = set('
132 ('mercurial.cmdutil', '{}'),
132 ('mercurial.cmdutil', '{}'),
133 ('mercurial.color', '{}'),
133 ('mercurial.color', '{}'),
134 ('mercurial.dagparser', "{'optionflags': 4}"),
134 ('mercurial.dagparser', "{'optionflags': 4}"),
135 ('mercurial.dirstateutils.v2', '{}'),
135 ('mercurial.encoding', '{}'),
136 ('mercurial.encoding', '{}'),
136 ('mercurial.fancyopts', '{}'),
137 ('mercurial.fancyopts', '{}'),
137 ('mercurial.formatter', '{}'),
138 ('mercurial.formatter', '{}'),
General Comments 0
You need to be logged in to leave comments. Login now