exit = function (ctx) return true end,
}
-cvs.cvs_source = class("cvs_source", source.basic_source)
+--------------------------------------------------------------------------------
+
+--- Build the cvsroot string.
+-- @param src Source object.
+-- @return CVSROOT string or false on error.
+-- @return Error object on failure.
+local function mkcvsroot(src)
+ local cvsroot, surl, u, re
+
+ surl, re = cache.remote_url(cache.cache(), src:get_server(), src:get_cvsroot())
+ if not surl then
+ return false, e:cat(re)
+ end
+
+ u, re = url.parse(surl)
+ if not u then
+ return false, e:cat(re)
+ end
+
+ if u.transport == "file" then
+ cvsroot = string.format("/%s", u.path)
+ elseif (u.transport == "ssh") or (u.transport == "rsync+ssh") or
+ u.transport == "scp" then
+ cvsroot = string.format("%s:/%s", u.server, u.path)
+ elseif u.transport == "cvspserver" then
+ cvsroot = string.format(":pserver:%s:/%s", u.server, u.path)
+ else
+ return false, err.new("cvs: unhandled transport: %s", u.transport)
+ end
+
+ return cvsroot
+end
local function cvs_tool(argv, workdir)
local rc, re, cvscmd, cvsflags, rsh
return e2lib.callcmd_log(cvscmd, workdir, { CVS_RSH=rsh })
end
+--------------------------------------------------------------------------------
+
+cvs.cvs_source = class("cvs_source", source.basic_source)
+
function cvs.cvs_source.static:is_scm_source_class()
return true
end
return true
end
---------------------------------------------------------------------------------
-
---- Build the cvsroot string.
--- @param sourcename Source name.
--- @return CVSROOT string or false on error.
--- @return Error object on failure.
-local function mkcvsroot(sourcename)
- local cvsroot, src, surl, u, re
+function cvs.cvs_source:fetch_source()
+ local rc, re, e, cvsroot, workdir, argv
- src = source.sources[sourcename]
+ e = err.new("fetching source failed: %s", self._name)
- surl, re = cache.remote_url(cache.cache(), src:get_server(), src:get_cvsroot())
- if not surl then
- return false, e:cat(re)
- end
-
- u, re = url.parse(surl)
- if not u then
- return false, e:cat(re)
- end
-
- if u.transport == "file" then
- cvsroot = string.format("/%s", u.path)
- elseif (u.transport == "ssh") or (u.transport == "rsync+ssh") or
- u.transport == "scp" then
- cvsroot = string.format("%s:/%s", u.server, u.path)
- elseif u.transport == "cvspserver" then
- cvsroot = string.format(":pserver:%s:/%s", u.server, u.path)
- else
- return false, err.new("cvs: unhandled transport: %s", u.transport)
- end
-
- return cvsroot
-end
-
-function cvs.fetch_source(info, sourcename)
- local rc, re, e, src, cvsroot, workdir, argv
-
- e = err.new("fetching source failed: %s", sourcename)
- src = source.sources[sourcename]
-
- if src:working_copy_available() then
+ if self:working_copy_available() then
return true
end
- cvsroot, re = mkcvsroot(sourcename)
+ cvsroot, re = mkcvsroot(self)
if not cvsroot then
return false, e:cat(re)
end
-- split the working directory into dirname and basename as some cvs clients
-- don't like slashes (e.g. in/foo) in their checkout -d<path> argument
- workdir = e2lib.dirname(e2lib.join(e2tool.root(), src:get_working()))
+ workdir = e2lib.dirname(e2lib.join(e2tool.root(), self:get_working()))
argv = {
"-d", cvsroot,
"checkout",
"-R",
- "-d", e2lib.basename(src:get_working()),
+ "-d", e2lib.basename(self:get_working()),
}
-- always fetch the configured branch, as we don't know the build mode here.
-- HEAD has special meaning to cvs
- if src:get_branch() ~= "HEAD" then
+ if self:get_branch() ~= "HEAD" then
table.insert(argv, "-r")
- table.insert(argv, src:get_branch())
+ table.insert(argv, self:get_branch())
end
- table.insert(argv, src:get_module())
+ table.insert(argv, self:get_module())
rc, re = cvs_tool(argv, workdir)
if not rc or rc ~= 0 then
return true
end
-function cvs.prepare_source(info, sourcename, sourceset, buildpath)
- local rc, re, e, src, cvsroot, argv
+function cvs.cvs_source:prepare_source(sourceset, buildpath)
+ local rc, re, e, cvsroot, argv
e = err.new("cvs.prepare_source failed")
- src = source.sources[sourcename]
- cvsroot, re = mkcvsroot(sourcename)
+ cvsroot, re = mkcvsroot(self)
if not cvsroot then
return false, re
end
argv = {
"-d", cvsroot,
"export", "-R",
- "-d", src:get_name(),
+ "-d", self:get_name(),
"-r",
}
if sourceset == "branch" or
- (sourceset == "lazytag" and src:get_tag() == "^") then
- table.insert(argv, src:get_branch())
+ (sourceset == "lazytag" and self:get_tag() == "^") then
+ table.insert(argv, self:get_branch())
elseif (sourceset == "tag" or sourceset == "lazytag") and
- src:get_tag() ~= "^" then
- table.insert(argv, src:get_tag())
+ self:get_tag() ~= "^" then
+ table.insert(argv, self:get_tag())
else
return false, e:cat(err.new("source set not allowed"))
end
- table.insert(argv, src:get_module())
+ table.insert(argv, self:get_module())
rc, re = cvs_tool(argv, buildpath)
if not rc or rc ~= 0 then
return false, e:cat(re)
end
elseif sourceset == "working-copy" then
- rc, re = e2lib.cp(e2lib.join(e2tool.root(), src:get_working()),
- e2lib.join(buildpath, src:get_name()), true)
+ rc, re = e2lib.cp(e2lib.join(e2tool.root(), self:get_working()),
+ e2lib.join(buildpath, self:get_name()), true)
if not rc then
return false, e:cat(re)
end
return true, nil
end
-function cvs.update(info, sourcename)
- local rc, re, e, src, workdir, argv
+function cvs.cvs_source:update_source()
+ local rc, re, e, workdir, argv
- e = err.new("updating source '%s' failed", sourcename)
- src = source.sources[sourcename]
+ e = err.new("updating source '%s' failed", self._name)
- rc, re = src:working_copy_available()
+ rc, re = self:working_copy_available()
if not rc then
return false, e:cat(re)
end
- workdir = e2lib.join(e2tool.root(), src:get_working())
+ workdir = e2lib.join(e2tool.root(), self:get_working())
argv = { "update", "-R" }
rc, re = cvs_tool(argv, workdir)
return true
end
+--------------------------------------------------------------------------------
+
function cvs.toresult(info, sourcename, sourceset, directory)
-- <directory>/source/<sourcename>.tar.gz
-- <directory>/makefile
return false, re
end
- rc, re = cvs.prepare_source(info, sourcename, sourceset, tmpdir)
+ rc, re = src:prepare_source(sourceset, tmpdir)
if not rc then
return false, e:cat(re)
end
exit = function (ctx) return true end,
}
+--------------------------------------------------------------------------------
+
+--- Generates the command to unpack an archive file.
+-- @param physpath Current location and filename to be unpacked later.
+-- @param virtpath Location and name of the file at the time of unpacking.
+-- @param destdir Path where the unpacked files shall be put.
+-- @return Tool name (string), or false on error.
+-- @return Argument vector table for the tool, or an error object on failure.
+local function gen_unpack_command(physpath, virtpath, destdir)
+
+ --- Determine archive type by looking at the file extension.
+ -- @param filename File name (string).
+ -- @return String constant describing archive,
+ -- or false if archive suffix is unknown.
+ -- @return Error object on failure.
+ local function archive_by_suffix(filename)
+ local name = filename:lower() -- case insensitive matching
+ local atype
+
+ if name:match("%.tar$") then
+ atype = "TAR"
+ elseif name:match("%.tgz") or name:match("%.tar%.gz$") then
+ atype = "TAR_GZ"
+ elseif name:match("%.tar%.bz2$") then
+ atype = "TAR_BZIP2"
+ elseif name:match("%.tar%.xz$") then
+ atype = "TAR_XZ"
+ elseif name:match("%.zip$") then
+ atype = "ZIP"
+ else
+ return false, err.new("can not determine archive type of '%s'",
+ filename)
+ end
+
+ return atype
+ end
+
+ local tool
+ local toolargv = {}
+
+ local atype, re = archive_by_suffix(physpath)
+ if not atype then
+ return false, re
+ end
+
+ if atype == "ZIP" then
+ tool = "unzip"
+ table.insert(toolargv, virtpath)
+ table.insert(toolargv, "-d")
+ table.insert(toolargv, destdir)
+ elseif atype == "TAR" then
+ tool = "tar"
+ table.insert(toolargv, "-C")
+ table.insert(toolargv, destdir)
+ table.insert(toolargv, "-xf")
+ table.insert(toolargv, virtpath)
+ elseif atype == "TAR_GZ" then
+ tool = "tar"
+ table.insert(toolargv, "-z")
+ table.insert(toolargv, "-C")
+ table.insert(toolargv, destdir)
+ table.insert(toolargv, "-xf")
+ table.insert(toolargv, virtpath)
+ elseif atype == "TAR_BZIP2" then
+ tool = "tar"
+ table.insert(toolargv, "-j")
+ table.insert(toolargv, "-C")
+ table.insert(toolargv, destdir)
+ table.insert(toolargv, "-xf")
+ table.insert(toolargv, virtpath)
+ elseif atype == "TAR_XZ" then
+ tool = "tar"
+ table.insert(toolargv, "--xz")
+ table.insert(toolargv, "-C")
+ table.insert(toolargv, destdir)
+ table.insert(toolargv, "-xf")
+ table.insert(toolargv, virtpath)
+ else
+ return false, err.new("unhandled archive type")
+ end
+
+ return tool, toolargv
+end
+
+--- Handle file:copy() in a way that appears intuitive to the user. Returns
+-- a directory and filename that can be passed to eg. mkdir -p and cp.
+-- @param buildpath Base build path (string).
+-- @param sourcename Name of the source (string).
+-- @param copypath Directory or file name where the source file should be
+-- copied to (string).
+-- @param location Soure file location (string).
+-- @param dircheck Check for destination (copypath) being an existing directory.
+-- "yes" enables checking (default), "no" disables the check, and "isdir"
+-- pretends destination is a directory. This flag is useful for collect_project,
+-- where we don't build the source, but just look at its config.
+-- @return Destination directory (string).
+-- @return Destination file name (string).
+local function gen_dest_dir_name(buildpath, sourcename, copypath, location,
+ dircheck)
+
+ dircheck = dircheck or "yes"
+ local destdir, destname
+ local destination = e2lib.join(buildpath, sourcename, copypath)
+
+ -- It may look like ending in a file name ("/foo/bar") - but if
+ -- bar is a directory, we have to copy the file into the
+ -- directory. It's not always possible to check for the destination
+ -- directory. dircheck therefore allows to skip the isdir check, so the
+ -- reults can still be used for code generation.
+
+ if dircheck == "isdir" or
+ (dircheck == "yes" and e2lib.isdir(destination)) then
+ destdir = destination
+ destname = e2lib.basename(location)
+ else
+ -- '.' and '..' are not path components as such, but refer
+ -- to the current and previous directory instead.
+ -- Fixup path by appending a harmless slash, to simplify
+ -- the logic below.
+ local last = e2lib.basename(destination)
+ if last == "." or last == ".." then
+ destination = e2lib.join(destination, "")
+ end
+
+ if string.sub(destination, -1) == "/" then
+ -- destination refers to a directory, indicated by the / at the end
+ -- use destname from location.
+ destdir = destination
+ destname = e2lib.basename(location)
+ else
+ -- destination (potentially) ends with a file name
+ destdir = e2lib.dirname(destination)
+ destname = e2lib.basename(destination)
+ end
+ end
+
+ return destdir, destname
+end
+
+--------------------------------------------------------------------------------
+
files.files_source = class("files_source", source.basic_source)
function files.files_source.static:is_selected_source_class(opts)
return true
end
---------------------------------------------------------------------------------
-
-function files.fetch_source(info, sourcename)
+function files.files_source:fetch_source()
local rc, re
- local src = source.sources[sourcename]
- local e = err.new("fetching source failed: %s", sourcename)
+ local e = err.new("fetching source failed: %s", self._name)
- for file in src:file_iter() do
+ for file in self:file_iter() do
if cache.cache_enabled(cache.cache(), file:server()) then
e2lib.logf(3, "files.fetch_source: caching file %s", file:servloc())
rc, re = cache.fetch_file_path(cache.cache(), file:server(), file:location())
return true
end
---- Handle file:copy() in a way that appears intuitive to the user. Returns
--- a directory and filename that can be passed to eg. mkdir -p and cp.
--- @param buildpath Base build path (string).
--- @param sourcename Name of the source (string).
--- @param copypath Directory or file name where the source file should be
--- copied to (string).
--- @param location Soure file location (string).
--- @param dircheck Check for destination (copypath) being an existing directory.
--- "yes" enables checking (default), "no" disables the check, and "isdir"
--- pretends destination is a directory. This flag is useful for collect_project,
--- where we don't build the source, but just look at its config.
--- @return Destination directory (string).
--- @return Destination file name (string).
-local function gen_dest_dir_name(buildpath, sourcename, copypath, location,
- dircheck)
-
- dircheck = dircheck or "yes"
- local destdir, destname
- local destination = e2lib.join(buildpath, sourcename, copypath)
-
- -- It may look like ending in a file name ("/foo/bar") - but if
- -- bar is a directory, we have to copy the file into the
- -- directory. It's not always possible to check for the destination
- -- directory. dircheck therefore allows to skip the isdir check, so the
- -- reults can still be used for code generation.
-
- if dircheck == "isdir" or
- (dircheck == "yes" and e2lib.isdir(destination)) then
- destdir = destination
- destname = e2lib.basename(location)
- else
- -- '.' and '..' are not path components as such, but refer
- -- to the current and previous directory instead.
- -- Fixup path by appending a harmless slash, to simplify
- -- the logic below.
- local last = e2lib.basename(destination)
- if last == "." or last == ".." then
- destination = e2lib.join(destination, "")
- end
-
- if string.sub(destination, -1) == "/" then
- -- destination refers to a directory, indicated by the / at the end
- -- use destname from location.
- destdir = destination
- destname = e2lib.basename(location)
- else
- -- destination (potentially) ends with a file name
- destdir = e2lib.dirname(destination)
- destname = e2lib.basename(destination)
- end
- end
-
- return destdir, destname
-end
-
---- Determine archive type by looking at the file extension.
--- @param filename File name (string).
--- @return String constant describing archive,
--- or false if archive suffix is unknown.
--- @return Error object on failure.
-local function archive_by_suffix(filename)
- local name = filename:lower() -- case insensitive matching
- local atype
-
- if name:match("%.tar$") then
- atype = "TAR"
- elseif name:match("%.tgz") or name:match("%.tar%.gz$") then
- atype = "TAR_GZ"
- elseif name:match("%.tar%.bz2$") then
- atype = "TAR_BZIP2"
- elseif name:match("%.tar%.xz$") then
- atype = "TAR_XZ"
- elseif name:match("%.zip$") then
- atype = "ZIP"
- else
- return false, err.new("can not determine archive type of '%s'",
- filename)
- end
-
- return atype
-end
-
---- Generates the command to unpack an archive file.
--- @param physpath Current location and filename to be unpacked later.
--- @param virtpath Location and name of the file at the time of unpacking.
--- @param destdir Path where the unpacked files shall be put.
--- @return Tool name (string), or false on error.
--- @return Argument vector table for the tool, or an error object on failure.
-local function gen_unpack_command(physpath, virtpath, destdir)
- local tool
- local toolargv = {}
-
- local atype, re = archive_by_suffix(physpath)
- if not atype then
- return false, re
- end
-
- if atype == "ZIP" then
- tool = "unzip"
- table.insert(toolargv, virtpath)
- table.insert(toolargv, "-d")
- table.insert(toolargv, destdir)
- elseif atype == "TAR" then
- tool = "tar"
- table.insert(toolargv, "-C")
- table.insert(toolargv, destdir)
- table.insert(toolargv, "-xf")
- table.insert(toolargv, virtpath)
- elseif atype == "TAR_GZ" then
- tool = "tar"
- table.insert(toolargv, "-z")
- table.insert(toolargv, "-C")
- table.insert(toolargv, destdir)
- table.insert(toolargv, "-xf")
- table.insert(toolargv, virtpath)
- elseif atype == "TAR_BZIP2" then
- tool = "tar"
- table.insert(toolargv, "-j")
- table.insert(toolargv, "-C")
- table.insert(toolargv, destdir)
- table.insert(toolargv, "-xf")
- table.insert(toolargv, virtpath)
- elseif atype == "TAR_XZ" then
- tool = "tar"
- table.insert(toolargv, "--xz")
- table.insert(toolargv, "-C")
- table.insert(toolargv, destdir)
- table.insert(toolargv, "-xf")
- table.insert(toolargv, virtpath)
- else
- return false, err.new("unhandled archive type")
- end
-
- return tool, toolargv
-end
-
---- Call the patch command
--- @param argv Vector of arguments supplied to patch tool.
--- @return True on success, false on error.
--- @return Error object on failure.
-local function patch_tool(argv)
- return e2lib.call_tool_argv("patch", argv)
+function files.files_source:update_source()
+ return true, nil
end
---- Prepare a files source.
--- @param info The info table.
--- @param sourcename The source name (string)
--- @param sourceset Unused.
--- @param buildpath Base path of the build directory ($T/build) (string).
--- @see toresult
--- @return bool
--- @return nil, maybe an error string on error
-function files.prepare_source(info, sourcename, sourceset, buildpath)
+function files.files_source:prepare_source(sourceset, buildpath)
local rc, re
- local e = err.new("error preparing source: %s", sourcename)
+ local e = err.new("error preparing source: %s", self._name)
local symlink = nil
- local src = source.sources[sourcename]
- for file in src:file_iter() do
+ for file in self:file_iter() do
rc, re = file:checksum_verify()
if not rc then
return false, e:cat(re)
end
if not symlink then
- symlink = buildpath .. "/" .. sourcename
- if file:unpack() ~= sourcename then
+ symlink = buildpath .. "/" .. self._name
+ if file:unpack() ~= self._name then
rc, re = e2lib.symlink(file:unpack(), symlink)
if not rc then
return false, e:cat(re)
end
else
if not symlink then
- symlink = buildpath .. "/" .. sourcename
+ symlink = buildpath .. "/" .. self._name
rc, re = e2lib.mkdir_recursive(symlink)
if not rc then
return false, e:cat(re)
return false, e:append(re)
end
local argv = { "-p", file:patch(), "-d", symlink, "-i", path }
- rc, re = patch_tool(argv)
+ rc, re = e2lib.call_tool_argv("patch", argv)
if not rc then
e:append("applying patch: \"%s\"", file:servloc())
return false, e:cat(re)
end
elseif file:copy() then
local destdir, destname
- destdir, destname = gen_dest_dir_name(buildpath, sourcename,
+ destdir, destname = gen_dest_dir_name(buildpath, self._name,
file:copy(), file:location())
rc, re = e2lib.mkdir_recursive(destdir)
return true, nil
end
+
+--------------------------------------------------------------------------------
+
--- Create a source result containing the generated Makefile and files
-- belonging to the source, for use with collect_project.
-- Result refers to a collection of files to recreate an e2source for
return true
end
---- Update the source.
--- @param info The info table.
--- @param sourcename The name of the source (string).
--- @return Boolean, true on success.
--- @return An error object on failure.
-function files.update(info, sourcename)
- return true, nil
-end
-
strict.lock(files)
-- vim:sw=4:sts=4:et:
return true
end
---------------------------------------------------------------------------------
+function git.git_source:fetch_source()
+ local e, rc, re, git_dir, work_tree, id
---- Return the git commit ID of the specified source configuration. Specific to
--- sources of type git, useful for writing plugins.
--- @param info Info table.
--- @param sourcename Source name.
--- @param sourceset string: the sourceset
--- @param check_remote bool: in tag mode: make sure the tag is available remote
--- @return True on success, false on error.
--- @return Error object on failure.
--- @return Commit ID (string) on success.
-function git.git_commit_id(info, sourcename, sourceset, check_remote)
- local rc, re, e, src, id, fr, gitdir, ref
+ e = err.new("fetching source failed: %s", self._name)
- e = err.new("getting commit ID failed for source: %s", sourcename)
- src = source.sources[sourcename]
+ if self:working_copy_available() then
+ return true
+ end
- rc, re = src:working_copy_available()
+ work_tree = e2lib.join(e2tool.root(), self:get_working())
+ git_dir = e2lib.join(work_tree, ".git")
+
+ e2lib.logf(2, "cloning %s:%s [%s]", self:get_server(), self:get_location(),
+ self:get_branch())
+
+ rc, re = generic_git.git_clone_from_server(cache.cache(), self:get_server(),
+ self:get_location(), work_tree, false --[[always checkout]])
if not rc then
return false, e:cat(re)
end
- rc, re = src:check_workingcopy()
+ rc, re, id = generic_git.lookup_id(git_dir, false,
+ "refs/heads/" .. self:get_branch())
if not rc then
return false, e:cat(re)
- end
-
- gitdir = e2lib.join(e2tool.root(), src:get_working(), ".git")
-
- if sourceset == "branch" or (sourceset == "lazytag" and src:get_tag() == "^") then
- ref = string.format("refs/heads/%s", src:get_branch())
-
- rc, re, id = generic_git.lookup_id(gitdir, false, ref)
+ elseif not id then
+ rc, re = generic_git.git_branch_new1(work_tree, true, self:get_branch(),
+ "origin/" .. self:get_branch())
if not rc then
return false, e:cat(re)
end
- elseif sourceset == "tag" or (sourceset == "lazytag" and src:get_tag() ~= "^") then
- ref = string.format("refs/tags/%s", src:get_tag())
- rc, re, id = generic_git.lookup_id(gitdir, false, ref)
+ rc, re = generic_git.git_checkout1(work_tree,
+ "refs/heads/" .. self:get_branch())
if not rc then
return false, e:cat(re)
end
-
- if id and check_remote then
- rc, re = generic_git.verify_remote_tag(gitdir, src:get_tag())
- if not rc then
- return false, e:cat(re)
- end
- end
- else
- return false, err.new("not an scm sourceset: %s", sourceset)
end
- if not id then
- re = err.new("can't get git commit ID for ref %q from repository %q",
- ref, src:get_working())
- return false, e:cat(re)
- end
-
- return true, nil, id
+ return true
end
--- update a working copy
--- @param info the info structure
--- @param sourcename string
-- @return bool
-- @return an error object
-function git.update(info, sourcename)
- local e, rc, re, src, gitwc, gitdir, argv, id, branch, remote
+function git.git_source:update_source()
+ local e, rc, re, gitwc, gitdir, argv, id, branch, remote
- src = source.sources[sourcename]
- e = err.new("updating source '%s' failed", sourcename)
+ e = err.new("updating source '%s' failed", self._name)
- rc, re = src:working_copy_available()
+ rc, re = self:working_copy_available()
if not rc then
return false, e:cat(re)
end
- e2lib.logf(2, "updating %s [%s]", src:get_working(), src:get_branch())
+ e2lib.logf(2, "updating %s [%s]", self:get_working(), self:get_branch())
- gitwc = e2lib.join(e2tool.root(), src:get_working())
+ gitwc = e2lib.join(e2tool.root(), self:get_working())
gitdir = e2lib.join(gitwc, ".git")
argv = generic_git.git_new_argv(gitdir, gitwc, "fetch")
return true
end
- if branch ~= "refs/heads/" .. src:get_branch() then
+ if branch ~= "refs/heads/" .. self:get_branch() then
e2lib.warnf("WOTHER", "not on configured branch. Skipping.")
return true
end
remote, re = generic_git.git_config(
- gitdir, "branch."..src:get_branch()..".remote")
+ gitdir, "branch."..self:get_branch()..".remote")
if not remote or string.len(remote) == 0 then
e2lib.warnf("WOTHER", "no remote configured for branch %q. Skipping.",
- src:get_branch())
+ self:get_branch())
return true
end
- branch = remote .. "/" .. src:get_branch()
+ branch = remote .. "/" .. self:get_branch()
argv = generic_git.git_new_argv(gitdir, gitwc, "merge", "--ff-only", branch)
rc, re = generic_git.git(argv)
if not rc then
return true
end
---- fetch a git source
--- @param info the info structure
--- @param sourcename string
--- @return bool
--- @return nil on success, an error string on error
-function git.fetch_source(info, sourcename)
- local e, rc, re, src, git_dir, work_tree, id
-
- src = source.sources[sourcename]
- e = err.new("fetching source failed: %s", sourcename)
-
- if src:working_copy_available() then
- return true
- end
-
- work_tree = e2lib.join(e2tool.root(), src:get_working())
- git_dir = e2lib.join(work_tree, ".git")
-
- e2lib.logf(2, "cloning %s:%s [%s]", src:get_server(), src:get_location(),
- src:get_branch())
-
- rc, re = generic_git.git_clone_from_server(cache.cache(), src:get_server(),
- src:get_location(), work_tree, false --[[always checkout]])
- if not rc then
- return false, e:cat(re)
- end
-
- rc, re, id = generic_git.lookup_id(git_dir, false,
- "refs/heads/" .. src:get_branch())
- if not rc then
- return false, e:cat(re)
- elseif not id then
- rc, re = generic_git.git_branch_new1(work_tree, true, src:get_branch(),
- "origin/" .. src:get_branch())
- if not rc then
- return false, e:cat(re)
- end
-
- rc, re = generic_git.git_checkout1(work_tree,
- "refs/heads/" .. src:get_branch())
- if not rc then
- return false, e:cat(re)
- end
- end
-
- return true
-end
-
---- prepare a git source
--- @param info the info structure
--- @param sourcename string
--- @param sourceset
--- @param buildpath
--- @return bool
--- @return nil on success, an error string on error
-function git.prepare_source(info, sourcename, sourceset, buildpath)
+function git.git_source:prepare_source(sourceset, buildpath)
local rc, re, e
- local src, srcdir, destdir
+ local srcdir, destdir, info
- e = err.new("preparing git source %s failed", sourcename)
- src = source.sources[sourcename]
+ e = err.new("preparing git source %s failed", self._name)
- rc, re = scm.generic_source_check(info, sourcename, true)
+ info = e2tool.info()
+ rc, re = scm.generic_source_check(info, self._name, true)
if not rc then
return false, e:cat(re)
end
- srcdir = e2lib.join(e2tool.root(), src:get_working())
- destdir = e2lib.join(buildpath, sourcename)
+ srcdir = e2lib.join(e2tool.root(), self:get_working())
+ destdir = e2lib.join(buildpath, self._name)
rc, re = e2lib.mkdir_recursive(destdir)
if not rc then
if sourceset == "working-copy" then
local empty
- srcdir = e2lib.join(e2tool.root(), src:get_working())
+ srcdir = e2lib.join(e2tool.root(), self:get_working())
empty = true
for f, re in e2lib.directory(srcdir, true) do
end
if empty then
- e2lib.warnf("WOTHER", "in result: %s", sourcename)
+ e2lib.warnf("WOTHER", "in result: %s", self._name)
e2lib.warnf("WOTHER", "working copy seems empty")
end
gitdir = e2lib.join(srcdir, ".git")
- rc, re = git.git_commit_id(info, sourcename, sourceset)
+ rc, re = git.git_commit_id(info, self._name, sourceset)
if not rc then
return false, e:cat(re)
end
table.insert(git_argv, "--format=tar")
if sourceset == "branch" or
- (sourceset == "lazytag" and src:get_tag() == "^") then
- table.insert(git_argv, "refs/heads/" .. src:get_branch())
+ (sourceset == "lazytag" and self:get_tag() == "^") then
+ table.insert(git_argv, "refs/heads/" .. self:get_branch())
elseif sourceset == "tag" or
- (sourceset == "lazytag" and src:get_tag() ~= "^") then
- table.insert(git_argv, "refs/tags/" .. src:get_tag())
+ (sourceset == "lazytag" and self:get_tag() ~= "^") then
+ table.insert(git_argv, "refs/tags/" .. self:get_tag())
else
error(err.new("invalid sourceset: %s", sourceset))
end
return true
end
+
+--------------------------------------------------------------------------------
+
+--- Return the git commit ID of the specified source configuration. Specific to
+-- sources of type git, useful for writing plugins.
+-- @param info Info table.
+-- @param sourcename Source name.
+-- @param sourceset string: the sourceset
+-- @param check_remote bool: in tag mode: make sure the tag is available remote
+-- @return True on success, false on error.
+-- @return Error object on failure.
+-- @return Commit ID (string) on success.
+function git.git_commit_id(info, sourcename, sourceset, check_remote)
+ local rc, re, e, src, id, fr, gitdir, ref
+
+ e = err.new("getting commit ID failed for source: %s", sourcename)
+ src = source.sources[sourcename]
+
+ rc, re = src:working_copy_available()
+ if not rc then
+ return false, e:cat(re)
+ end
+
+ rc, re = src:check_workingcopy()
+ if not rc then
+ return false, e:cat(re)
+ end
+
+ gitdir = e2lib.join(e2tool.root(), src:get_working(), ".git")
+
+ if sourceset == "branch" or (sourceset == "lazytag" and src:get_tag() == "^") then
+ ref = string.format("refs/heads/%s", src:get_branch())
+
+ rc, re, id = generic_git.lookup_id(gitdir, false, ref)
+ if not rc then
+ return false, e:cat(re)
+ end
+ elseif sourceset == "tag" or (sourceset == "lazytag" and src:get_tag() ~= "^") then
+ ref = string.format("refs/tags/%s", src:get_tag())
+
+ rc, re, id = generic_git.lookup_id(gitdir, false, ref)
+ if not rc then
+ return false, e:cat(re)
+ end
+
+ if id and check_remote then
+ rc, re = generic_git.verify_remote_tag(gitdir, src:get_tag())
+ if not rc then
+ return false, e:cat(re)
+ end
+ end
+ else
+ return false, err.new("not an scm sourceset: %s", sourceset)
+ end
+
+ if not id then
+ re = err.new("can't get git commit ID for ref %q from repository %q",
+ ref, src:get_working())
+ return false, e:cat(re)
+ end
+
+ return true, nil, id
+end
+
function git.toresult(info, sourcename, sourceset, directory)
local rc, re, argv
local e = err.new("converting result")
local licence = require("licence")
local scm = require("scm")
local source = require("source")
+local strict = require("strict")
local url = require("url")
local gitrepo_source = class("gitrepo_source", source.basic_source)
return true
end
---------------------------------------------------------------------------------
+function gitrepo_source:fetch_source()
+ local e, rc, re, git_dir, work_tree, id
---- Fetch a gitrepo source. Adapted from git plugin.
--- @param info the info structure
--- @param sourcename string
--- @return bool
--- @return true on success, an error string on error
-function gitrepo.fetch_source(info, sourcename)
- assertIsTable(info)
- assertIsStringN(sourcename)
-
- local e, rc, re, src, git_dir, work_tree, id
-
- src = source.sources[sourcename]
- e = err.new("fetching source failed: %s", sourcename)
+ e = err.new("fetching source failed: %s", self._name)
- if src:working_copy_available() then
+ if self:working_copy_available() then
return true
end
- work_tree = e2lib.join(e2tool.root(), src:get_working())
+ work_tree = e2lib.join(e2tool.root(), self:get_working())
git_dir = e2lib.join(work_tree, ".git")
- e2lib.logf(2, "cloning %s:%s [%s]", src:get_server(), src:get_location(),
- src:get_branch())
+ e2lib.logf(2, "cloning %s:%s [%s]", self:get_server(), self:get_location(),
+ self:get_branch())
- rc, re = generic_git.git_clone_from_server(cache.cache(), src:get_server(),
- src:get_location(), work_tree, false --[[always checkout]])
+ rc, re = generic_git.git_clone_from_server(cache.cache(), self:get_server(),
+ self:get_location(), work_tree, false --[[always checkout]])
if not rc then
return false, e:cat(re)
end
rc, re, id = generic_git.lookup_id(git_dir, false,
- "refs/heads/" .. src:get_branch())
+ "refs/heads/" .. self:get_branch())
if not rc then
return false, e:cat(re)
elseif not id then
- rc, re = generic_git.git_branch_new1(work_tree, true, src:get_branch(),
- "origin/" .. src:get_branch())
+ rc, re = generic_git.git_branch_new1(work_tree, true, self:get_branch(),
+ "origin/" .. self:get_branch())
if not rc then
return false, e:cat(re)
end
rc, re = generic_git.git_checkout1(work_tree,
- "refs/heads/" .. src:get_branch())
+ "refs/heads/" .. self:get_branch())
if not rc then
return false, e:cat(re)
end
return true
end
---- prepare a git source
--- @param info the info structure
--- @param sourcename string
+--- update a working copy
+-- @return bool
+-- @return an error object
+function gitrepo_source:update_source()
+ local e, rc, re, gitwc, gitdir, argv, id, branch, remote
+
+ e = err.new("updating source '%s' failed", self._name)
+
+ rc, re = scm.generic_source_check(e2tool.info(), self._name, true)
+ if not rc then
+ return false, e:cat(re)
+ end
+
+ e2lib.logf(2, "updating %s [%s]", self:get_working(), self:get_branch())
+
+ gitwc = e2lib.join(e2tool.root(), self:get_working())
+ gitdir = e2lib.join(gitwc, ".git")
+
+ argv = generic_git.git_new_argv(gitdir, gitwc, "fetch")
+ rc, re = generic_git.git(argv)
+ if not rc then
+ return false, e:cat(re)
+ end
+
+ argv = generic_git.git_new_argv(gitdir, gitwc, "fetch", "--tags")
+ rc, re = generic_git.git(argv)
+ if not rc then
+ return false, e:cat(re)
+ end
+
+ -- Use HEAD commit ID to find the branch we're on
+ rc, re, id = generic_git.lookup_id(gitdir, false, "HEAD")
+ if not rc then
+ return false, e:cat(re)
+ elseif not id then
+ return false, e:cat(err.new("can not find commit ID for HEAD"))
+ end
+
+ rc, re, branch = generic_git.lookup_ref(gitdir, false, id, "refs/heads/")
+ if not rc then
+ return false, e:cat(re)
+ elseif not branch then
+ e2lib.warnf("WOTHER", "HEAD is not on a branch (detached?). Skipping")
+ return true
+ end
+
+ if branch ~= "refs/heads/" .. self:get_branch() then
+ e2lib.warnf("WOTHER", "not on configured branch. Skipping.")
+ return true
+ end
+
+ remote, re = generic_git.git_config(
+ gitdir, "branch."..self:get_branch()..".remote")
+ if not remote or string.len(remote) == 0 then
+ e2lib.warnf("WOTHER", "no remote configured for branch %q. Skipping.",
+ self:get_branch())
+ return true
+ end
+
+ branch = remote .. "/" .. self:get_branch()
+ argv = generic_git.git_new_argv(gitdir, gitwc, "merge", "--ff-only", branch)
+ rc, re = generic_git.git(argv)
+ if not rc then
+ return false, e:cat(re)
+ end
+
+ return true
+end
+
+--- prepare source for building.
-- @param sourceset can be either:
-- "tag": the git repository will be checked out to the tag
-- "branch": the git repository will be checked out to the branch
-- @param buildpath the path where the source will be created
-- @return True on success, false on failure.
-- @return Error object on failure.
-function gitrepo.prepare_source(info, sourcename, sourceset, buildpath)
- assertIsTable(info)
- assertIsStringN(sourcename)
+function gitrepo_source:prepare_source(sourceset, buildpath)
assertIsStringN(sourceset)
assertIsStringN(buildpath)
local rc, re, e
- local src, argv, destdir, worktree, ref
+ local argv, destdir, worktree, ref
- e = err.new("preparing source failed: %s", sourcename)
- src = source.sources[sourcename]
+ e = err.new("preparing source failed: %s", self._name)
- rc, re = scm.generic_source_check(info, sourcename, true)
+ rc, re = scm.generic_source_check(e2tool.info(), self._name, true)
if not rc then
return false, e:cat(re)
end
if sourceset == "tag" or sourceset == "branch" then
- destdir = e2lib.join(buildpath, sourcename, ".git")
+ destdir = e2lib.join(buildpath, self._name, ".git")
rc, re = e2lib.mkdir_recursive(destdir)
if not rc then
return false, e:cat(re)
end
- worktree = e2lib.join(e2tool.root(), src:get_working())
+ worktree = e2lib.join(e2tool.root(), self:get_working())
argv = generic_git.git_new_argv(false, false, "clone",
"--mirror", worktree, destdir)
rc, re = generic_git.git(argv)
end
if sourceset == "tag" then
- ref = string.format("refs/tags/%s", src:get_tag())
+ ref = string.format("refs/tags/%s", self:get_tag())
else
- ref = string.format("refs/heads/%s", src:get_branch())
+ ref = string.format("refs/heads/%s", self:get_branch())
end
rc, re = generic_git.git_checkout1(e2lib.join(destdir, ".."), ref)
elseif sourceset == "working-copy" then
local argv = {
"-a",
- e2lib.join(e2tool.root(), src:get_working(), ""),
- e2lib.join(buildpath, sourcename),
+ e2lib.join(e2tool.root(), self:get_working(), ""),
+ e2lib.join(buildpath, self._name),
}
rc, re = e2lib.rsync(argv)
if not rc then
end
else
return false, err.new("preparing source failed, not a valid type: %s, %s",
- sourcename, sourceset)
+ self._name, sourceset)
end
return true
end
---- update a working copy. from git plugin
--- @param info the info structure
--- @param sourcename string
--- @return bool
--- @return an error object
-function gitrepo.update(info, sourcename)
- local e, rc, re, src, gitwc, gitdir, argv, id, branch, remote
-
- src = source.sources[sourcename]
- e = err.new("updating source '%s' failed", sourcename)
-
- rc, re = scm.generic_source_check(info, sourcename, true)
- if not rc then
- return false, e:cat(re)
- end
-
- e2lib.logf(2, "updating %s [%s]", src:get_working(), src:get_branch())
-
- gitwc = e2lib.join(e2tool.root(), src:get_working())
- gitdir = e2lib.join(gitwc, ".git")
-
- argv = generic_git.git_new_argv(gitdir, gitwc, "fetch")
- rc, re = generic_git.git(argv)
- if not rc then
- return false, e:cat(re)
- end
-
- argv = generic_git.git_new_argv(gitdir, gitwc, "fetch", "--tags")
- rc, re = generic_git.git(argv)
- if not rc then
- return false, e:cat(re)
- end
-
- -- Use HEAD commit ID to find the branch we're on
- rc, re, id = generic_git.lookup_id(gitdir, false, "HEAD")
- if not rc then
- return false, e:cat(re)
- elseif not id then
- return false, e:cat(err.new("can not find commit ID for HEAD"))
- end
-
- rc, re, branch = generic_git.lookup_ref(gitdir, false, id, "refs/heads/")
- if not rc then
- return false, e:cat(re)
- elseif not branch then
- e2lib.warnf("WOTHER", "HEAD is not on a branch (detached?). Skipping")
- return true
- end
-
- if branch ~= "refs/heads/" .. src:get_branch() then
- e2lib.warnf("WOTHER", "not on configured branch. Skipping.")
- return true
- end
-
- remote, re = generic_git.git_config(
- gitdir, "branch."..src:get_branch()..".remote")
- if not remote or string.len(remote) == 0 then
- e2lib.warnf("WOTHER", "no remote configured for branch %q. Skipping.",
- src:get_branch())
- return true
- end
-
- branch = remote .. "/" .. src:get_branch()
- argv = generic_git.git_new_argv(gitdir, gitwc, "merge", "--ff-only", branch)
- rc, re = generic_git.git(argv)
- if not rc then
- return false, e:cat(re)
- end
-
- return true
-end
+--------------------------------------------------------------------------------
--- Archives the source and prepares the necessary files outside the archive
-- @param info the info structure
--------------------------------------------------------------------------------
-return gitrepo
+return strict.lock(gitrepo)
-- vim:sw=4:sts=4:et:
return true
end
---------------------------------------------------------------------------------
-
-function svn.fetch_source(info, sourcename)
+function svn.svn_source:fetch_source()
local rc, re
- local e = err.new("fetching source failed: %s", sourcename)
- local src = source.sources[sourcename]
- local location = src:get_location()
- local server = src:get_server()
- local surl, re = cache.remote_url(cache.cache(), server, location)
+ local e = err.new("fetching source failed: %s", self._name)
+ local surl, re = cache.remote_url(cache.cache(), self._server, self._location)
if not surl then
return false, e:cat(re)
end
return false, e:cat(re)
end
- if src:working_copy_available() then
+ if self:working_copy_available() then
return true
end
- local argv = { "checkout", svnurl, e2tool.root() .. "/" .. src:get_working() }
+ local argv = { "checkout", svnurl, e2tool.root() .. "/" .. self:get_working() }
rc, re = svn_tool(argv)
if not rc then
return true
end
-function svn.prepare_source(info, sourcename, sourceset, build_path)
+function svn.svn_source:update_source()
local rc, re
- local e = err.new("svn.prepare_source failed")
- local src = source.sources[sourcename]
- local location = src:get_location()
- local server = src:get_server()
- local surl, re = cache.remote_url(cache.cache(), server, location)
+ local e = err.new("updating source '%s' failed", self._name)
+ local workdir = e2lib.join(e2tool.root(), self:get_working())
+ rc, re = svn_tool({ "update" }, workdir)
+ if not rc then
+ return false, e:cat(re)
+ end
+ return true
+end
+
+function svn.svn_source:prepare_source(sourceset, buildpath)
+ local rc, re
+ local e = err.new("preparing source for build failed: %s", self._name)
+ local surl, re = cache.remote_url(cache.cache(), self._server, self._location)
if not surl then
return false, e:cat(re)
end
if sourceset == "tag" or sourceset == "branch" then
local rev
if sourceset == "tag" then
- rev = src:get_tag()
+ rev = self._tag
else -- sourceset == "branch"
- rev = src:get_branch()
+ rev = self._branch
end
local argv = { "export", svnurl .. "/" .. rev,
- build_path .. "/" .. sourcename }
+ buildpath .. "/" .. self._name }
rc, re = svn_tool(argv)
if not rc then
return false, e:cat(re)
end
elseif sourceset == "working-copy" then
- -- cp -R e2tool.root()/src.working/src.workingcopy_subdir build_path
- local s = e2lib.join(e2tool.root(), src:get_working(),
- src:get_workingcopy_subdir())
- local d = e2lib.join(build_path, src:get_name())
+ local s = e2lib.join(e2tool.root(), self:get_working(),
+ self:get_workingcopy_subdir())
+ local d = e2lib.join(buildpath, self._name)
rc, re = e2lib.cp(s, d, true)
if not rc then
return false, e:cat(re)
else
return false, e:cat("invalid source set")
end
- return true, nil
+ return true
end
+--------------------------------------------------------------------------------
+
function svn.toresult(info, sourcename, sourceset, directory)
-- <directory>/source/<sourcename>.tar.gz
-- <directory>/makefile
return false, e:cat(re)
end
- rc, re = svn.prepare_source(info, sourcename, sourceset, tmpdir)
+ rc, re = src:prepare_source(sourceset, tmpdir)
if not rc then
return false, e:cat(re)
end
return true, nil
end
-function svn.update(info, sourcename)
- local rc, re
- local e = err.new("updating source '%s' failed", sourcename)
- local src = source.sources[sourcename]
- local workdir = e2lib.join(e2tool.root(), src:get_working())
- rc, re = svn_tool({ "update" }, workdir)
- if not rc then
- return false, e:cat(re)
- end
- return true
-end
-
strict.lock(svn)
-- vim:sw=4:sts=4:et: