<commit_before>
--- Fetch back-end for retrieving sources from GIT.
local git = {}

local unpack = unpack or table.unpack

local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local vers = require("luarocks.vers")
local util = require("luarocks.util")

local cached_git_version

--- Get git version.
-- @param git_cmd string: name of git command.
-- @return table: git version as returned by luarocks.vers.parse_version.
local function git_version(git_cmd)
   if not cached_git_version then
      local version_line = io.popen(fs.Q(git_cmd)..' --version'):read()
      local version_string = version_line:match('%d-%.%d+%.?%d*')
      cached_git_version = vers.parse_version(version_string)
   end

   return cached_git_version
end

--- Check if git satisfies version requirement.
-- @param git_cmd string: name of git command.
-- @param version string: required version.
-- @return boolean: true if git matches version or is newer, false otherwise.
local function git_is_at_least(git_cmd, version)
   return git_version(git_cmd) >= vers.parse_version(version)
end

--- Git >= 1.7.10 can clone a branch **or tag**, < 1.7.10 by branch only. We
-- need to know this in order to build the appropriate command; if we can't
-- clone by tag then we'll have to issue a subsequent command to check out the
-- given tag.
-- @param git_cmd string: name of git command.
-- @return boolean: Whether Git can clone by tag.
local function git_can_clone_by_tag(git_cmd)
   return git_is_at_least(git_cmd, "1.7.10")
end

--- Git >= 1.8.4 can fetch submodules shallowly, saving bandwidth and time for
-- submodules with large history.
-- @param git_cmd string: name of git command.
-- @return boolean: Whether Git can fetch submodules shallowly.
local function git_supports_shallow_submodules(git_cmd)
   return git_is_at_least(git_cmd, "1.8.4")
end

local function git_identifier(git_cmd, ver)
   if not (ver:match("^dev%-%d+$") or ver:match("^scm%-%d+$")) then
      return nil
   end
   local date_hash = util.popen_read(fs.Q(git_cmd).." log --pretty=format:'%ai %h' -n 1")
   local date, time, tz, hash = date_hash:match("([^%s]+) ([^%s]+) ([^%s]+) ([^%s]+)")
   date = date:gsub("%-", "")
   time = time:gsub(":", "")
   return date .. "." .. time .. "." .. hash
end

--- Download sources for building a rock, using git.<commit_msg>Catch error when git fails to read the hash<commit_after>
--- Fetch back-end for retrieving sources from GIT.
local git = {}

local unpack = unpack or table.unpack

local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local vers = require("luarocks.vers")
local util = require("luarocks.util")

local cached_git_version

--- Get git version.
-- @param git_cmd string: name of git command.
-- @return table: git version as returned by luarocks.vers.parse_version.
local function git_version(git_cmd)
   if not cached_git_version then
      local version_line = io.popen(fs.Q(git_cmd)..' --version'):read()
      local version_string = version_line:match('%d-%.%d+%.?%d*')
      cached_git_version = vers.parse_version(version_string)
   end

   return cached_git_version
end

--- Check if git satisfies version requirement.
-- @param git_cmd string: name of git command.
-- @param version string: required version.
-- @return boolean: true if git matches version or is newer, false otherwise.
local function git_is_at_least(git_cmd, version)
   return git_version(git_cmd) >= vers.parse_version(version)
end

--- Git >= 1.7.10 can clone a branch **or tag**, < 1.7.10 by branch only. We
-- need to know this in order to build the appropriate command; if we can't
-- clone by tag then we'll have to issue a subsequent command to check out the
-- given tag.
-- @param git_cmd string: name of git command.
-- @return boolean: Whether Git can clone by tag.
local function git_can_clone_by_tag(git_cmd)
   return git_is_at_least(git_cmd, "1.7.10")
end

--- Git >= 1.8.4 can fetch submodules shallowly, saving bandwidth and time for
-- submodules with large history.
-- @param git_cmd string: name of git command.
-- @return boolean: Whether Git can fetch submodules shallowly.
local function git_supports_shallow_submodules(git_cmd)
   return git_is_at_least(git_cmd, "1.8.4")
end

local function git_identifier(git_cmd, ver)
   if not (ver:match("^dev%-%d+$") or ver:match("^scm%-%d+$")) then
      return nil
   end
   local date_hash = util.popen_read(fs.Q(git_cmd).." log --pretty=format:'%ai %h' -n 1")
   if not date_hash then
      return nil
   end
   local date, time, tz, hash = date_hash:match("([^%s]+) ([^%s]+) ([^%s]+) ([^%s]+)")
   date = date:gsub("%-", "")
   time = time:gsub(":", "")
   return date .. "." .. time .. "." .. hash
end

--- Download sources for building a rock, using git.
{'fraction_non_alphanumeric': 0.13512944643233005, 'fraction_numerical': 0.00799831614396969, 'mean_word_length': 3.8, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5494874', 'n_tokens_mistral': 1584, 'n_tokens_neox': 1529, 'n_words': 524}