Skip to content

Commit bad391a

Browse files
committed
Support ignoring whitespace in diffs
1 parent 75ebaf2 commit bad391a

12 files changed

Lines changed: 276 additions & 102 deletions

File tree

assets/css/app.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,16 @@ table.package-list .button {
395395
font-weight: 600;
396396
}
397397

398+
.diff-stats-header .whitespace-toggle {
399+
color: #ddd;
400+
font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;
401+
font-size: 14px;
402+
}
403+
404+
.diff-stats-header .whitespace-toggle:hover {
405+
color: white;
406+
}
407+
398408
.loading-spinner {
399409
height: 60px;
400410
width: 100%;

lib/diff/hex/behaviour.ex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
defmodule Diff.Hex.Behaviour do
22
@callback diff(package :: String.t(), from :: String.t(), to :: String.t()) ::
33
{:ok, Enumerable.t()} | :error
4+
@callback diff(package :: String.t(), from :: String.t(), to :: String.t(), Keyword.t()) ::
5+
{:ok, Enumerable.t()} | :error
46
end

lib/diff/hex/hex.ex

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@ defmodule Diff.Hex do
102102
end
103103
end
104104

105-
def diff(package, from, to) do
105+
def diff(package, from, to), do: diff(package, from, to, [])
106+
107+
def diff(package, from, to, opts) do
106108
with {:ok, tarball_from} <- get_tarball(package, from),
107109
path_from = Diff.TmpDir.tmp_dir("package-#{package}-#{from}"),
108110
:ok <- unpack_tarball(tarball_from, path_from),
@@ -131,7 +133,7 @@ defmodule Diff.Hex do
131133

132134
with {_, true} <- {:file_size_old, file_size_check?(path_old)},
133135
{_, true} <- {:file_size_new, file_size_check?(path_new)},
134-
{_, {:ok, output}} <- {:git_diff, git_diff(path_old, path_new)} do
136+
{_, {:ok, output}} <- {:git_diff, git_diff(path_old, path_new, opts)} do
135137
if output do
136138
[{:ok, {output, path_from, path_to}}]
137139
else
@@ -157,24 +159,29 @@ defmodule Diff.Hex do
157159
end
158160
end
159161

160-
defp git_diff(path_from, path_to) do
161-
case System.cmd("git", [
162-
"-c",
163-
"core.quotepath=false",
164-
"-c",
165-
"diff.algorithm=histogram",
166-
"diff",
167-
"--no-index",
168-
"--no-color",
169-
path_from,
170-
path_to
171-
]) do
162+
defp git_diff(path_from, path_to, opts) do
163+
args =
164+
[
165+
"-c",
166+
"core.quotepath=false",
167+
"-c",
168+
"diff.algorithm=histogram",
169+
"diff",
170+
"--no-index",
171+
"--no-color"
172+
] ++ ignore_whitespace_args(opts) ++ [path_from, path_to]
173+
174+
case System.cmd("git", args) do
172175
{"", 0} -> {:ok, nil}
173176
{output, 1} -> {:ok, output}
174177
other -> {:error, other}
175178
end
176179
end
177180

181+
defp ignore_whitespace_args(opts) do
182+
if Keyword.get(opts, :ignore_whitespace, false), do: ["-w"], else: []
183+
end
184+
178185
defp file_size_check?(path) do
179186
File.stat!(path).size <= @max_file_size
180187
end

lib/diff/storage/gcs.ex

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ defmodule Diff.Storage.GCS do
55

66
@gs_xml_url "https://storage.googleapis.com"
77

8-
def get_diff(package, from_version, to_version, diff_id) do
9-
with {:ok, hash} <- combined_checksum(package, from_version, to_version),
8+
def get_diff(package, from_version, to_version, diff_id, opts \\ []) do
9+
with {:ok, hash} <- combined_checksum(package, from_version, to_version, opts),
1010
url = url(diff_key(package, from_version, to_version, hash, diff_id)),
1111
{:ok, 200, _headers, body} <-
1212
Diff.HTTP.retry("gs", fn -> Diff.HTTP.get(url, headers()) end) do
@@ -25,8 +25,8 @@ defmodule Diff.Storage.GCS do
2525
end
2626
end
2727

28-
def put_diff(package, from_version, to_version, diff_id, diff_data) do
29-
with {:ok, hash} <- combined_checksum(package, from_version, to_version),
28+
def put_diff(package, from_version, to_version, diff_id, diff_data, opts \\ []) do
29+
with {:ok, hash} <- combined_checksum(package, from_version, to_version, opts),
3030
url = url(diff_key(package, from_version, to_version, hash, diff_id)),
3131
{:ok, 200, _headers, _body} <-
3232
Diff.HTTP.retry("gs", fn -> Diff.HTTP.put(url, headers(), diff_data) end) do
@@ -42,10 +42,10 @@ defmodule Diff.Storage.GCS do
4242
end
4343
end
4444

45-
def list_diffs(package, from_version, to_version) do
46-
case get_metadata(package, from_version, to_version) do
45+
def list_diffs(package, from_version, to_version, opts \\ []) do
46+
case get_metadata(package, from_version, to_version, opts) do
4747
{:ok, %{total_diffs: total_diffs}} ->
48-
diff_ids = 0..(total_diffs - 1) |> Enum.map(&"diff-#{&1}")
48+
diff_ids = diff_ids(total_diffs)
4949
{:ok, diff_ids}
5050

5151
{:error, :not_found} ->
@@ -56,8 +56,8 @@ defmodule Diff.Storage.GCS do
5656
end
5757
end
5858

59-
def get_metadata(package, from_version, to_version) do
60-
with {:ok, hash} <- combined_checksum(package, from_version, to_version),
59+
def get_metadata(package, from_version, to_version, opts \\ []) do
60+
with {:ok, hash} <- combined_checksum(package, from_version, to_version, opts),
6161
url = url(metadata_key(package, from_version, to_version, hash)),
6262
{:ok, 200, _headers, body} <-
6363
Diff.HTTP.retry("gs", fn -> Diff.HTTP.get(url, headers()) end) do
@@ -79,8 +79,8 @@ defmodule Diff.Storage.GCS do
7979
end
8080
end
8181

82-
def put_metadata(package, from_version, to_version, metadata) do
83-
with {:ok, hash} <- combined_checksum(package, from_version, to_version),
82+
def put_metadata(package, from_version, to_version, metadata, opts \\ []) do
83+
with {:ok, hash} <- combined_checksum(package, from_version, to_version, opts),
8484
url = url(metadata_key(package, from_version, to_version, hash)),
8585
{:ok, json} <- Jason.encode(metadata),
8686
{:ok, 200, _headers, _body} <-
@@ -106,12 +106,18 @@ defmodule Diff.Storage.GCS do
106106
[{"authorization", "#{token.type} #{token.token}"}]
107107
end
108108

109-
def combined_checksum(package, from, to) do
109+
def combined_checksum(package, from, to, opts \\ []) do
110110
with {:ok, checksums} <- Diff.Hex.get_checksums(package, [from, to]) do
111-
{:ok, :erlang.phash2({Application.get_env(:diff, :cache_version), checksums})}
111+
{:ok, :erlang.phash2(Diff.Storage.cache_key(checksums, opts))}
112112
end
113113
end
114114

115+
defp diff_ids(0), do: []
116+
117+
defp diff_ids(total_diffs) do
118+
0..(total_diffs - 1) |> Enum.map(&"diff-#{&1}")
119+
end
120+
115121
defp diff_key(package, from_version, to_version, hash, diff_id) do
116122
"diffs/#{package}-#{from_version}-#{to_version}-#{hash}-#{diff_id}.json"
117123
end

lib/diff/storage/local.ex

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ defmodule Diff.Storage.Local do
33

44
@behaviour Diff.Storage
55

6-
def get_diff(package, from_version, to_version, diff_id) do
7-
case combined_checksum(package, from_version, to_version) do
6+
def get_diff(package, from_version, to_version, diff_id, opts \\ []) do
7+
case combined_checksum(package, from_version, to_version, opts) do
88
{:ok, hash} ->
99
filename = diff_key(package, from_version, to_version, hash, diff_id)
1010
path = Path.join([dir(), package, filename])
@@ -20,8 +20,8 @@ defmodule Diff.Storage.Local do
2020
end
2121
end
2222

23-
def put_diff(package, from_version, to_version, diff_id, diff_data) do
24-
with {:ok, hash} <- combined_checksum(package, from_version, to_version),
23+
def put_diff(package, from_version, to_version, diff_id, diff_data, opts \\ []) do
24+
with {:ok, hash} <- combined_checksum(package, from_version, to_version, opts),
2525
filename = diff_key(package, from_version, to_version, hash, diff_id),
2626
path = Path.join([dir(), package, filename]),
2727
:ok <- File.mkdir_p(Path.dirname(path)) do
@@ -34,10 +34,10 @@ defmodule Diff.Storage.Local do
3434
end
3535
end
3636

37-
def list_diffs(package, from_version, to_version) do
38-
case get_metadata(package, from_version, to_version) do
37+
def list_diffs(package, from_version, to_version, opts \\ []) do
38+
case get_metadata(package, from_version, to_version, opts) do
3939
{:ok, %{total_diffs: total_diffs}} ->
40-
diff_ids = 0..(total_diffs - 1) |> Enum.map(&"diff-#{&1}")
40+
diff_ids = diff_ids(total_diffs)
4141
{:ok, diff_ids}
4242

4343
{:error, :not_found} ->
@@ -48,8 +48,8 @@ defmodule Diff.Storage.Local do
4848
end
4949
end
5050

51-
def get_metadata(package, from_version, to_version) do
52-
case combined_checksum(package, from_version, to_version) do
51+
def get_metadata(package, from_version, to_version, opts \\ []) do
52+
case combined_checksum(package, from_version, to_version, opts) do
5353
{:ok, hash} ->
5454
filename = metadata_key(package, from_version, to_version, hash)
5555
path = Path.join([dir(), package, filename])
@@ -74,8 +74,8 @@ defmodule Diff.Storage.Local do
7474
end
7575
end
7676

77-
def put_metadata(package, from_version, to_version, metadata) do
78-
with {:ok, hash} <- combined_checksum(package, from_version, to_version),
77+
def put_metadata(package, from_version, to_version, metadata, opts \\ []) do
78+
with {:ok, hash} <- combined_checksum(package, from_version, to_version, opts),
7979
filename = metadata_key(package, from_version, to_version, hash),
8080
path = Path.join([dir(), package, filename]),
8181
:ok <- File.mkdir_p(Path.dirname(path)),
@@ -89,12 +89,18 @@ defmodule Diff.Storage.Local do
8989
end
9090
end
9191

92-
def combined_checksum(package, from, to) do
92+
def combined_checksum(package, from, to, opts \\ []) do
9393
with {:ok, checksums} <- Diff.Hex.get_checksums(package, [from, to]) do
94-
{:ok, :erlang.phash2({Application.get_env(:diff, :cache_version), checksums})}
94+
{:ok, :erlang.phash2(Diff.Storage.cache_key(checksums, opts))}
9595
end
9696
end
9797

98+
defp diff_ids(0), do: []
99+
100+
defp diff_ids(total_diffs) do
101+
0..(total_diffs - 1) |> Enum.map(&"diff-#{&1}")
102+
end
103+
98104
defp diff_key(package, from_version, to_version, hash, diff_id) do
99105
"diffs/#{package}-#{from_version}-#{to_version}-#{hash}-#{diff_id}.json"
100106
end

lib/diff/storage/storage.ex

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ defmodule Diff.Storage do
44
@type to_version :: String.t()
55
@type diff_id :: String.t()
66
@type diff_html :: String.t()
7+
@type diff_options :: Keyword.t()
78
@type diff_metadata :: %{
89
total_diffs: non_neg_integer(),
910
total_additions: non_neg_integer(),
@@ -14,34 +15,59 @@ defmodule Diff.Storage do
1415
# New diff-level storage callbacks
1516
@callback get_diff(package, from_version, to_version, diff_id) ::
1617
{:ok, diff_html} | {:error, term}
18+
@callback get_diff(package, from_version, to_version, diff_id, diff_options) ::
19+
{:ok, diff_html} | {:error, term}
1720
@callback put_diff(package, from_version, to_version, diff_id, diff_html) ::
1821
:ok | {:error, term}
22+
@callback put_diff(package, from_version, to_version, diff_id, diff_html, diff_options) ::
23+
:ok | {:error, term}
1924
@callback list_diffs(package, from_version, to_version) :: {:ok, [diff_id]} | {:error, term}
25+
@callback list_diffs(package, from_version, to_version, diff_options) ::
26+
{:ok, [diff_id]} | {:error, term}
2027

2128
# Metadata storage callbacks
2229
@callback get_metadata(package, from_version, to_version) ::
2330
{:ok, diff_metadata} | {:error, term}
31+
@callback get_metadata(package, from_version, to_version, diff_options) ::
32+
{:ok, diff_metadata} | {:error, term}
2433
@callback put_metadata(package, from_version, to_version, diff_metadata) :: :ok | {:error, term}
34+
@callback put_metadata(package, from_version, to_version, diff_metadata, diff_options) ::
35+
:ok | {:error, term}
2536

2637
defp impl(), do: Application.get_env(:diff, :storage_impl)
2738

28-
def get_diff(package, from_version, to_version, diff_id) do
29-
impl().get_diff(package, from_version, to_version, diff_id)
39+
def get_diff(package, from_version, to_version, diff_id, opts \\ []) do
40+
impl().get_diff(package, from_version, to_version, diff_id, opts)
3041
end
3142

32-
def put_diff(package, from_version, to_version, diff_id, diff_html) do
33-
impl().put_diff(package, from_version, to_version, diff_id, diff_html)
43+
def put_diff(package, from_version, to_version, diff_id, diff_html, opts \\ []) do
44+
impl().put_diff(package, from_version, to_version, diff_id, diff_html, opts)
3445
end
3546

36-
def list_diffs(package, from_version, to_version) do
37-
impl().list_diffs(package, from_version, to_version)
47+
def list_diffs(package, from_version, to_version, opts \\ []) do
48+
impl().list_diffs(package, from_version, to_version, opts)
3849
end
3950

40-
def get_metadata(package, from_version, to_version) do
41-
impl().get_metadata(package, from_version, to_version)
51+
def get_metadata(package, from_version, to_version, opts \\ []) do
52+
impl().get_metadata(package, from_version, to_version, opts)
53+
end
54+
55+
def put_metadata(package, from_version, to_version, metadata, opts \\ []) do
56+
impl().put_metadata(package, from_version, to_version, metadata, opts)
57+
end
58+
59+
def cache_key(checksums, opts) do
60+
base_key = {Application.get_env(:diff, :cache_version), checksums}
61+
62+
case cache_options(opts) do
63+
[] -> base_key
64+
options -> {base_key, options}
65+
end
4266
end
4367

44-
def put_metadata(package, from_version, to_version, metadata) do
45-
impl().put_metadata(package, from_version, to_version, metadata)
68+
defp cache_options(opts) do
69+
opts
70+
|> Keyword.take([:ignore_whitespace])
71+
|> Enum.reject(fn {_key, value} -> value in [false, nil] end)
4672
end
4773
end

0 commit comments

Comments
 (0)