diff options
-rw-r--r-- | src/luarocks/deps.lua | 9 | ||||
-rw-r--r-- | src/luarocks/fetch/git.lua | 57 |
2 files changed, 58 insertions, 8 deletions
diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua index 0e3265b5..f6c86d1c 100644 --- a/src/luarocks/deps.lua +++ b/src/luarocks/deps.lua | |||
@@ -159,6 +159,15 @@ function deps.compare_versions(a, b) | |||
159 | return deps.parse_version(a) > deps.parse_version(b) | 159 | return deps.parse_version(a) > deps.parse_version(b) |
160 | end | 160 | end |
161 | 161 | ||
162 | --- Check if rockspec format version satisfies version requirement. | ||
163 | -- @param rockspec table: The rockspec table. | ||
164 | -- @param version string: required version. | ||
165 | -- @return boolean: true if rockspec format matches version or is newer, false otherwise. | ||
166 | function deps.format_is_at_least(rockspec, version) | ||
167 | local rockspec_format = rockspec.rockspec_format or "1.0" | ||
168 | return deps.parse_version(rockspec_format) >= deps.parse_version(version) | ||
169 | end | ||
170 | |||
162 | --- Consumes a constraint from a string, converting it to table format. | 171 | --- Consumes a constraint from a string, converting it to table format. |
163 | -- For example, a string ">= 1.0, > 2.0" is converted to a table in the | 172 | -- For example, a string ">= 1.0, > 2.0" is converted to a table in the |
164 | -- format {op = ">=", version={1,0}} and the rest, "> 2.0", is returned | 173 | -- format {op = ">=", version={1,0}} and the rest, "> 2.0", is returned |
diff --git a/src/luarocks/fetch/git.lua b/src/luarocks/fetch/git.lua index e540d696..ce41659b 100644 --- a/src/luarocks/fetch/git.lua +++ b/src/luarocks/fetch/git.lua | |||
@@ -7,20 +7,48 @@ local unpack = unpack or table.unpack | |||
7 | 7 | ||
8 | local fs = require("luarocks.fs") | 8 | local fs = require("luarocks.fs") |
9 | local dir = require("luarocks.dir") | 9 | local dir = require("luarocks.dir") |
10 | local deps = require("luarocks.deps") | ||
10 | local util = require("luarocks.util") | 11 | local util = require("luarocks.util") |
11 | 12 | ||
13 | local cached_git_version | ||
14 | |||
15 | --- Get git version. | ||
16 | -- @param git_cmd string: name of git command. | ||
17 | -- @return table: git version as returned by luarocks.deps.parse_version. | ||
18 | local function git_version(git_cmd) | ||
19 | if not cached_git_version then | ||
20 | local version_line = io.popen(fs.Q(git_cmd)..' --version'):read() | ||
21 | local version_string = version_line:match('%d-%.%d+%.?%d*') | ||
22 | cached_git_version = deps.parse_version(version_string) | ||
23 | end | ||
24 | |||
25 | return cached_git_version | ||
26 | end | ||
27 | |||
28 | --- Check if git satisfies version requirement. | ||
29 | -- @param git_cmd string: name of git command. | ||
30 | -- @param version string: required version. | ||
31 | -- @return boolean: true if git matches version or is newer, false otherwise. | ||
32 | local function git_is_at_least(git_cmd, version) | ||
33 | return git_version(git_cmd) >= deps.parse_version(version) | ||
34 | end | ||
35 | |||
12 | --- Git >= 1.7.10 can clone a branch **or tag**, < 1.7.10 by branch only. We | 36 | --- Git >= 1.7.10 can clone a branch **or tag**, < 1.7.10 by branch only. We |
13 | -- need to know this in order to build the appropriate command; if we can't | 37 | -- need to know this in order to build the appropriate command; if we can't |
14 | -- clone by tag then we'll have to issue a subsequent command to check out the | 38 | -- clone by tag then we'll have to issue a subsequent command to check out the |
15 | -- given tag. | 39 | -- given tag. |
40 | -- @param git_cmd string: name of git command. | ||
16 | -- @return boolean: Whether Git can clone by tag. | 41 | -- @return boolean: Whether Git can clone by tag. |
17 | local function git_can_clone_by_tag(git_cmd) | 42 | local function git_can_clone_by_tag(git_cmd) |
18 | local version_string = io.popen(fs.Q(git_cmd)..' --version'):read() | 43 | return git_is_at_least(git_cmd, "1.7.10") |
19 | local major, minor, tiny = version_string:match('(%d-)%.(%d+)%.?(%d*)') | 44 | end |
20 | major, minor, tiny = tonumber(major), tonumber(minor), tonumber(tiny) or 0 | 45 | |
21 | local value = major > 1 or (major == 1 and (minor > 7 or (minor == 7 and tiny >= 10))) | 46 | --- Git >= 1.8.4 can fetch submodules shallowly, saving bandwidth and time for |
22 | git_can_clone_by_tag = function() return value end | 47 | -- submodules with large history. |
23 | return value | 48 | -- @param git_cmd string: name of git command. |
49 | -- @return boolean: Whether Git can fetch submodules shallowly. | ||
50 | local function git_supports_shallow_submodules(git_cmd) | ||
51 | return git_is_at_least(git_cmd, "1.8.4") | ||
24 | end | 52 | end |
25 | 53 | ||
26 | --- Download sources for building a rock, using git. | 54 | --- Download sources for building a rock, using git. |
@@ -77,12 +105,25 @@ function git.get_sources(rockspec, extract, dest_dir, depth) | |||
77 | ok, err = fs.change_dir(module) | 105 | ok, err = fs.change_dir(module) |
78 | if not ok then return nil, err end | 106 | if not ok then return nil, err end |
79 | if tag_or_branch and not git_can_clone_by_tag() then | 107 | if tag_or_branch and not git_can_clone_by_tag() then |
80 | local checkout_command = {fs.Q(git_cmd), "checkout", tag_or_branch} | 108 | if not fs.execute(fs.Q(git_cmd), "checkout", tag_or_branch) then |
81 | if not fs.execute(unpack(checkout_command)) then | ||
82 | return nil, 'Failed to check out the "' .. tag_or_branch ..'" tag or branch.' | 109 | return nil, 'Failed to check out the "' .. tag_or_branch ..'" tag or branch.' |
83 | end | 110 | end |
84 | end | 111 | end |
85 | 112 | ||
113 | -- Fetching git submodules is supported only when rockspec format is >= 3.0. | ||
114 | if deps.format_is_at_least(rockspec, "3.0") then | ||
115 | command = {fs.Q(git_cmd), "submodule", "update", "--init", "--recursive"} | ||
116 | |||
117 | if git_supports_shallow_submodules(git_cmd) then | ||
118 | -- Fetch only the last commit of each submodule. | ||
119 | table.insert(command, 5, "--depth=1") | ||
120 | end | ||
121 | |||
122 | if not fs.execute(unpack(command)) then | ||
123 | return nil, 'Failed to fetch submodules.' | ||
124 | end | ||
125 | end | ||
126 | |||
86 | fs.delete(dir.path(store_dir, module, ".git")) | 127 | fs.delete(dir.path(store_dir, module, ".git")) |
87 | fs.delete(dir.path(store_dir, module, ".gitignore")) | 128 | fs.delete(dir.path(store_dir, module, ".gitignore")) |
88 | fs.pop_dir() | 129 | fs.pop_dir() |