Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hex: Handle additional dynamic version reading approaches #4442

Merged
merged 4 commits into from
Nov 30, 2021

Conversation

landongrindheim
Copy link
Member

@landongrindheim landongrindheim commented Nov 23, 2021

I think #sanitized_content is meant to make a common Elixir pattern
safe for parsing (rather, to prevent code execution while we dependency
management is being performed). Unfortunately, there are no hints in
either Git commit history or in the pull requests that were opened
around Elixir package management.

The pattern that this is handling (at least in the fixtures in this
repo) is the case where there's a top-level file titled VERSION, which
is read in in the Mixfile's project metadata. We're handling a couple of
cases here:

String.trim(File.read("VERSION"))  # String.trim("0.0.1")
String.trim(File.read!("VERSION")) # String.trim({:ok, "0.0.1"})

A lot of Elixir code relies on piping output from one function to
another, which can cause the above pattern to read as:

"VERSION" |> File.read() |> String.trim()
"VERSION"
|> File.read()
|> String.trim()

We've not been handling these pipelines properly, which has led to errors like:

(ArgumentError) cannot pipe "VERSION" into "0.0.1", can only pipe (snip)

This pull request is meant to enable us to handle both the nested and piped approaches.

@landongrindheim landongrindheim force-pushed the handle-more-mix-file-version-variations branch 2 times, most recently from fa48db2 to c1b6fe4 Compare November 23, 2021 18:16
@landongrindheim landongrindheim changed the title Expand regexp to capture Hex: Handle additional dynamic version reading approaches Nov 23, 2021
I _think_ `#sanitized_content` is meant to make a common Elixir pattern
safe for parsing (rather, to prevent code execution while we dependency
management is being performed). Unfortunately, there are no hints in
either Git commit history or in the pull requests that were opened
around Elixir package management.

The pattern that this is handling (at least in the fixtures in this
repo) is the case where there's a top-level file titled VERSION, which
is read in in the Mixfile's project metadata. We're handling a couple of
cases here:

```elixir
String.trim(File.read("VERSION"))  # String.trim("0.0.1")
String.trim(File.read!("VERSION")) # String.trim({:ok, "0.0.1"})
```

A lot of Elixir code relies on piping output from one function to
another, which can cause the above pattern to read as:

```elixir
"VERSION" |> File.read() |> String.trim()
"VERSION"
|> File.read()
|> String.trim()
```

We're not handling these properly, which has led to errors like:
```plaintext
(ArgumentError) cannot pipe "VERSION" into "0.0.1", can only pipe (snip)
```

This commit is meant to capture only the former pattern (nested calls),
so that we can properly handle the latter in upcoming commits.
Until this commit, we've only handled the following syntax:
```elixir
String.trim(File.read("VERSION"))
String.trim(File.read!("VERSION"))
```

However, we've encountered users using the following idioms:
```elixir
"VERSION" |> File.read() |> String.trim()
"VERSION" |> File.read!() |> String.trim()
```
and:
```elixir
"VERSION"
|> File.read()
|> String.trim()

"VERSION"
|> File.read!()
|> String.trim()
```

This commit allows us to handle the latter cases, where the pipe
operator is used.
@landongrindheim landongrindheim force-pushed the handle-more-mix-file-version-variations branch from c72588d to fb042c5 Compare November 29, 2021 15:28
@landongrindheim landongrindheim marked this pull request as ready for review November 29, 2021 15:30
@landongrindheim landongrindheim requested a review from a team as a code owner November 29, 2021 15:30
@@ -11,16 +11,40 @@ def initialize(mixfile_content:)
@mixfile_content = mixfile_content
end

FILE_READ = /File.read\(.*?\)/.freeze
FILE_READ_BANG = /File.read!\(.*?\)/.freeze
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question (non-blocking): it looks like we're trying to match File.read. Do we also need to match IO.read and/or Pathname#read?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't. These are matching Elixir functions what share a name with Ruby methods. They do have a very familiar feel as the language's creator came out of the Ruby community 😄

@landongrindheim landongrindheim merged commit 2204d22 into main Nov 30, 2021
@landongrindheim landongrindheim deleted the handle-more-mix-file-version-variations branch November 30, 2021 13:49
@landongrindheim landongrindheim mentioned this pull request Nov 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants