]> git.e2factory.org Git - e2factory.git/commitdiff
cleanup: refactor scm related code.
authorGordon Hecker <gh@emlix.com>
Thu, 21 Jan 2010 17:17:57 +0000 (18:17 +0100)
committerGordon Hecker <gh@emlix.com>
Fri, 12 Feb 2010 09:51:59 +0000 (10:51 +0100)
The e2scm module was renamed to scm and code size was reduced by 75 percent
by unifying interfaces.
The following modules were turned into proper lua modules:
* scm (e2scm)
* files
* git
* svn
* cvs

Signed-off-by: Gordon Hecker <gh@emlix.com>
local/Makefile
local/cvs.lua
local/e2scm.lua [deleted file]
local/e2tool.lua
local/fetch-sources.lua
local/files.lua
local/git.lua
local/scm.lua [new file with mode: 0644]
local/svn.lua

index 26a4190fe3deea6b15e99e74fc83c07f80a0709b..5899a86df7a26f6abab51f408dd48f69ae298d15 100644 (file)
@@ -43,7 +43,7 @@ LOCALLUATOOLS = \
        playground build-numbers cf
 LOCALSHTOOLS =
 LUA_LIBS = e2option.lua luafile.lua generic_git.lua err.lua
-LUA_LIBS += e2tool.lua
+LUA_LIBS += e2tool.lua scm.lua git.lua svn.lua cvs.lua files.lua
 LOCALTOOLS = $(LOCALSHTOOLS) $(LOCALLUATOOLS)
 
 SYMLINKS_2_1 = lookup-server use-source prepare-cargo sync-results cleanup \
@@ -127,7 +127,6 @@ e2local.lc: strict.lua \
                url.lua \
                collection.lua \
                e2lib.lua \
-               e2scm.lua git.lua svn.lua cvs.lua files.lua \
                hash.lua \
                lock.lua \
                e2build.lua \
index 629be7e00d79921f2ce668c4b92a202f1724180d..08964dc986a1248435cd1a7d869c4136f3123b3b 100644 (file)
 
 -- cvs.lua - CVS-specific SCM operations -*- Lua -*-
 --
--- See e2scm.lua for more information about these operations.
---
--- A "cvs" source description file "src" has this content:
---
--- <server> <remote> <working> <branch> <tag>
---
--- Restrictions:
---
--- * the working copy directory must have the same basename as
---   the CVS module name
--- * branches are not supported, yet
---
--- This code has only been tested superficially.
-
-
-local cvs = {}
+module("cvs", package.seeall)
+require("scm")
 
 --- validate source configuration, log errors to the debug log
 -- @param info the info table
 -- @param sourcename the source name
 -- @return bool
 function cvs.validate_source(info, sourcename)
-  local rc, re = generic_validate_source(info, sourcename)
+  local rc, re = git.generic_validate_source(info, sourcename)
   if not rc then
     -- error in generic configuration. Don't try to go on.
     return false, re
@@ -59,7 +45,7 @@ function cvs.validate_source(info, sourcename)
     src.sourceid = {}
   end
   local e = new_error("in source %s:", sourcename)
-  rc, re = source_apply_default_working(info, sourcename)
+  rc, re = git.source_apply_default_working(info, sourcename)
   if not rc then
     return false, e:cat(re)
   end
@@ -329,7 +315,7 @@ function cvs.sourceid(info, sourcename, source_set)
                src.sourceid[source_set] = "working-copy"
        end
        if src.sourceid[source_set] then
-               return src.sourceid[source_set]
+               return true, nil, src.sourceid[source_set]
        end
        local e = new_error("calculating sourceid failed for source %s", 
                                                                sourcename)
@@ -340,7 +326,7 @@ function cvs.sourceid(info, sourcename, source_set)
                hash.hash_line(hc, l)
                local licenceid, re = e2tool.licenceid(info, l)
                if not licenceid then
-                       return nil, re
+                       return false, re
                end
                hash.hash_line(hc, licenceid)
        end
@@ -362,7 +348,7 @@ function cvs.sourceid(info, sourcename, source_set)
        -- skip src.working
        e2lib.logf(4, "hash data for source %s\n%s", src.name, hc.data)
        src.sourceid[source_set] = hash.hash_finish(hc)
-       return src.sourceid[source_set], nil
+       return true, nil, src.sourceid[source_set]
 end
 
 function cvs.toresult(info, sourcename, sourceset, directory)
@@ -371,7 +357,7 @@ function cvs.toresult(info, sourcename, sourceset, directory)
        -- <directory>/licences
        local rc, re
        local e = new_error("converting result")
-       rc, re = check(info, sourcename, true)
+       rc, re = git.check(info, sourcename, true)
        if not rc then
                return false, e:cat(re)
        end
@@ -442,4 +428,4 @@ function cvs.check_workingcopy(info, sourcename)
        return true, nil
 end
 
-e2scm.register("cvs", cvs)
+scm.register("cvs", cvs)
diff --git a/local/e2scm.lua b/local/e2scm.lua
deleted file mode 100644 (file)
index d10d71f..0000000
+++ /dev/null
@@ -1,420 +0,0 @@
---[[
-   e2factory, the emlix embedded build system
-
-   Copyright (C) 2007-2009 Gordon Hecker <gh@emlix.com>, emlix GmbH
-   Copyright (C) 2007-2009 Oskar Schirmer <os@emlix.com>, emlix GmbH
-   Copyright (C) 2007-2008 Felix Winkelmann, emlix GmbH
-   
-   For more information have a look at http://www.e2factory.org
-
-   e2factory is a registered trademark by emlix GmbH.
-
-   This file is part of e2factory, the emlix embedded build system.
-   
-   e2factory is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-   
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-   
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-]]
-
--- e2scm.lua - SCM-specific functionality -*- Lua -*-
-
-
-e2scm = e2lib.module("e2scm")
-
-
--- General SCM wrapping
---
--- SCM-specific functions are implemented as sub-tables of the "e2scm"
--- namespace and calls to "e2scm.<SCM>.<op>(...)" are simply passed
--- to the SCM specific entries (after checking whether such an operation
--- exists for the selected SCM).
---
---   e2scm.register(SCMNAME, [TABLE]) -> TABLE
---
---     Registers an SCM with the given name and creates the namespace and
---     returns it (to be filled with operations). If a table is given as
---     argument, then the argument table is used instead of creating a
---     fresh one.
---
---   e2scm.register_op(OPNAME, DOC)
---
---     Registers SCM operation with documentation string.
---
-
-local scms = {}
-local ops = {}
-local scmmt = {}
-
-function scmmt.__index(t, k)
-  local doc = ops[ k ] or 
-    e2lib.bomb("invalid SCM operation `" .. k .. "'")
-  local x = rawget(t, k)
-  return x or e2lib.abort("`" .. t.name .. "' can not " .. ops[ k ])
-end
-
-function e2scm.register(scm, t)
-  t = t or {}
-  t.name = scm
-  scms[ scm ] = t
-  return t
-end
-
-function e2scm.register_op(op, doc)
-  ops[ op ] = doc
-end
-
-function e2scm.registered(scm)
-  return scms[ scm ]
-end
-
--- iterate over registrated scm, include "files" when all is true
-function e2scm.iteratescms(all)
-  local k = nil
-  local t = scms
-  local function nextscm(t)
-    k = next(t, k)
-    if k == "files" and not all then k = next(t, k) end
-    return k
-  end
-  return nextscm, t
-end
-
--- for all scms, add an options flag
-function e2scm.optionsaddflags(all, text)
-  local t = text or "use"
-  for scm in e2scm.iteratescms(all) do
-    e2option.flag(scm, t .. " source of type '" .. scm .. "'")
-  end
-end
-
--- with options parsed, see which flag has been given with the options
-function e2scm.optionswhichflag(options, default)
-  local f = nil
-  for scm in e2scm.iteratescms(true) do
-    if options[scm] then
-      f = f and e2lib.abort("scm type flags to be used exclusively") or scm
-    end
-  end
-  return f or default or e2lib.abort("no scm type flag given")
-end
-
-local mt = {}
-
-function mt.__index(t, k)
-  local scm = scms[ k ]
-  return scm or e2lib.bomb("no SCM is registered under the name `" .. k .. "'")
-end
-
-setmetatable(e2scm, mt)
-
-scm = {}
-
-local function sourcebyname(info, sourcename)
-       local s = info.sources[sourcename]
-       if not s then
-               return nil, new_error("no source by that name: %s", sourcename)
-       end
-       return s, nil
-end
-
---- calculate and return the sourceid
--- @param info
--- @param sourcename
--- @param sourceset string: source set
--- @return string: the sourceid, or nil
--- @return an error object on failure
-function scm.sourceid(info, sourcename, sourceset)
-       local src = sourcebyname(info, sourcename)
-       local rc, re, e
-       e = new_error("getting sourceid failed")
-       if not e2scm[src.type] then
-               return false, e:append("no such source type: %s", src.type)
-       end
-       if not e2scm[src.type].sourceid then
-               e:append("sourceid not implemented for source type: %s",
-                                                               src.type)
-               return false, e
-       end
-       local sourceid
-       sourceid, re = e2scm[src.type].sourceid(info, sourcename, sourceset)
-       if not sourceid then
-               return nil, re
-       end
-       return sourceid, nil
-end
-
---- validate a source configuration
--- @param info
--- @param sourcename
--- @return bool
--- @return an error object on failure
-function scm.validate_source(info, sourcename)
-       local src = info.sources[sourcename]
-       local rc, re, e
-       e = new_error("validating source failed")
-       if not e2scm[src.type] then
-               return false, e:append("no such source type: %s", src.type)
-       end
-       if not e2scm[src.type].validate_source then
-               e:append("validate_source not implemented for source type: %s",
-                                                               src.type)
-               return false, e
-       end
-       rc, re = e2scm[src.type].validate_source(info, sourcename)
-       if not rc then
-               return false, re
-       end
-       return true, nil
-end
-
---- create a result from a source
--- @param info
--- @param sourcename
--- @param sourceset string: source set
--- @param directory string: destination path to create the result
--- @return bool
--- @return an error object on failure
-function scm.toresult(info, sourcename, sourceset, directory)
-       -- create in directory the following structure:
-       -- ./makefile
-       -- ./source/<files>
-       -- ./licences/<files>.licences   -- a list of licences per file
-       --          ...
-       local src = info.sources[sourcename]
-       local rc, re, e
-       e = new_error("calling scm operation failed")
-       if not e2scm[src.type] then
-               return false, e:append("no such source type: %s", src.type)
-       end
-       if not e2scm[src.type].toresult then
-               e:append("toresult not implemented for source type: %s",
-                                                               src.type)
-               return false, e
-       end
-       local rc, re = e2scm[src.type].toresult(info, sourcename, 
-                                               sourceset, directory)
-       if not rc then
-               return false, re
-       end
-       return true, nil
-end
-
---- prepare a source for building
--- @param info
--- @param sourcename
--- @param sourceset string: source set
--- @param buildpath string: destination path
--- @return bool
--- @return an error object on failure
-function scm.prepare_source(info, sourcename, sourceset, buildpath)
-       local src = info.sources[sourcename]
-       local rc, re, e
-       e = new_error("calling scm operation failed")
-       if not e2scm[src.type] then
-               return false, e:append("no such source type: %s", src.type)
-       end
-       if not e2scm[src.type].prepare_source then
-               e:append("prepare_source not implemented for source type: %s",
-                                                               src.type)
-               return false, e
-       end
-       rc, re = e2scm[src.type].prepare_source(info, sourcename, sourceset,
-                                                               buildpath)
-       if not rc then
-               return false, re
-       end
-       return true, nil
-end
-
---- fetch a source
--- @param info
--- @param sourcename
--- @return bool
--- @return an error object on failure
-function scm.fetch_source(info, sourcename)
-       local src = info.sources[sourcename]
-       local rc, re, e
-       e = new_error("calling scm operation failed")
-       if not e2scm[src.type] then
-               return false, e:append("no such source type: %s", src.type)
-       end
-       if not e2scm[src.type].fetch_source then
-               e:append("fetch_source not implemented for source type: %s",
-                                                               src.type)
-               return false, e
-       end
-       rc, re = e2scm[src.type].fetch_source(info, sourcename)
-       if not rc then
-               return false, re
-       end
-       return true, nil
-end
-
---- update a source
--- @param info
--- @param sourcename
--- @return bool
--- @return an error object on failure
-function scm.update(info, sourcename)
-       local src = info.sources[sourcename]
-       local rc, re, e
-       e = new_error("calling scm operation failed")
-       if not e2scm[src.type] then
-               return false, e:append("no such source type: %s", src.type)
-       end
-       if not e2scm[src.type].update then
-               e:append("update not implemented for source type: %s",
-                                                               src.type)
-               return false, e
-       end
-       rc, re = e2scm[src.type].update(info, sourcename)
-       if not rc then
-               return false, re
-       end
-       return true, nil
-end
-
---- sanity check a working copy
--- @param info
--- @param sourcename
--- @return bool
--- @return an error object on failure
-function scm.check_workingcopy(info, sourcename)
-       local src = info.sources[sourcename]
-       local rc, re, e
-       e = new_error("calling scm operation failed")
-       if not e2scm[src.type] then
-               return false, e:append("no such source type: %s", src.type)
-       end
-       if not e2scm[src.type].check_workingcopy then
-               e:append(
-                   "check_workingcopy not implemented for source type: %s",
-                                                               src.type)
-               return false, e
-       end
-       rc, re = e2scm[src.type].check_workingcopy(info, sourcename)
-       if not rc then
-               return false, re
-       end
-       return true, nil
-end
-
---- check if a working copy is available
--- @param info
--- @param sourcename
--- @return bool
--- @return an error object on failure
-function scm.working_copy_available(info, sourcename)
-       local src = info.sources[sourcename]
-       local rc, re, e
-       e = new_error("calling scm operation failed")
-       if not e2scm[src.type] then
-               return false, e:append("no such source type: %s", src.type)
-       end
-       if not e2scm[src.type].working_copy_available then
-               e:append(
-                       "working_copy_available not implemented for source "..
-                       "type: %s", src.type)
-               return false, e
-       end
-       rc, re = e2scm[src.type].working_copy_available(info, sourcename)
-       if not rc then
-               return false, re
-       end
-       return true, nil
-end
-
---- create a table of lines for display
--- @param info
--- @param sourcename
--- @return a table
--- @return an error object on failure
-function scm.display(info, sourcename)
-       local src = info.sources[sourcename]
-       local rc, re, e
-       e = new_error("calling scm operation failed")
-       if not e2scm[src.type] then
-               return false, e:append("no such source type: %s", src.type)
-       end
-       if not e2scm[src.type].display then
-               e:append(
-                       "display not implemented for source "..
-                       "type: %s", src.type)
-               return false, e
-       end
-       rc, re = e2scm[src.type].display(info, sourcename)
-       if not rc then
-               return nil, re
-       end
-       return rc, nil
-end
-
---- check if this scm type supports a working copy
--- @param info
--- @param sourcename
--- @return a table
--- @return an error object on failure
-function scm.has_working_copy(info, sourcename)
-       local src = info.sources[sourcename]
-       local rc, re, e
-       e = new_error("calling scm operation failed")
-       if not e2scm[src.type] then
-               return false, e:append("no such source type: %s", src.type)
-       end
-       if not e2scm[src.type].has_working_copy then
-               e:append(
-                       "has_working_copy not implemented for source "..
-                       "type: %s", src.type)
-               return false, e
-       end
-       rc, re = e2scm[src.type].has_working_copy(info, sourcename)
-       if not rc then
-               return false, re
-       end
-       return true, nil
-end
-
---- register a new scm interface
--- @param name string: interface name
--- @param func function: interface function
--- @return bool
--- @return an error object on failure
-function scm.register_interface(name, func)
-  local e = new_error("registering scm interface failed")
-  if scm[name] then
-    return false, e:append(
-               "interface with that name exists: %s", name)
-  end
-  scm[name] = func
-  return true, nil
-end
-
---- register a new scm function (accessible through a scm interface)
--- @param type string: scm type
--- @param name string: interface name
--- @param func function: interface function
--- @return bool
--- @return an error object on failure
-function scm.register_function(type, name, func)
-  local e = new_error("registering scm function failed")
-  if not e2scm[type] then
-    return false, e:append("no scm type by that name: %s", type)
-  end
-  if not scm[name] then
-    return false, e:append("no scm interface by that name: %s", name)
-  end
-  if e2scm[type][name] then
-    return false, e:append("scm function exists: %s.%s", type, name)
-  end
-  scms[type][name] = func
-  return true, nil
-end
index 10654c412a7c9fa6d953420eacb07b7cb86e9881..166618f1989089489dd5b9fb284b06330680553f 100644 (file)
 -- High-level tools used by the build process and basic build operations.
 
 module("e2tool", package.seeall)
+require("scm")
+require("files")
+require("git")
+require("cvs")
+require("svn")
 
 -- Information gathering and inquiry
 --
@@ -1410,9 +1415,9 @@ function pbuildid(info, resultname)
        for _,s in ipairs(r.sources) do
                local src = info.sources[s]
                local source_set = r.build_mode.source_set()
-               local sourceid, re = 
+               local rc, re, sourceid =
                                scm.sourceid(info, s, source_set)
-               if not sourceid then
+               if not rc then
                        return nil, e:cat(re)
                end
                hash.hash_line(hc, s)                   -- source name
@@ -1623,10 +1628,6 @@ function check_source(info, sourcename)
                e2lib.warnf("WDEFAULT", " type attribute defaults to `files'")
                src.type = "files"
        end
-       if not e2scm[src.type] then
-               e:append("unknown scm type: %s", src.type)
-               return false, e
-       end
        rc, re = scm.validate_source(info, sourcename)
        if not rc then
                return false, re
index d85baa1c810b27d5e0de56c74496a3515cd6bd8b..37320ac1e8741498ed132becfc3913526f0dbfef 100755 (executable)
@@ -140,7 +140,7 @@ function fetch_sources(info, opts, sel)
   -- fetch
   for _, s in pairs(info.sources) do
     local has_wc = scm.has_working_copy(info, s.name)
