aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNorman Clarke <norman@njclarke.com>2012-06-22 11:41:56 -0300
committerNorman Clarke <norman@njclarke.com>2012-07-06 10:55:27 -0300
commitdb2ef01fe45bf80a73d273ab90d5ea0a5fc13ea3 (patch)
tree07fa9cb51919ff1f438b3a662a50cace1f1ca333
parent040f6eb2508438d9f7e3ced6a1f3ecb5cc23b89d (diff)
downloadluarocks-db2ef01fe45bf80a73d273ab90d5ea0a5fc13ea3.tar.gz
luarocks-db2ef01fe45bf80a73d273ab90d5ea0a5fc13ea3.tar.bz2
luarocks-db2ef01fe45bf80a73d273ab90d5ea0a5fc13ea3.zip
Adjust Git clone command according to Git version.
Git 1.7.10 and higher allows a branch or a tag to be passed as an argument to `git clone` along with `--depth=1`, which lets us check out the exact code needed to pack a rockspec without the entire repository's history. This offers a significant performance improvement for large repositories. For Git 1.7.9 and earlier, Luarocks will clone the repository without the branch argument in order to support both branches and tags. This is possible in part because prior to Git 1.7.10, git will clone sufficient repository history to check out any tag, even when the --depth option is passed. After cloning, Luarocks will then perform a `git checkout` prior to packing a rockspec. This is slower but lets Luarocks work consistently on more versions of Git. Resolves #73 Resolves #78 This change was implemented by: * Juan Ramírez (https://github.com/ichramm) * Ignacio Burgueño (https://github.com/ignacio) * Norman Clarke (https://github.com/norman)
-rw-r--r--src/luarocks/fetch/git.lua41
1 files changed, 35 insertions, 6 deletions
diff --git a/src/luarocks/fetch/git.lua b/src/luarocks/fetch/git.lua
index e5f1ad4d..d643d25d 100644
--- a/src/luarocks/fetch/git.lua
+++ b/src/luarocks/fetch/git.lua
@@ -6,6 +6,20 @@ local fs = require("luarocks.fs")
6local dir = require("luarocks.dir") 6local dir = require("luarocks.dir")
7local util = require("luarocks.util") 7local util = require("luarocks.util")
8 8
9--- Git >= 1.7.10 can clone a branch **or tag**, < 1.7.10 by branch only. We
10-- need to know this in order to build the appropriate command; if we can't
11-- clone by tag then we'll have to issue a subsequent command to check out the
12-- given tag.
13-- @return boolean: Whether Git can clone by tag.
14local function git_can_clone_by_tag()
15 local version_string = io.popen('git --version'):read()
16 local major, minor, tiny = version_string:match('(%d-)%.(%d+)%.?(%d*)')
17 major, minor, tiny = tonumber(major), tonumber(minor), tonumber(tiny) or 0
18 value = major > 1 or (major == 1 and (minor > 7 or (minor == 7 and tiny >= 10)))
19 git_can_clone_by_tag = function() return value end
20 return git_can_clone_by_tag()
21end
22
9--- Download sources for building a rock, using git. 23--- Download sources for building a rock, using git.
10-- @param rockspec table: The rockspec table 24-- @param rockspec table: The rockspec table
11-- @param extract boolean: Unused in this module (required for API purposes.) 25-- @param extract boolean: Unused in this module (required for API purposes.)
@@ -22,11 +36,7 @@ function get_sources(rockspec, extract, dest_dir)
22 local module = dir.base_name(rockspec.source.url) 36 local module = dir.base_name(rockspec.source.url)
23 -- Strip off .git from base name if present 37 -- Strip off .git from base name if present
24 module = module:gsub("%.git$", "") 38 module = module:gsub("%.git$", "")
25 local command = {git_cmd, "clone", "--depth=1", rockspec.source.url, module} 39
26 local tag_or_branch = rockspec.source.tag or rockspec.source.branch
27 if tag_or_branch then
28 table.insert(command, 4, "--branch=" .. tag_or_branch)
29 end
30 local store_dir 40 local store_dir
31 if not dest_dir then 41 if not dest_dir then
32 store_dir = fs.make_temp_dir(name_version) 42 store_dir = fs.make_temp_dir(name_version)
@@ -39,14 +49,33 @@ function get_sources(rockspec, extract, dest_dir)
39 end 49 end
40 store_dir = fs.absolute_name(store_dir) 50 store_dir = fs.absolute_name(store_dir)
41 fs.change_dir(store_dir) 51 fs.change_dir(store_dir)
52
53 local command = {git_cmd, "clone", "--depth=1", rockspec.source.url, module}
54 local tag_or_branch = rockspec.source.tag or rockspec.source.branch
55 -- If the tag or branch is explicitly set to "master" in the rockspec, then
56 -- we can avoid passing it to Git since it's the default.
57 if tag_or_branch == "master" then tag_or_branch = nil end
58 if tag_or_branch then
59 if git_can_clone_by_tag() then
60 -- The argument to `--branch` can actually be a branch or a tag as of
61 -- Git 1.7.10.
62 table.insert(command, 4, "--branch=" .. tag_or_branch)
63 end
64 end
42 if not fs.execute(unpack(command)) then 65 if not fs.execute(unpack(command)) then
43 return nil, "Failed cloning git repository." 66 return nil, "Failed cloning git repository."
44 end 67 end
45 fs.change_dir(module) 68 fs.change_dir(module)
69 if tag_or_branch and not git_can_clone_by_tag() then
70 local checkout_command = {git_cmd, "checkout", tag_or_branch}
71 if not fs.execute(unpack(checkout_command)) then
72 return nil, 'Failed to check out the "' .. tag_or_branch ..'" tag or branch.'
73 end
74 end
75
46 fs.delete(dir.path(store_dir, module, ".git")) 76 fs.delete(dir.path(store_dir, module, ".git"))
47 fs.delete(dir.path(store_dir, module, ".gitignore")) 77 fs.delete(dir.path(store_dir, module, ".gitignore"))
48 fs.pop_dir() 78 fs.pop_dir()
49 fs.pop_dir() 79 fs.pop_dir()
50 return module, store_dir 80 return module, store_dir
51end 81end
52