Skip to content

Commit fc83145

Browse files
author
José Valim
committed
Allow git migration to and from sparse
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
1 parent 091ce84 commit fc83145

File tree

10 files changed

+124
-179
lines changed

10 files changed

+124
-179
lines changed

lib/mix/lib/mix/dep.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ defmodule Mix.Dep do
267267
do: "the dependency was built with another SCM, run \"#{mix_env_var}mix deps.compile\""
268268

269269
defp dep_status(%Mix.Dep{app: app, requirement: req, manager: manager, opts: opts, from: from}) do
270-
opts = Keyword.drop(opts, [:dest, :build, :lock, :manager])
270+
opts = Keyword.drop(opts, [:dest, :build, :lock, :manager, :checkout])
271271
opts = opts ++ (if manager, do: [manager: manager], else: [])
272272
info = if req, do: {app, req, opts}, else: {app, opts}
273273
"\n > In #{Path.relative_to_cwd(from)}:\n #{inspect info}\n"

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

Lines changed: 56 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ defmodule Mix.SCM.Git do
2525
end
2626

2727
def accepts_options(_app, opts) do
28-
opts = sparse_opts(opts)
28+
opts =
29+
opts
30+
|> Keyword.put(:checkout, opts[:dest])
31+
|> sparse_opts()
32+
2933
cond do
3034
gh = opts[:github] ->
3135
opts
@@ -42,7 +46,7 @@ defmodule Mix.SCM.Git do
4246

4347
def checked_out?(opts) do
4448
# Are we inside a Git repository?
45-
git_dest(opts)
49+
opts[:checkout]
4650
|> Path.join(".git/HEAD")
4751
|> File.regular?
4852
end
@@ -53,7 +57,7 @@ defmodule Mix.SCM.Git do
5357

