Skip to content

Commit 5d48abb

Browse files
author
José Valim
committed
Ensure we can clean deps that no longer exists
1 parent 1403350 commit 5d48abb

File tree

8 files changed

+45
-43
lines changed

8 files changed

+45
-43
lines changed

lib/mix/lib/mix/scm.ex

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,6 @@ defmodule Mix.SCM do
100100
"""
101101
defcallback equal?(opts1 :: opts, opts2 :: opts) :: boolean
102102

103-
@doc """
104-
This behavior function should clean the given dependency.
105-
"""
106-
defcallback clean(opts) :: any
107-
108103
@doc """
109104
Returns all available SCM.
110105
"""

lib/mix/lib/mix/scm/git.ex

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,6 @@ defmodule Mix.SCM.Git do
6868
end
6969
end
7070

71-
def clean(opts) do
72-
File.rm_rf opts[:dest]
73-
end
74-
7571
## Helpers
7672

7773
defp location("git://github.com/" <> rest) do

lib/mix/lib/mix/scm/path.ex

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,4 @@ defmodule Mix.SCM.Path do
4646
def update(opts) do
4747
opts[:lock]
4848
end
49-
50-
def clean(opts) do
51-
path = Path.relative_to_cwd opts[:dest]
52-
Mix.shell.info " #{path} is a path dependency, it was not cleaned"
53-
:noop
54-
end
55-
end
49+
end

lib/mix/lib/mix/tasks/clean.ex

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ defmodule Mix.Tasks.Clean do
99
1010
## Command line options
1111
12-
* `--all` - Clean everything, including dependencies
12+
* `--all` - Clean everything, including builds and dependencies
1313
1414
"""
1515

@@ -23,7 +23,11 @@ defmodule Mix.Tasks.Clean do
2323
File.rm(manifest)
2424
end)
2525

26-
File.rm_rf(Mix.Project.app_path)
27-
if opts[:all], do: Mix.Task.run("deps.clean", args)
26+
if opts[:all] do
27+
Mix.Task.run("deps.clean", args)
28+
File.rm_rf(Path.dirname(Mix.Project.build_path))
29+
else
30+
File.rm_rf(Mix.Project.app_path)
31+
end
2832
end
2933
end

