Link Cartfile dependencies in the source viewer

What does this MR do and why?

A Cartfile is highlighted by the backend today. cartfile is listed in LEGACY_FILE_TYPES, so the file is served through the legacy viewer, where the server-side DependencyLinker runs. The origins are linked on master; nothing is broken.

This MR moves the file type over to the frontend source viewer without losing those links. It adds a Highlight.js dependency linker for cartfile, registers it in link_dependencies.js alongside the existing gemfile, podspec_json, composer_json and go_sum linkers, and removes cartfile from LEGACY_FILE_TYPES, the same way !255262 (merged) does for podfile.

It handles the two origin shapes Carthage supports:

  • github "Owner/Repo" links the Owner/Repo text to https://github.com/Owner/Repo.
  • git "https://...", binary "https://..." and the URL form of github "https://..." (GitHub Enterprise) link the URL to itself.

Both patterns follow what the Ruby linker accepts rather than the shape of a tidy file. MethodLinker#method_call_regex allows leading whitespace and any run of whitespace between the keyword and the quoted value, so an indented entry and a column-aligned one are matched here too, and the original spacing is preserved in the output.

The URL match runs to the closing quote rather than stopping at an ampersand, so a query string stays whole. The URL is unescaped before the link is built, because createLink escapes what it is given.

Both patterns are anchored to the start of a line and require one of the three keywords, so a commented-out line such as # github "Owner/Repo" or an unrecognised keyword is left untouched. Version constraints after the origin (>= 2.3.1, ~> 1.0) are not part of the match.

A Cartfile is highlighted as plaintext, so the whole line arrives as a single <span class="">...</span> with the quotes already escaped as &quot; and ampersands as &amp;; the regexes are written against that exact shape.

References

  • Resolves #367651
  • Sibling changes for the other Cocoa manifests: !255262 (merged) (Podfile) and !255264 (merged) (podspec)
  • Other file types moving to the new viewer: !255267 (merged) (requirements.txt) and !255271 (merged) (go.mod)
  • Reuses createLink from app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util.js, so links carry the same target and rel attributes as every other linker. unescape comes from lodash-es, as it does in package_json_linker.js.
  • Each of those merge requests removes an entry from LEGACY_FILE_TYPES, and removing enough entries brings the array under the line limit so Prettier collapses it. Expect a one-line conflict on each merge after the first.

Differences

Before: A Cartfile was rendered by the legacy backend viewer, with links produced by Gitlab::DependencyLinker::CartfileLinker.

After: A Cartfile is rendered by the frontend source viewer, with the same links produced client side. ReactiveCocoa/ReactiveCocoa links to https://github.com/ReactiveCocoa/ReactiveCocoa, opening in a new tab. The git, binary and URL-style github origins are clickable links to their URL, query string included. Indented and column-aligned entries are linked and keep their spacing. Commented-out lines, unknown keywords and version constraints are unchanged.

How to set up and validate locally

  1. In a project, add a file named Cartfile with the following content:
github "ReactiveCocoa/ReactiveCocoa" >= 2.3.1
github "Mantle/Mantle" ~> 1.0
  github "Indented/Repo"
github   "Aligned/Repo"
github "https://enterprise.local/project/repo"
git "https://enterprise.local/desktop/git-error-translations2.git"
binary "https://my.domain.com/release/MyFramework.json" ~> 2.3
binary "https://my.domain.com/release/MyFramework.json?arch=arm64&variant=debug"
# github "Commented/Out"
local "Unknown/Keyword"
  1. Open the file in the repository view.
  2. ReactiveCocoa/ReactiveCocoa, Mantle/Mantle, Indented/Repo and Aligned/Repo should link to their GitHub repositories, with the indentation and the extra spaces intact. All four URLs should link to themselves, and the last one should include &variant=debug in both the link text and its target rather than stopping at ?arch=arm64. The commented line and the unknown keyword should not be links.

Specs:

yarn jest spec/frontend/vue_shared/components/source_viewer/plugins/utils/cartfile_linker_spec.js spec/frontend/vue_shared/components/source_viewer/plugins/link_dependencies_spec.js spec/frontend/repository/components/blob_content_viewer_spec.js

cartfile_linker_spec.js covers GitHub shorthand origins with version constraints, all three URL-origin keywords, indented and column-aligned origins, a URL with an escaped query string, and that comments and unknown keywords are untouched. link_dependencies_spec.js asserts the cartfile file type is routed to the new linker. blob_content_viewer_spec.js covers the LEGACY_FILE_TYPES change.

MR acceptance checklist

  • The change is limited to the frontend source viewer; no backend, database, or API changes.
  • cartfile is removed from LEGACY_FILE_TYPES, so the file is actually served by the frontend viewer and the new linker is reached.
  • Links are built with the shared createLink helper, so they carry target="_blank" and rel="nofollow noreferrer noopener" like every other dependency linker.
  • Only github, git and binary origins are linked; comments, unknown keywords and version constraints are not rewritten.
  • Leading and intra-line whitespace is matched the way MethodLinker#method_call_regex matches it, and preserved in the output.
  • A URL keeps its full query string, and is unescaped before the link is built so an escaped separator does not come back double-escaped.
  • Unit specs added for the linker and for its registration in link_dependencies.js; the source viewer plugin suite and the blob content viewer suite pass locally.
  • Changelog: changed trailer is on the commit, since this moves an existing behaviour to the frontend viewer rather than adding a new one.
  • No documentation change required; the links a reader sees are unchanged.
  • No feature flag needed; the change is small and isolated to one file type.
Edited by Jeston Singh

Merge request reports

Loading
Loading