5458
cond do
5559
lock_rev = get_lock_rev(lock, opts) ->
56-
File.cd!(git_dest(opts), fn ->
60+
File.cd!(opts[:checkout], fn ->
5761
%{origin: origin, rev: rev} = get_rev_info()
5862
if get_lock_repo(lock) == origin and lock_rev == rev do
5963
:ok
@@ -79,129 +83,100 @@ defmodule Mix.SCM.Git do
7983

8084
def checkout(opts) do
8185
assert_git!()
82-
83-
path = git_dest(opts)
84-
location = opts[:git]
85-
86-
_ = File.rm_rf!(path)
87-
88-
fun =
89-
if opts[:sparse] do
90-
sparse_check(git_version())
91-
File.mkdir_p!(path)
92-
fn -> init_sparse(opts) end
93-
else
94-
git!(~s(clone --no-checkout --progress "#{location}" "#{path}"))
95-
fn -> do_checkout(opts) end
96-
end
97-
98-
File.cd! path, fun
86+
path = opts[:checkout]
87+
File.rm_rf!(path)
88+
File.mkdir_p!(path)
89+
File.cd!(path, fn ->
90+
git!("init --quiet")
91+
git!("--git-dir=.git remote add origin \"#{opts[:git]}\"")
92+
checkout(path, opts)
93+
end)
9994
end
10095

10196
def update(opts) do
10297
assert_git!()
98+
path = opts[:checkout]
99+
File.cd! path, fn -> checkout(path, opts) end
100+
end
103101

104-
File.cd! git_dest(opts), fn ->
105-
sparse_toggle(opts)
102+
defp checkout(_path, opts) do
103+
# Set configuration
104+
sparse_toggle(opts)
105+
update_origin(opts[:git])
106106

107-
location = opts[:git]
108-
update_origin(location)
107+
# Fetch external data
108+
command = IO.iodata_to_binary(["--git-dir=.git fetch --force --quiet",
109+
progress_switch(git_version()),
110+
tags_switch(opts[:tag])])
111+
git!(command)
109112

110-
command = IO.iodata_to_binary(["--git-dir=.git fetch --force",
111-
progress_switch(git_version()),
112-
tags_switch(opts[:tag])])
113+
# Migrate the git repo
114+
rev = get_lock_rev(opts[:lock], opts) || get_opts_rev(opts)
115+
git!("--git-dir=.git checkout --quiet #{rev}")
113116

114-
git!(command)
115-
do_checkout(opts)
117+
if opts[:submodules] do
118+
git!("--git-dir=.git submodule update --init --recursive")
116119
end
120+
121+
# Get the new repo lock
122+
get_lock(opts)
117123
end
118124

119125
defp sparse_opts(opts) do
120126
if opts[:sparse] do
121127
dest = Path.join(opts[:dest], opts[:sparse])
122-
opts
123-
|> Keyword.put(:git_dest, opts[:dest])
124-
|> Keyword.put(:dest, dest)
128+
Keyword.put(opts, :dest, dest)
125129
else
126130
opts
127131
end
128132
end
129133

134+
defp sparse_toggle(opts) do
135+
cond do
136+
sparse = opts[:sparse] ->
137+
sparse_check(git_version())
138+
git!("--git-dir=.git config core.sparsecheckout true")
139+
File.write!(".git/info/sparse-checkout", sparse)
140+
File.exists?(".git/info/sparse-checkout") ->
141+
File.write!(".git/info/sparse-checkout", "*")
142+
git!("--git-dir=.git read-tree -mu HEAD")
143+
git!("--git-dir=.git config core.sparsecheckout false")
144+
File.rm(".git/info/sparse-checkout")
145+
true ->
146+
:ok
147+
end
148+
end
149+
130150
defp sparse_check(version) do
131151
unless {1, 7, 0} <= version do
132-
version =
133-
version
134-
|> Tuple.to_list
135-
|> Enum.join(".")
152+
version = version |> Tuple.to_list |> Enum.join(".")
136153
Mix.raise "Git >= 1.7.0 is required to use sparse checkout. " <>
137-
"You are running version #{version}"
154+
"You are running version #{version}"
138155
end
139156
end
140157

141-
defp sparse_toggle(opts) do
142-
git!("config core.sparsecheckout #{opts[:sparse] != nil}")
143-
end
144-
145-
146158
defp progress_switch(version) when {1, 7, 1} <= version, do: " --progress"
147159
defp progress_switch(_), do: ""
148160

149161
defp tags_switch(nil), do: ""
150162
defp tags_switch(_), do: " --tags"
151163

152-
defp git_dest(opts) do
153-
if opts[:git_dest] do
154-
opts[:git_dest]
155-
else
156-
opts[:dest]
157-
end
158-
end
159-
160164
## Helpers
161165

162166
defp validate_git_options(opts) do
163167
err = "You should specify only one of branch, ref or tag, and only once. " <>
164168
"Error on Git dependency: #{opts[:git]}"
165169
validate_single_uniq(opts, [:branch, :ref, :tag], err)
166-
167-
err = "You should specify only one sparse path. " <>
168-
"Error on Git dependency: #{opts[:git]}"
169-
validate_single_uniq(opts, [:sparse], err)
170170
end
171171

172172
defp validate_single_uniq(opts, take, error) do
173173
case Keyword.take(opts, take) do
174-
[] -> opts
174+
[] -> opts
175175
[_] -> opts
176176
_ -> Mix.raise error
177177
end
178178
end
179179

180-
defp init_sparse(opts) do
181-
git!("init --quiet")
182-
git!("remote add origin #{opts[:git]} --fetch")
183-
sparse_toggle(opts)
184-
185-
sparse_info =
186-
File.cwd!
187-
|> Path.join(".git/info/sparse-checkout")
188-
189-
File.write(sparse_info, opts[:sparse])
190-
191-
do_checkout(opts)
192-
end
193-
194-
defp do_checkout(opts) do
195-
rev = get_lock_rev(opts[:lock], opts) || get_opts_rev(opts)
196-
git!("--git-dir=.git checkout --quiet #{rev}")
197-
198-
if opts[:submodules] do
199-
git!("--git-dir=.git submodule update --init --recursive")
200-
end
201-
202-
get_lock(opts)
203-
end
204-
205180
defp get_lock(opts) do
206181
%{rev: rev} = get_rev_info()
207182
{:git, opts[:git], rev, get_lock_opts(opts)}
@@ -217,13 +192,7 @@ defmodule Mix.SCM.Git do
217192
defp get_lock_rev(_, _), do: nil
218193

219194
defp get_lock_opts(opts) do
220-
lock_opts = Keyword.take(opts, [:branch, :ref, :tag])
221-
lock_opts =
222-
if opts[:sparse] do
223-
lock_opts ++ [sparse: opts[:sparse]]
224-
else
225-
lock_opts
226-
end
195+
lock_opts = Keyword.take(opts, [:branch, :ref, :tag, :sparse])
227196

228197
if opts[:submodules] do
229198
lock_opts ++ [submodules: true]
Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
11
{sub_dirs, ["apps/*"]}.
22

3-
{deps, [
4-
{git_rebar, "0.1..*", {git, "../../test/fixtures/git_rebar", master}}
5-
]}.
6-
73
{overrides, [{add, rebar_dep, [{src_dirs, ["apps/rebar_dep/src"]}]}]}.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
CONFIG ++ [{'SCRIPT', SCRIPT}].
1+
CONFIG ++ [{'SCRIPT', SCRIPT}] ++ [{deps, [{git_rebar, "0.1..*", {git, filename:absname("../../test/fixtures/git_rebar"), master}}]}].

lib/mix/test/fixtures/rebar_override/rebar.config

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[
2+
{deps, [
3+
{git_rebar, {git, filename:absname("../../test/fixtures/git_rebar")}}
4+
]},
5+
{overrides, [
6+
{override, git_rebar, [{deps, [{git_repo, {git, filename:absname("../../test/fixtures/git_repo")}}]}]}
7+
]}
8+
].

lib/mix/test/mix/rebar_test.exs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ defmodule Mix.RebarTest do
106106

107107
assert Enum.find(deps, fn %Mix.Dep{app: app, opts: opts} ->
108108
if app == :git_rebar do
109-
assert Enum.find(opts, &match?({:git, "../../test/fixtures/git_rebar"}, &1))
109+
assert Enum.find(opts, &match?({:git, _}, &1))
110110
assert Enum.find(opts, &match?({:ref, "master"}, &1))
111111
true
112112
end
@@ -155,7 +155,7 @@ defmodule Mix.RebarTest do
155155

156156
in_tmp "get and compile dependencies for Rebar", fn ->
157157
Mix.Tasks.Deps.Get.run []
158-
assert_received {:mix_shell, :info, ["* Getting git_rebar (../../test/fixtures/git_rebar)"]}
158+
assert_received {:mix_shell, :info, ["* Getting git_rebar" <> _]}
159159

160160
Mix.Tasks.Deps.Compile.run []
161161
assert_received {:mix_shell, :run, ["==> git_rebar (compile)\n"]}
@@ -185,7 +185,7 @@ defmodule Mix.RebarTest do
185185

186186
in_tmp "get and compile dependencies for rebar3", fn ->
187187
Mix.Tasks.Deps.Get.run []
188-
assert_received {:mix_shell, :info, ["* Getting git_rebar (../../test/fixtures/git_rebar)"]}
188+
assert_received {:mix_shell, :info, ["* Getting git_rebar " <> _]}
189189

190190
Mix.Tasks.Deps.Compile.run []
191191
assert_received {:mix_shell, :run, ["===> Compiling git_rebar\n"]}

lib/mix/test/mix/scm/git_test.exs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ defmodule Mix.SCM.GitTest do
3030
assert_raise Mix.Error, ~r/You should specify only one of branch, ref or tag/, fn ->
3131
Mix.SCM.Git.accepts_options(nil, [git: "/repo", branch: "master", branch: "develop"])
3232
end
33-
34-
assert_raise Mix.Error, ~r/You should specify only one sparse path/, fn ->
35-
Mix.SCM.Git.accepts_options(nil, [git: "/repo", sparse: "/a", sparse: "/b", dest: "/repo"])
36-
end
3733
end
3834

3935
defp lock(opts \\ []) do

0 commit comments

Comments
 (0)