-    local wc_avail = e2scm[s.type].working_copy_available(info, s.name)
+    local wc_avail = scm.working_copy_available(info, s.name)
     if opts.fetch and sel[s.name] then
       if wc_avail then
         e2lib.log(1, "working copy for " .. s.name .. " is already available")
@@ -159,7 +159,7 @@ function fetch_sources(info, opts, sel)
   -- update
   for _, s in pairs(info.sources) do
     local has_wc = scm.has_working_copy(info, s.name)
-    local wc_avail = e2scm[s.type].working_copy_available(info, s.name)
+    local wc_avail = scm.working_copy_available(info, s.name)
     if opts.update and has_wc and sel[s.name] then
       if not wc_avail then
         e2lib.log(1, string.format("working copy for %s is not available",
index 9f29a74eccb014cf51844ebc7a287a2eeb71859c..0bedde8d08e37e2b02f5d81553d701dfc754f96c 100644 (file)
@@ -29,8 +29,8 @@
 --
 -- See e2scm.lua for more information about these operations.
 
-
-local files = {}
+module("files", package.seeall)
+require("scm")
 
 --- validate source configuration, log errors to the debug log
 -- @param info the info table
@@ -38,7 +38,7 @@ local files = {}
 -- @return bool
 function files.validate_source(info, sourcename)
   local rc1 = true   -- the return value
-  local rc, e = generic_validate_source(info, sourcename)
+  local rc, e = git.generic_validate_source(info, sourcename)
   if not rc then
     return false, e
   end
@@ -317,7 +317,7 @@ function files.sourceid(info, sourcename, sourceset)
        end
        local src = info.sources[sourcename]
        if src.sourceid then
-               return src.sourceid
+               return true, nil, src.sourceid
        end
        -- sourceset is ignored for files sources
        local hc = hash.hash_start()
@@ -327,7 +327,7 @@ function files.sourceid(info, sourcename, sourceset)
                hash.hash_line(hc, l)
                local licenceid, re = e2tool.licenceid(info, l)
                if not licenceid then
-                       return nil, re
+                       return false, re
                end
                hash.hash_line(hc, licenceid)
        end
@@ -346,7 +346,7 @@ function files.sourceid(info, sourcename, sourceset)
        e2lib.log(4, string.format("hash data for source %s\n%s", src.name, 
                                                                hc.data))
        src.sourceid = hash.hash_finish(hc)
-       return src.sourceid
+       return true, nil, src.sourceid
 end
 
 -- export the source to a result structure
@@ -443,4 +443,8 @@ function files.check_workingcopy(info, sourcename)
        return true, nil
 end
 
-e2scm.register("files", files)
+function files.update(info, sourcename)
+       return true, nil
+end
+
+scm.register("files", files)
index 2470f6f16eb1b9823f77311a69b7f792a15f32ea..bb968883dbcedd2a6eb716dd2558b619ab31a0d1 100644 (file)
@@ -29,7 +29,8 @@
 --
 -- See e2scm.lua for more information about these operations.
 
-local git = {}
+module("git", package.seeall)
+require("scm")
 
 --- git branch wrapper
 -- get the current branch
@@ -656,12 +657,12 @@ function git.sourceid(info, sourcename, sourceset)
                src.commitid = {}
        end
        if src.sourceid[sourceset] then
-               return src.sourceid[sourceset]
+               return true, nil, src.sourceid[sourceset]
        end
        src.commitid[sourceset], e = git.get_revision_id(info, sourcename,
                                sourceset, e2option.opts["check-remote"])
        if not src.commitid[sourceset] then
-               return nil, e
+               return false, e
        end
        local hc = hash.hash_start()
        hash.hash_line(hc, src.name)
@@ -670,7 +671,7 @@ function git.sourceid(info, sourcename, sourceset)
                hash.hash_line(hc, l)
                local licenceid, re = e2tool.licenceid(info, l)
                if not licenceid then
-                       return nil, re
+                       return false, re
                end
                hash.hash_line(hc, licenceid)
        end
@@ -684,7 +685,7 @@ function git.sourceid(info, sourcename, sourceset)
        e2lib.log(4, string.format("hash data for source %s\n%s", src.name,
                                                                hc.data))
        src.sourceid[sourceset] = hash.hash_finish(hc)
-       return src.sourceid[sourceset]
+       return true, nil, src.sourceid[sourceset]
 end
 
 function git.toresult(info, sourcename, sourceset, directory)
@@ -813,4 +814,4 @@ function git.check_workingcopy(info, sourcename)
        return true, nil
 end
 
-e2scm.register("git", git)
+scm.register("git", git)
diff --git a/local/scm.lua b/local/scm.lua
new file mode 100644 (file)
index 0000000..8e188ac
--- /dev/null
@@ -0,0 +1,121 @@
+--[[
+   e2factory, the emlix embedded build system
+
+   Copyright (C) 2007-2009 Gordon Hecker <gh@emlix.com>, emlix GmbH
+   Copyright (C) 2007-2009 Oskar Schirmer <os@emlix.com>, emlix GmbH
+   Copyright (C) 2007-2008 Felix Winkelmann, emlix GmbH
+
+   For more information have a look at http://www.e2factory.org
+
+   e2factory is a registered trademark by emlix GmbH.
+
+   This file is part of e2factory, the emlix embedded build system.
+
+   e2factory is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+]]
+
+scm = module("scm", package.seeall)
+
+-- scm modules
+local scms = {}
+
+-- scm interfaces
+local intf = {}
+
+--- register a scm module
+-- @param scmname string: scm name
+-- @param mod the module
+-- @return bool
+-- @return an error object on failure
+function register(scmname, mod)
+  local e = new_error("error registering scm")
+  if scms[scmname] then
+    return false, e:append("scm with that name exists")
+  end
+  scms[scmname] = {}
+  for name,func in pairs(intf) do
+    rc, re = register_function(scmname, name, mod[name])
+    if not rc then
+      return false, e:cat(re)
+    end
+  end
+  return true, nil
+end
+
+--- register a new scm interface
+-- @param name string: interface name
+-- @return bool
+-- @return an error object on failure
+function register_interface(name)
+  local e = new_error("registering scm interface failed")
+  if intf[name] then
+    return false, e:append(
+               "interface with that name exists: %s", name)
+  end
+
+  -- closure: name
+  local function func(info, sourcename, ...)
+    local src = info.sources[sourcename]
+    local rc, re, e
+    e = new_error("calling scm operation failed")
+    if not scms[src.type] then
+      return false, e:append("no such source type: %s", src.type)
+    end
+    local f = scms[src.type][name]
+    if not f then
+      e:append("%s is not implemented for source type: %s", src.type)
+      return false, e
+    end
+    return f(info, sourcename, ...)
+  end
+
+  intf[name] = func
+
+  -- we have lots of calls like scm.<function>(...). Register the interface
+  -- function in the scm module to support those calls.
+  scm[name] = func
+  return true, nil
+end
+
+--- register a new scm function (accessible through a scm interface)
+-- @param type string: scm type
+-- @param name string: interface name
+-- @param func function: interface function
+-- @return bool
+-- @return an error object on failure
+function register_function(type, name, func)
+  local e = new_error("registering scm function failed")
+  if not scms[type] then
+    return false, e:append("no scm type by that name: %s", type)
+  end
+  if not intf[name] then
+    return false, e:append("no scm interface by that name: %s", name)
+  end
+  if scms[type][name] then
+    return false, e:append("scm function exists: %s.%s", type, name)
+  end
+  scms[type][name] = func
+  return true, nil
+end
+
+register_interface("sourceid")
+register_interface("validate_source")
+register_interface("toresult")
+register_interface("prepare_source")
+register_interface("fetch_source")
+register_interface("update")
+register_interface("check_workingcopy")
+register_interface("working_copy_available")
+register_interface("display")
+register_interface("has_working_copy")
index b9bcf56fc1bf5378308c5fb704e1b9c22dd41b74..9f5fa2f341875db8eac4fab002d2c9b2d725b190 100644 (file)
 ]]
 
 -- svn.lua - Subversion-specific SCM operations -*- Lua -*-