lib/mix/lib/mix/tasks/deps.clean.ex

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,39 @@ defmodule Mix.Tasks.Deps.Clean do
1111
1212
Clean does not unlock the dependencies, unless `--unlock` is given.
1313
"""
14-
import Mix.Deps, only: [loaded: 0, loaded_by_name: 1, format_dep: 1]
15-
1614
def run(args) do
1715
Mix.Project.get! # Require the project to be available
16+
1817
{ opts, args, _ } = OptionParser.parse(args, switches: [unlock: :boolean, all: :boolean])
18+
loaded = Mix.Deps.loaded
1919

2020
cond do
2121
opts[:all] ->
22-
do_clean loaded, opts
22+
do_clean Enum.map(loaded, &(&1.app)), loaded, opts
2323
args != [] ->
24-
do_clean loaded_by_name(args), opts
24+
do_clean args, loaded, opts
2525
true ->
2626
raise Mix.Error, message: "mix deps.clean expects dependencies as arguments or " <>
2727
"the --all option to clean all dependencies"
2828
end
2929
end
3030

31-
defp do_clean(deps, opts) do
31+
defp do_clean(apps, loaded, opts) do
3232
shell = Mix.shell
33-
34-
apps = Enum.map deps, fn(Mix.Dep[scm: scm, opts: opts] = dep) ->
35-
shell.info "* Cleaning #{format_dep(dep)}"
36-
File.rm_rf!(opts[:build])
37-
scm.clean opts
38-
dep.app
33+
build = Mix.Project.build_path |> Path.join("lib")
34+
deps = Mix.Project.deps_path
35+
36+
Enum.each apps, fn(app) ->
37+
shell.info "* Cleaning #{app}"
38+
load_paths =
39+
if dep = Enum.find(loaded, &(&1.app == app)) do
40+
Mix.Deps.load_paths(dep)
41+
else
42+
[Path.join([build, app, "ebin"])]
43+
end
44+
45+
Enum.each(load_paths, &(&1 |> Path.dirname |> File.rm_rf!))
46+
File.rm_rf!(Path.join(deps, app))
3947
end
4048

4149
if opts[:unlock] do

lib/mix/test/mix/tasks/clean_test.exs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ defmodule Mix.Tasks.CleanTest do
2626
:ok
2727
end
2828

29-
test "removes the build configuration" do
29+
test "removes the build application" do
3030
in_fixture "deps_status", fn ->
3131
Mix.Tasks.Compile.run ["--no-deps"]
3232
assert File.exists?("_build/shared/lib/sample")
@@ -36,14 +36,28 @@ defmodule Mix.Tasks.CleanTest do
3636
end
3737
end
3838

39-
test "cleans all repos" do
39+
test "cleans deps" do
4040
in_fixture "deps_status", fn ->
4141
assert File.exists?("_build/shared/lib/ok")
42-
Mix.Tasks.Clean.run ["--all"]
42+
Mix.Tasks.Deps.Clean.run ["--all"]
4343

44+
assert File.exists?("_build/shared")
4445
refute File.exists?("_build/shared/lib/ok")
46+
assert_received { :mix_shell, :info, ["* Cleaning ok"] }
47+
4548
# Assert we don't choke on unfetched deps
46-
assert_received { :mix_shell, :info, ["* Cleaning unknown (deps/unknown)"] }
49+
assert_received { :mix_shell, :info, ["* Cleaning unknown"] }
50+
end
51+
end
52+
53+
test "cleans all deps and builds" do
54+
in_fixture "deps_status", fn ->
55+
assert File.exists?("_build/shared/lib/ok")
56+
Mix.Tasks.Clean.run ["--all"]
57+
58+
refute File.exists?("_build")
59+
assert_received { :mix_shell, :info, ["* Cleaning ok"] }
60+
assert_received { :mix_shell, :info, ["* Cleaning unknown"] }
4761
end
4862
end
4963
end

lib/mix/test/mix/tasks/deps.git_test.exs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,6 @@ defmodule Mix.Tasks.DepsGitTest do
6363
assert_received { :mix_shell, :info, [^message] }
6464
assert_received { :mix_shell, :info, ["* Compiling git_repo"] }
6565
assert_received { :mix_shell, :info, ["Compiled lib/git_repo.ex"] }
66-
67-
Mix.Tasks.Deps.Clean.run ["--all"]
68-
message = "* Cleaning git_repo 0.1.0 (#{fixture_path("git_repo")})"
69-
assert_received { :mix_shell, :info, [^message] }
70-
refute File.exists?("_build/shared/lib/git_repo/ebin/Elixir.Git.Repo.beam")
7166
end
7267
after
7368
Mix.Project.pop

lib/mix/test/mix/tasks/deps.path_test.exs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ defmodule Mix.Tasks.DepsPathTest do
2424
assert_received { :mix_shell, :info, ["Compiled lib/raw_repo.ex"] }
2525
assert_received { :mix_shell, :info, ["Generated raw_repo.app"] }
2626
assert File.exists?("_build/shared/lib/raw_repo/ebin/Elixir.RawRepo.beam")
27-
28-
Mix.Tasks.Deps.Clean.run ["--all"]
29-
assert_received { :mix_shell, :info, ["* Cleaning raw_repo 0.1.0 (custom/raw_repo)"] }
30-
assert_received { :mix_shell, :info, [" custom/raw_repo is a path dependency, it was not cleaned"] }
3127
end
3228
after
3329
Mix.Project.pop

0 commit comments

Comments
 (0)