# Path: meld/iohelpers.py
# def find_shared_parent_path(
#     paths: Sequence[Optional[Gio.File]],
# ) -> Optional[Gio.File]:
# 
#     if not paths or not paths[0] or any(path is None for path in paths):
#         return None
# 
#     current_parent = paths[0].get_parent()
#     if len(paths) == 1:
#         return current_parent
# 
#     while current_parent:
#         is_valid_parent = all(
#             current_parent.get_relative_path(path)
#             for path in paths
#         )
#         if is_valid_parent:
#             break
# 
#         current_parent = current_parent.get_parent()
# 
#     # Either we've broken out of the loop early, in which case we have
#     # a valid common parent path, or we've fallen through, in which
#     # case the path return is None.
#     return current_parent
# 
# def format_parent_relative_path(parent: Gio.File, descendant: Gio.File) -> str:
#     """Format shortened child paths using a common parent
# 
#     This is a helper for shortening sets of paths using their common
#     parent as a guide for what is required to distinguish the paths
#     from one another. The helper operates on every path individually,
#     so that this work can be done in individual widgets using only the
#     path being displayed (`descendent` here) and the common parent
#     (`parent` here).
#     """
# 
#     # When thinking about the segmentation we do here, there are
#     # four path components that we care about:
#     #
#     #  * any path components above the non-common parent
#     #  * the earliest non-common parent
#     #  * any path components between the actual filename and the
#     #    earliest non-common parent
#     #  * the actual filename
#     #
#     # This is easiest to think about with an example of comparing
#     # two files in a parallel repository structure (or similar).
#     # Let's say that you have two copies of Meld at
#     # /home/foo/checkouts/meld and /home/foo/checkouts/meld-new,
#     # and you're comparing meld/filediff.py within those checkouts.
#     # The components we want would then be (left to right):
#     #
#     #  ---------------------------------------------
#     #  | /home/foo/checkouts | /home/foo/checkouts |
#     #  | meld                | meld-new            |
#     #  | meld                | meld                |
#     #  | filediff.py         | filediff.py         |
#     #  ---------------------------------------------
#     #
#     # Of all of these, the first (the first common parent) is the
#     # *only* one that's actually guaranteed to be the same. The
#     # second will *always* be different (or won't exist if e.g.,
#     # you're comparing files in the same folder or similar). The
#     # third component can be basically anything. The fourth
#     # components will often be the same but that's not guaranteed.
# 
#     base_path_str = None
#     elided_path = None
# 
#     descendant_parent = descendant.get_parent()
#     if descendant_parent is None:
#         raise ValueError(f'Path {descendant.get_path()} has no parent')
# 
#     relative_path_str = parent.get_relative_path(descendant_parent)
# 
#     if relative_path_str:
#         relative_path = pathlib.Path(relative_path_str)
# 
#         base_path_str = relative_path.parts[0]
#         if len(relative_path.parts) == 1:
#             # No directory components, so we have no elided path
#             # segment
#             elided_path = None
#         else:
#             base_path_gfile = parent.get_child(base_path_str)
#             elided_path = base_path_gfile.get_relative_path(
#                 descendant_parent)
# 
#     show_parent = not parent.has_parent()
#     # It looks odd to have a single component, so if we don't have a
#     # base path, we'll use the direct parent. In this case the parent
#     # won't provide any disambiguation... it's just for appearances.
#     if not show_parent and not base_path_str:
#         base_path_str = parent.get_basename()
# 
#     label_segments = [
#         '…' if not show_parent else None,
#         base_path_str,
#         '…' if elided_path else None,
#         descendant.get_basename(),
#     ]
#     label_text = format_home_relative_path(parent) if show_parent else ""
#     label_text += GLib.build_filenamev([s for s in label_segments if s])
# 
#     return label_text


import pytest
from gi.repository import Gio
from meld.iohelpers import find_shared_parent_path, format_parent_relative_path
            '/home/hey/',
            '/home/hey/project/foo.txt',
            '…/project/foo.txt',
        ),
        # Child is a more-than-2-depth child of parent
        (
            '/home/hey/',
            '/home/hey/project/hey/hey/foo.txt',
            '…/project/…/foo.txt',
        ),
    ],
)
def test_format_parent_relative_path(
    parent: str,
    child: str,
    expected_label: str,
):
    parent_gfile = Gio.File.new_for_path(parent)
    child_gfile = Gio.File.new_for_path(child)

    label = format_parent_relative_path(parent_gfile, child_gfile)

    assert label == expected_label


def test_format_parent_relative_path_no_parent():
    parent_gfile = Gio.File.new_for_path('/')
    child_gfile = Gio.File.new_for_path('/')

    with pytest.raises(ValueError, match='has no parent'):

