public static String getRelativeLinkTo(Item p) {
        Map<Object, String> ancestors = new HashMap<>();
        View view = null;

        StaplerRequest request = Stapler.getCurrentRequest();
        for (Ancestor a : request.getAncestors()) {
            ancestors.put(a.getObject(), a.getRelativePath());
            if (a.getObject() instanceof View)
                view = (View) a.getObject();
        }

        String path = ancestors.get(p);
        if (path != null) {
            return normalizeURI(path + '/');
        }

        Item i = p;
        String url = "";
        while (true) {
            ItemGroup ig = i.getParent();
            url = i.getShortUrl() + url;

            if (ig == Jenkins.get() || (view != null && ig == view.getOwner().getItemGroup())) {
                assert i instanceof TopLevelItem;
                if (view != null) {
                    // assume p and the current page belong to the same view, so return a relative path
                    // (even if they did not, View.getItem does not by default verify ownership)
                    return normalizeURI(ancestors.get(view) + '/' + url);
                } else {
                    // otherwise return a path from the root Hudson
                    return normalizeURI(request.getContextPath() + '/' + p.getUrl());
                }
            }

            path = ancestors.get(ig);
            if (path != null) {
                return normalizeURI(path + '/' + url);
            }

            assert ig instanceof Item; // if not, ig must have been the Hudson instance
            i = (Item) ig;
        }
    }
@Test
    public void testGetRelativeLinkTo_JobContainedInViewWithinItemGroup() {
        String contextPath = "/jenkins";
        StaplerRequest req = createMockRequest(contextPath);
        try (
                MockedStatic<Stapler> mocked = mockStatic(Stapler.class);
                MockedStatic<Jenkins> mockedJenkins = mockStatic(Jenkins.class)
        ) {
            Jenkins j = createMockJenkins(mockedJenkins);
            TopLevelItemAndItemGroup parent = mock(TopLevelItemAndItemGroup.class);
            when(parent.getShortUrl()).thenReturn("parent/");
            mocked.when(Stapler::getCurrentRequest).thenReturn(req);
            View view = mock(View.class);
            when(view.getOwner()).thenReturn(parent);
            when(parent.getItemGroup()).thenReturn(parent);
            createMockAncestors(req, createAncestor(j, "../../.."), createAncestor(parent, "../.."), createAncestor(view, "."));
            TopLevelItem i = createMockItem(parent, "job/i/", "parent/job/i/");
            when(view.getItems()).thenReturn(List.of(i));
            String result = Functions.getRelativeLinkTo(i);
            assertEquals("job/i/", result);
        }
    }