diff options
author | Norman Clarke <norman@njclarke.com> | 2012-06-22 11:41:56 -0300 |
---|---|---|
committer | Norman Clarke <norman@njclarke.com> | 2012-07-06 10:55:27 -0300 |
commit | db2ef01fe45bf80a73d273ab90d5ea0a5fc13ea3 (patch) | |
tree | 07fa9cb51919ff1f438b3a662a50cace1f1ca333 | |
parent | 040f6eb2508438d9f7e3ced6a1f3ecb5cc23b89d (diff) | |
download | luarocks-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.lua | 41 |
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") | |||
6 | local dir = require("luarocks.dir") | 6 | local dir = require("luarocks.dir") |
7 | local util = require("luarocks.util") | 7 | local 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. | ||
14 | local 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() | ||
21 | end | ||
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 |
51 | end | 81 | end |
52 | |||