---
--- See e2scm.lua for more information about these operations.
---
--- The code assumes the directory layout in a svn repository looks like this:
---
--- <source>/<branch>/<dir>
--- <source>/<tag>/<dir>
 
--- helper functions
+module("svn", package.seeall)
+require("scm")
 
 --- translate url into subversion url
 -- @param u table: url table
@@ -220,7 +214,7 @@ function svn.sourceid(info, sourcename, source_set) --OK
        end
        src.sourceid["working-copy"] = "working-copy"
        if src.sourceid[source_set] then
-               return src.sourceid[source_set]
+               return true, nil, src.sourceid[source_set]
        end
        local hc = hash.hash_start()
        hash.hash_line(hc, src.name)
@@ -236,7 +230,7 @@ function svn.sourceid(info, sourcename, source_set) --OK
        e2lib.log(4, string.format("hash data for source %s\n%s", src.name,
                                                                hc.data))
        src.sourceid[source_set] = hash.hash_finish(hc)
-       return src.sourceid[source_set]
+       return true, nil, src.sourceid[source_set]
 end
 
 function svn.toresult(info, sourcename, sourceset, directory) --OK
@@ -245,7 +239,7 @@ function svn.toresult(info, sourcename, sourceset, directory) --OK
        -- <directory>/licences
        local rc, re
        local e = new_error("converting result")
-       rc, re = check(info, sourcename, true)
+       rc, re = git.check(info, sourcename, true)
        if not rc then
                return false, e:cat(re)
        end
@@ -325,7 +319,7 @@ end
 -- @param sourcename the source name
 -- @return bool
 function svn.validate_source(info, sourcename) --OK
-  local rc, re = generic_validate_source(info, sourcename)
+  local rc, re = git.generic_validate_source(info, sourcename)
   if not rc then
     -- error in generic configuration. Don't try to go on.
     return false, re
@@ -335,7 +329,7 @@ function svn.validate_source(info, sourcename) --OK
     src.sourceid = {}
   end
   local e = new_error("in source %s:", sourcename)
-  rc, re = source_apply_default_working(info, sourcename)
+  rc, re = git.source_apply_default_working(info, sourcename)
   if not rc then
     return false, e:cat(re)
   end
@@ -377,4 +371,4 @@ function svn.validate_source(info, sourcename) --OK
   return true, nil
 end
 
-e2scm.register("svn", svn)
+scm.register("svn", svn)