Skip to content

Commit 7f967e1

Browse files
authored
Merge pull request #7 from JuliaPackaging/tk/bindeps
RFC: download a binary of git if it is not already installed
2 parents 8447f3a + cbccc3b commit 7f967e1

File tree

7 files changed

+113
-21
lines changed

7 files changed

+113
-21
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
*.jl.cov
22
*.jl.*.cov
33
*.jl.mem
4+
deps/downloads/
5+
deps/usr/
6+
deps/deps.jl

REQUIRE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
julia 0.4
22
Compat 0.8.4
3+
BinDeps
4+
@osx Homebrew

appveyor.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ notifications:
2020
on_build_status_changed: false
2121

2222
install:
23+
# If there's a newer build queued for the same PR, cancel this one
24+
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
25+
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
26+
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
27+
throw "There are newer queued builds for this pull request, failing early." }
2328
# Download most recent Julia Windows binary
2429
- ps: (new-object net.webclient).DownloadFile(
2530
$("http://s3.amazonaws.com/"+$env:JULIAVERSION),

deps/build.jl

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using Compat
2+
import BinDeps: download_cmd, unpack_cmd, splittarpath
3+
if is_apple()
4+
using Homebrew
5+
end
6+
7+
gitcmd = `git`
8+
gitver = "notfound"
9+
try
10+
gitver = readchomp(`$gitcmd --version`)
11+
end
12+
if gitver == "notfound"
13+
if is_apple()
14+
# we could allow other options, but lots of other packages already
15+
# depend on Homebrew.jl on mac and it needs a working git to function
16+
error("Working git not found on path, try running\nPkg.build(\"Homebrew\")")
17+
end
18+
baseurl = ""
19+
filename = ""
20+
if is_linux() && Sys.ARCH === :x86_64
21+
# use conda for a non-root option
22+
gitver = "2.8.2"
23+
baseurl = "https://anaconda.org/conda-forge/git/$gitver/download/linux-64/"
24+
filename = "git-$gitver-2.tar.bz2"
25+
elseif is_linux() && (Sys.ARCH in (:i686, :i586, :i486, :i386))
26+
# conda-forge doesn't build for 32 bit linux
27+
gitver = "2.6.4"
28+
baseurl = "https://anaconda.org/anaconda/git/$gitver/download/linux-32/"
29+
filename = "git-$gitver-0.tar.bz2"
30+
elseif is_windows()
31+
# download and extract portablegit
32+
gitver = "2.9.0"
33+
baseurl = "https://github.com/git-for-windows/git/releases/" *
34+
"download/v$gitver.windows.1/"
35+
filename = "PortableGit-$gitver-$(Sys.WORD_SIZE)-bit.7z.exe"
36+
end
37+
downloadurl = baseurl * filename
38+
if !isempty(downloadurl)
39+
info("Downloading git version $gitver from $downloadurl\nTo " *
40+
"avoid this download, install git manually and add it to your " *
41+
"path before\nrunning Pkg.add(\"Git\") or Pkg.build(\"Git\")")
42+
dest = joinpath("usr", string(Sys.MACHINE))
43+
for dir in ("downloads", "usr", dest)
44+
isdir(dir) || mkdir(dir)
45+
end
46+
filename = joinpath("downloads", filename)
47+
isfile(filename) || run(download_cmd(downloadurl, filename))
48+
# TODO: checksum validation
49+
(b, ext, sec_ext) = splittarpath(filename)
50+
run(unpack_cmd(filename, dest, is_windows() ? ".7z" : ext, sec_ext))
51+
# TODO: make this less noisy on windows, see how WinRPM does it
52+
gitcmd = `$(joinpath(dirname(@__FILE__), dest, "bin", "git"))`
53+
end
54+
try
55+
gitver = readchomp(`$gitcmd --version`)
56+
info("Successfully installed $gitver to $gitcmd")
57+
# TODO: fix a warning about missing /templates here on linux
58+
# by setting an environment variable in deps.jl
59+
catch err
60+
error("Could not automatically install git, error was: $err\n" *
61+
(isempty(downloadurl) ? "Try installing git via your system " *
62+
"package manager then running\nPkg.build(\"Git\")" : ""))
63+
end
64+
else
65+
try
66+
# this is in a try because some environments like centos 7
67+
# docker containers don't have `which` installed by default
68+
gitpath = chomp(readlines(is_windows() ? `where git` : `which git`)[1])
69+
gitcmd = `$gitpath`
70+
end
71+
info("Using $gitver found on path" * (gitcmd == `git` ?
72+
"" : " at $gitcmd"))
73+
end
74+
open("deps.jl", "w") do f
75+
println(f, "gitcmd = $gitcmd")
76+
end

src/Git.jl

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,25 @@ module Git
66
#
77
using Compat
88
import Base: shell_escape
9+
export gitcmd # determined by deps/build.jl and saved in deps/deps.jl
10+
11+
depsjl = joinpath(dirname(@__FILE__), "..", "deps", "deps.jl")
12+
isfile(depsjl) ? include(depsjl) : error("Git.jl not properly installed. " *
13+
"Please run\nPkg.build(\"Git\")")
914

1015
function dir(d)
1116
g = joinpath(d,".git")
1217
isdir(g) && return g
13-
normpath(d, Base.readchomp(setenv(`git rev-parse --git-dir`, dir=d)))
18+
normpath(d, Base.readchomp(setenv(`$gitcmd rev-parse --git-dir`, dir=d)))
1419
end
1520

21+
git() = gitcmd
1622
function git(d)
17-
isempty(d) && return `git`
23+
isempty(d) && return gitcmd
1824
work_tree = abspath(d)
1925
git_dir = joinpath(work_tree, dir(work_tree))
2026
normpath(work_tree, ".") == normpath(git_dir, ".") ? # is it a bare repo?
21-
`git --git-dir=$work_tree` : `git --work-tree=$work_tree --git-dir=$git_dir`
27+
`$gitcmd --git-dir=$work_tree` : `$gitcmd --work-tree=$work_tree --git-dir=$git_dir`
2228
end
2329

2430
cmd(args::Cmd; dir="") = `$(git(dir)) $args`

test/gitutils.jl

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ function mktree(d::Dict)
1414
lstree = ""
1515
for (name, data) in d
1616
if isa(data, AbstractString)
17-
sha1 = write_and_readchomp(data, `git hash-object -w --stdin`)
17+
sha1 = write_and_readchomp(data, `$gitcmd hash-object -w --stdin`)
1818
lstree *= "100644 blob $sha1\t$name\n"
1919
elseif isa(data, Dict)
2020
sha1 = mktree(data)
@@ -25,21 +25,21 @@ function mktree(d::Dict)
2525
error("mktree: don't know what to do with $name => $data")
2626
end
2727
end
28-
write_and_readchomp(lstree, `git mktree`)
28+
write_and_readchomp(lstree, `$gitcmd mktree`)
2929
end
3030

3131
function verify_tree(d::Dict, tree::AbstractString)
3232
# check that tree matches d
3333
seen = Set()
34-
for line in eachline(`git ls-tree $tree`)
34+
for line in eachline(`$gitcmd ls-tree $tree`)
3535
m = match(r"^(\d{6}) (\w+) ([0-9a-f]{40})\t(.*)$", line)
3636
@test m != nothing
3737
perm, kind, sha1, name = m.captures
3838
@test haskey(d,name)
3939
data = d[name]
4040
if isa(data, AbstractString)
4141
@test kind == "blob"
42-
@test data == readstring(`git cat-file blob $sha1`)
42+
@test data == readstring(`$gitcmd cat-file blob $sha1`)
4343
elseif isa(data, Dict)
4444
@test kind == "tree"
4545
verify_tree(data, sha1)
@@ -74,15 +74,15 @@ function verify_work(d::Dict)
7474
end
7575
end
7676
# check for anything that's not in d
77-
for line in eachline(`ls -A`)
77+
for line in readdir()
7878
name = chomp(line)
7979
@test name == ".git" || haskey(d,name)
8080
end
8181
end
8282

8383
function git_verify(h::Dict, i::Dict, w::Dict)
8484
verify_tree(h, "HEAD")
85-
verify_tree(i, readchomp(`git write-tree`))
85+
verify_tree(i, readchomp(`$gitcmd write-tree`))
8686
verify_work(w)
8787
end
8888

@@ -93,24 +93,24 @@ function git_setup(h::Dict, i::Dict, w::Dict, parents::AbstractString...)
9393
work = mktree(w)
9494

9595
# clear the repo
96-
for line in eachline(`ls -A`)
96+
for line in readdir()
9797
name = chomp(line)
9898
name == ".git" || rm(name, recursive=true)
9999
end
100100

101101
# create the head commit
102-
commit_tree = `git commit-tree $headt`
102+
commit_tree = `$gitcmd commit-tree $headt`
103103
for parent in parents
104104
commit_tree = `$commit_tree -p $parent`
105105
end
106106
head = write_and_readchomp(headt, commit_tree)
107-
run(`git reset -q --soft $head`)
107+
run(`$gitcmd reset -q --soft $head`)
108108

109-
run(`git read-tree $work`) # read work into the index
110-
run(`git checkout-index -fa`) # check the index out
111-
run(`git read-tree $index`) # setup the index
109+
run(`$gitcmd read-tree $work`) # read work into the index
110+
run(`$gitcmd checkout-index -fa`) # check the index out
111+
run(`$gitcmd read-tree $index`) # setup the index
112112

113113
# verify that everything is as expected
114114
git_verify(h, i, w)
115115
end
116-
git_setup(h::Dict, i::Dict, w::Dict) = git_setup(h, i, w, readchomp(`git rev-parse HEAD`))
116+
git_setup(h::Dict, i::Dict, w::Dict) = git_setup(h, i, w, readchomp(`$gitcmd rev-parse HEAD`))

test/runtests.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ dir = string("tmp.",randstring())
1212
mkdir(dir)
1313
@test isdir(dir)
1414
try cd(dir) do
15-
run(`git init -q`)
16-
run(`git config user.name "Julia Tester"`)
17-
run(`git config user.email [email protected]`)
18-
run(`git commit -q --allow-empty -m "initial empty commit"`)
15+
run(`$gitcmd init -q`)
16+
run(`$gitcmd config user.name "Julia Tester"`)
17+
run(`$gitcmd config user.email [email protected]`)
18+
run(`$gitcmd commit -q --allow-empty -m "initial empty commit"`)
1919
git_verify(Dict(), Dict(), Dict())
2020

2121
# each path can have one of these content in each of head, index, work
@@ -26,7 +26,7 @@ try cd(dir) do
2626

2727
contents = [nothing, "foo", "bar", Dict{Any,Any}("baz"=>"qux")]
2828
b = length(contents)
29-
states = [ [ base(b,k,6) => contents[rem(div(k,b^p),b)+1] for k=0:(b^3)^2-1 ] for p=0:5 ]
29+
states = [Dict([(base(b,k,6), contents[rem(div(k,b^p),b)+1]) for k=0:(b^3)^2-1]) for p=0:5]
3030

3131
git_setup(states[1:3]...)
3232
try Git.transact() do

0 commit comments

Comments
 (0)