# Path: meld/iohelpers.py
# def find_shared_parent_path(
#     paths: Sequence[Optional[Gio.File]],
# ) -> Optional[Gio.File]:
# 
#     if not paths or not paths[0] or any(path is None for path in paths):
#         return None
# 
#     current_parent = paths[0].get_parent()
#     if len(paths) == 1:
#         return current_parent
# 
#     while current_parent:
#         is_valid_parent = all(
#             current_parent.get_relative_path(path)
#             for path in paths
#         )
#         if is_valid_parent:
#             break
# 
#         current_parent = current_parent.get_parent()
# 
#     # Either we've broken out of the loop early, in which case we have
#     # a valid common parent path, or we've fallen through, in which
#     # case the path return is None.
#     return current_parent
# 
# def format_parent_relative_path(parent: Gio.File, descendant: Gio.File) -> str:
#     """Format shortened child paths using a common parent
# 
#     This is a helper for shortening sets of paths using their common
#     parent as a guide for what is required to distinguish the paths
#     from one another. The helper operates on every path individually,
#     so that this work can be done in individual widgets using only the
#     path being displayed (`descendent` here) and the common parent
#     (`parent` here).
#     """
# 
#     # When thinking about the segmentation we do here, there are
#     # four path components that we care about:
#     #
#     #  * any path components above the non-common parent
#     #  * the earliest non-common parent
#     #  * any path components between the actual filename and the
#     #    earliest non-common parent
#     #  * the actual filename
#     #
#     # This is easiest to think about with an example of comparing
#     # two files in a parallel repository structure (or similar).
#     # Let's say that you have two copies of Meld at
#     # /home/foo/checkouts/meld and /home/foo/checkouts/meld-new,
#     # and you're comparing meld/filediff.py within those checkouts.
#     # The components we want would then be (left to right):
#     #
#     #  ---------------------------------------------
#     #  | /home/foo/checkouts | /home/foo/checkouts |
#     #  | meld                | meld-new            |
#     #  | meld                | meld                |
#     #  | filediff.py         | filediff.py         |
#     #  ---------------------------------------------
#     #
#     # Of all of these, the first (the first common parent) is the
#     # *only* one that's actually guaranteed to be the same. The
#     # second will *always* be different (or won't exist if e.g.,
#     # you're comparing files in the same folder or similar). The
#     # third component can be basically anything. The fourth
#     # components will often be the same but that's not guaranteed.
# 
#     base_path_str = None
#     elided_path = None
# 
#     descendant_parent = descendant.get_parent()
#     if descendant_parent is None:
#         raise ValueError(f'Path {descendant.get_path()} has no parent')
# 
#     relative_path_str = parent.get_relative_path(descendant_parent)
# 
#     if relative_path_str:
#         relative_path = pathlib.Path(relative_path_str)
# 
#         base_path_str = relative_path.parts[0]
#         if len(relative_path.parts) == 1:
#             # No directory components, so we have no elided path
#             # segment
#             elided_path = None
#         else:
#             base_path_gfile = parent.get_child(base_path_str)
#             elided_path = base_path_gfile.get_relative_path(
#                 descendant_parent)
# 
#     show_parent = not parent.has_parent()
#     # It looks odd to have a single component, so if we don't have a
#     # base path, we'll use the direct parent. In this case the parent
#     # won't provide any disambiguation... it's just for appearances.
#     if not show_parent and not base_path_str:
#         base_path_str = parent.get_basename()
# 
#     label_segments = [
#         '…' if not show_parent else None,
#         base_path_str,
#         '…' if elided_path else None,
#         descendant.get_basename(),
#     ]
#     label_text = format_home_relative_path(parent) if show_parent else ""
#     label_text += GLib.build_filenamev([s for s in label_segments if s])
# 
#     return label_text


# Path: test/test_iohelpers.py
import pytest
from gi.repository import Gio
from meld.iohelpers import find_shared_parent_path, format_parent_relative_path

            '/home/hey/',
            '/home/hey/project/foo.txt',
            '…/project/foo.txt',
        ),
        # Child is a more-than-2-depth child of parent
        (
            '/home/hey/',
            '/home/hey/project/hey/hey/foo.txt',
            '…/project/…/foo.txt',
        ),
    ],
)
def test_format_parent_relative_path(
    parent: str,
    child: str,
    expected_label: str,
):
    parent_gfile = Gio.File.new_for_path(parent)
    child_gfile = Gio.File.new_for_path(child)

    label = format_parent_relative_path(parent_gfile, child_gfile)

    assert label == expected_label


def test_format_parent_relative_path_no_parent():
    parent_gfile = Gio.File.new_for_path('/')
    child_gfile = Gio.File.new_for_path('/')

    with pytest.raises(ValueError, match='has no parent'):

        format_parent_relative_path(parent_gfile, child_gfile)