]> git.e2factory.org Git - e2factory.git/commitdiff
replace ad-hoc file table with file_class
authorTobias Ulmer <tu@emlix.com>
Fri, 25 Nov 2016 18:22:09 +0000 (19:22 +0100)
committerTobias Ulmer <tu@emlix.com>
Fri, 25 Nov 2016 18:22:09 +0000 (19:22 +0100)
Signed-off-by: Tobias Ulmer <tu@emlix.com>
local/chroot.lua
local/e2-fetch-sources.lua
local/e2-ls-project.lua
local/e2build.lua
local/e2tool.lua
local/licence.lua
local/project.lua
local/result.lua
plugins/collect_project.lua
plugins/files.lua

index eaa3bcf83233fddd6e2c64092c76df36ee11c6ca..91381857a40a9c9d73ad6b3bc1ce853a1af238d4 100644 (file)
@@ -86,7 +86,7 @@ end
 -- @param sha1 SHA1 checksum string. If file is local sha1 may be nil
 -- @return May throw error(err) on invalid input.
 function chroot.chroot:add_file(location, server, sha1)
-    local t, ok, re
+    local t, ok, re, file
 
     ok, re = e2lib.vrfy_string_len(location, "chroot location")
     if not ok then
@@ -106,7 +106,9 @@ function chroot.chroot:add_file(location, server, sha1)
     end
 
     self._chrootgroupid = false
-    table.insert(self._files, { location=location, server=server, sha1=sha1 })
+    file = e2tool.file_class:new(server, location)
+    file:sha1(sha1)
+    table.insert(self._files, file)
 end
 
 --- Iterator that returns file tables in the order they were added.
@@ -120,11 +122,7 @@ function chroot.chroot:file_iter()
 
         if self._files[i] then
             -- return a copy
-            return {
-                location = self._files[i].location,
-                server = self._files[i].server,
-                sha1 = self._files[i].sha1,
-            }
+            return self._files[i]:instance_copy()
         end
 
         return nil
@@ -149,10 +147,10 @@ function chroot.chroot:chrootgroupid(info)
     hash.hash_append(hc, self._name)
 
     local fileid
-    for f in self:file_iter() do
-        hash.hash_append(hc, f.server)
-        hash.hash_append(hc, f.location)
-        fileid, re = e2tool.fileid(info, f)
+    for file in self:file_iter() do
+        hash.hash_append(hc, file:server())
+        hash.hash_append(hc, file:location())
+        fileid, re = e2tool.fileid(info, file)
         if not fileid then
             return false, e:cat(re)
         end
index 15685a231a98f6232a90f3c895166639740df1b4..23a16cc8ff2c50152f37467ade16c0c7bd2319ca 100644 (file)
@@ -106,9 +106,9 @@ local function e2_fetch_source(arg)
         for _,g in ipairs(chroot.groups_sorted) do
             grp = chroot.groups_byname[g]
             for file in grp:file_iter() do
-                if cache.cache_enabled(info.cache, file.server) then
-                    rc, re = cache.fetch_file_path(info.cache, file.server,
-                        file.location)
+                if cache.cache_enabled(info.cache, file:server()) then
+                    rc, re = cache.fetch_file_path(info.cache, file:server(),
+                        file:location())
                     if not rc then
                         return false, re
                     end
index d17b47fcc515c917350eececbed8439e8f2571b5..d8faf7f19d116626c23ffabc9dd679ba207dd7a7 100644 (file)
@@ -299,8 +299,8 @@ local function e2_ls_project(arg)
             s2 = " "
         end
         p2(s1, s2, lic:get_name())
-        for f in lic:file_iter() do
-            p3(s1, s2, "file", string.format("%s:%s", f.server, f.location))
+        for file in lic:file_iter() do
+            p3(s1, s2, "file", string.format("%s:%s", file:server(), file:location()))
         end
     end
 
@@ -320,8 +320,8 @@ local function e2_ls_project(arg)
             s2 = " "
         end
         p2(s1, s2, grp:get_name(), grp:get_name())
-        for f in grp:file_iter() do
-            p3(s1, s2, "file", string.format("%s:%s", f.server, f.location))
+        for file in grp:file_iter() do
+            p3(s1, s2, "file", string.format("%s:%s", file:server(), file:location()))
         end
         --[[if grp.groupid then
             p3(s1, s2, "groupid", grp.groupid)
index 51a14c109144bbc8c146ee654803ebc5bc0e7bda..938e36c64f2db6212979aeef4d01a384c27e32c4 100644 (file)
@@ -434,15 +434,15 @@ function e2build.build_process_class:_setup_chroot(res, return_flags)
     for cgrpnm in res:chroot_list():iter() do
         grp = chroot.groups_byname[cgrpnm]
 
-        for f in grp:file_iter() do
+        for file in grp:file_iter() do
 
-            path, re = cache.fetch_file_path(info.cache, f.server, f.location)
+            path, re = cache.fetch_file_path(info.cache, file:server(), file:location())
             if not path then
                 return false, e:cat(re)
             end
 
-            if f.sha1 then
-                rc, re = e2tool.verify_hash(info, f)
+            if file:sha1() then
+                rc, re = e2tool.verify_hash(info, file)
                 if not rc then
                     return false, e:cat(re)
                 end
index b1a98af5435c5954befd5dd14640e66f6a4a6be2..c339bac25051e71a7642a98f910051a4d6b56813 100644 (file)
@@ -24,6 +24,7 @@ package.loaded["e2tool"] = e2tool
 local buildconfig = require("buildconfig")
 local cache = require("cache")
 local chroot = require("chroot")
+local class = require("class")
 local digest = require("digest")
 local e2build = require("e2build")
 local e2lib = require("e2lib")
@@ -46,6 +47,174 @@ local strict = require("strict")
 local tools = require("tools")
 local url = require("url")
 
+--- @type file_class
+e2tool.file_class = class("file_class")
+
+--- File_class constructor.
+-- A file_class represents a single file entry in various e2 config files.
+-- Server name and location are required, everything else is optional and some
+-- attributes are not universal. Most error checking is thus left to other
+-- layers, except for some basic assert statements.
+-- @param server Server name (as known to cache)
+-- @param location Path to file relative to server
+-- @raise Assert on bad input
+function e2tool.file_class:initialize(server, location)
+    assertIsStringN(server)
+    self._server = server
+
+    assertIsStringN(location)
+    self._location = location
+end
+
+--- Create a new instance.
+-- Note that the licences sl is NOT copied.
+-- @return object copy
+-- @see sl.sl
+function e2tool.file_class:instance_copy()
+    local c = e2tool.file_class:new(self:server(), self:location())
+    c:sha1(self:sha1())
+    c:licences(self:licences()) -- stringlist, doesn't create a copy
+    c:unpack(self:unpack())
+    c:copy(self:copy())
+    c:patch(self:patch())
+    return c
+end
+
+--- Turn a file object into a table.
+-- File entry like in e2source, chroot, etc.
+-- @return file table
+function e2tool.file_class:to_config_table()
+    local t = {}
+
+    t.server = self:server()
+    t.location = self:location()
+
+    if self:sha1() then
+        t.sha1 = self:sha1()
+    end
+    if self:unpack() then
+        t.unpack = self:unpack()
+    end
+    if self:copy() then
+        t.copy = self:copy()
+    end
+    if self:patch() then
+        t.patch = self:patch()
+    end
+    if self:licences() then
+        t.licences = self:licences():totable()
+    end
+
+    return t
+end
+
+--- Set or return the server attribute.
+-- Server name is any name known to cache.
+-- @param server Optional server name to set
+-- @return Server name
+-- @raise Assert on bad input or unset server name
+function e2tool.file_class:server(server)
+    if server then
+        assertIsStringN(server)
+        self._server = server
+    else
+        assertIsStringN(self._server)
+    end
+
+    return self._server
+end
+
+--- Set or return the location attribute.
+-- File path relative to server.
+-- @param location Optional location to set
+-- @return Location
+-- @raise Assert on bad input or unset location
+function e2tool.file_class:location(location)
+    if location then
+        assertIsStringN(location)
+        self._location = location
+    else
+        assertIsStringN(self._location)
+    end
+
+    return self._location
+end
+
+--- Get or set the <b>configured</b> SHA1 sum.
+-- @param sha1 Optional SHA1 sum to set
+-- @return SHA1 sum or false (unset)
+-- @raise Assert on bad input
+function e2tool.file_class:sha1(sha1)
+    if sha1 then
+        assertIsString(sha1)
+        assert(#sha1 == digest.SHA1_LEN)
+        self._sha1 = sha1
+    end
+
+    return self._sha1 or false
+end
+
+--- Get or set per-file licence list.
+-- @param lic_sl Optional licences stringlist to set
+-- @return licence stringlist or false (unset)
+-- @raise Assert on bad input
+function e2tool.file_class:licences(lic_sl)
+    if lic_sl then
+        assertIsTable(lic_sl)
+        assert(lic_sl:isInstanceOf(sl.sl))
+        self._licences = lic_sl
+    end
+
+    return self._licences or false
+end
+
+--- Get or set the unpack attribute.
+-- unpack, copy and patch are exclusive attributes, only one can be set
+-- @param unpack Optional unpack attribute to set
+-- @return Unpack attribute or false (unset)
+-- @raise Assert on bad input
+function e2tool.file_class:unpack(unpack)
+    if unpack then
+        assertIsString(unpack)
+        assert(not self._copy and not self._patch)
+        self._unpack = unpack
+    end
+
+    return self._unpack or false
+end
+
+--- Get or set the copy attribute.
+-- unpack, copy and patch are exclusive attributes, only one can be set
+-- @param copy Optional copy attribute to set
+-- @return Copy attribute or false (unset)
+-- @raise Assert on bad input
+function e2tool.file_class:copy(copy)
+    if copy then
+        assertIsString(copy)
+        assert(not self._unpack and not self._patch)
+        self._copy = copy
+    end
+
+    return self._copy or false
+end
+
+--- Get or set the patch attribute.
+-- unpack, copy and patch are exclusive attributes, only one can be set
+-- @param patch Optional patch attribute to set
+-- @return Patch attribute or false (unset)
+-- @raise Assert on bad input
+function e2tool.file_class:patch(patch)
+    if patch then
+        assertIsStringN(patch)
+        assert(not self._unpack and not self._copy)
+        self._patch = patch
+    end
+
+    return self._patch or false
+end
+
+--- @section end
+
 --- Info table contains servers, caches and more...
 -- @table info
 -- @field current_tool Name of the current local tool (string).
@@ -630,14 +799,13 @@ end
 -- @return error object on failure.
 local function compute_fileid(file, flags)
     assertIsTable(file)
-    assertIsStringN(file.server)
-    assertIsStringN(file.location)
+    assert(file:isInstanceOf(e2tool.file_class))
 
     local rc, re, info, path, fileid
 
     info = e2tool.info()
 
-    path, re = cache.fetch_file_path(info.cache, file.server, file.location, flags)
+    path, re = cache.fetch_file_path(info.cache, file:server(), file:location(), flags)
     if not path then
         return false, re
     end
@@ -656,15 +824,14 @@ end
 -- @return error object on failure.
 local function compute_remote_fileid(file)
     assertIsTable(file)
-    assertIsStringN(file.server)
-    assertIsStringN(file.location)
+    assert(file:isInstanceOf(e2tool.file_class))
 
     local rc, re, info, surl, u, fileid
 
     info = e2tool.info()
 
 
-    surl, re = cache.remote_url(info.cache, file.server, file.location)
+    surl, re = cache.remote_url(info.cache, file:server(), file:location())
     if not surl then
         return false, re
     end
@@ -716,15 +883,13 @@ end
 function e2tool.verify_hash(info, file)
     assertIsTable(info)
     assertIsTable(file)
-    assertIsStringN(file.server)
-    assertIsStringN(file.location)
-    assertIsStringN(file.sha1)
+    assert(file:isInstanceOf(e2tool.file_class))
 
     local rc, re, e, id_cache, id_remote, id_fetch, fileid
 
-    e = err.new("error verifying checksum of %s:%s", file.server, file.location)
+    e = err.new("error verifying checksum of %s:%s", file:server(), file:location())
 
-    if cache.cache_enabled(info.cache, file.server) then
+    if cache.cache_enabled(info.cache, file:server()) then
         id_cache, re = compute_fileid(file)
         if not id_cache then
             return false, e:cat(re)
@@ -769,9 +934,9 @@ function e2tool.verify_hash(info, file)
 
     fileid = id_cache or id_fetch
 
-    if file.sha1 ~= fileid then
+    if file:sha1() ~= fileid then
         e:append("checksum verification failed: configured file checksum differs from computed file checksum")
-        e:append("configured: %s computed: %s", file.sha1, fileid)
+        e:append("configured: %s computed: %s", file:sha1(), fileid)
         rc = false
     end
 
@@ -791,16 +956,15 @@ end
 function e2tool.fileid(info, file)
     assertIsTable(info)
     assertIsTable(file)
-    assertIsStringN(file.server)
-    assertIsStringN(file.location)
+    assert(file:isInstanceOf(e2tool.file_class))
 
     local rc, re, e, fileid
 
     e = err.new("error calculating file id for file: %s:%s",
-        file.server, file.location)
+        file:server(), file:location())
 
-    if file.sha1 then
-        fileid = file.sha1
+    if file:sha1() then
+        fileid = file:sha1()
     else
         fileid, re = compute_fileid(file)
         if not fileid then
@@ -809,11 +973,11 @@ function e2tool.fileid(info, file)
     end
 
     if e2option.opts["check-remote"] then
-        local filever = {
-            server = file.server,
-            location = file.location,
-            sha1 = fileid
-        }
+        local filever
+
+        filever = file:instance_copy()
+        filever:sha1(fileid)
+
         rc, re = e2tool.verify_hash(info, filever)
         if not rc then
             return false, e:cat(re)
index ba67c239d5556ad1266bd7a23605c631914e6364..5d43077dd136bb7165b715802d5ecd82fc38d769 100644 (file)
@@ -59,7 +59,7 @@ end
 -- @param sha1 SHA1 checksum string. If file is local sha1 may be nil
 -- @return May throw error(err) on invalid input.
 function licence.licence:add_file(location, server, sha1)
-    local t, ok, re
+    local file, ok, re
 
     ok, re = e2lib.vrfy_string_len(location, "licence location")
     if not ok then
@@ -80,12 +80,9 @@ function licence.licence:add_file(location, server, sha1)
 
     self._licenceid = false
 
-    t = {
-        location = location,
-        server = server,
-        sha1 = sha1,
-    }
-    table.insert(self._files, t)
+    file = e2tool.file_class:new(server, location)
+    file:sha1(sha1)
+    table.insert(self._files, file)
 end
 
 --- Iterator that returns file tables in the order they were added.
@@ -96,12 +93,7 @@ function licence.licence:file_iter()
         i = i + 1
 
         if self._files[i] then
-            -- return a copy
-            return {
-                location = self._files[i].location,
-                server = self._files[i].server,
-                sha1 = self._files[i].sha1,
-            }
+            return self._files[i]:instance_copy()
         end
 
         return nil
@@ -133,8 +125,8 @@ function licence.licence:licenceid(info)
     hash.hash_append(hc, self._name)
 
     for file in self:file_iter() do
-        hash.hash_append(hc, file.server)
-        hash.hash_append(hc, file.location)
+        hash.hash_append(hc, file:server())
+        hash.hash_append(hc, file:location())
 
         fileid, re = e2tool.fileid(info, file)
         if not fileid then
@@ -213,8 +205,8 @@ function licence.load_licence_config(info)
             return false, e:append("files attribute in %s not a table", name)
         end
 
-        for _,file in ipairs(l.files) do
-            rc, re = e2lib.vrfy_dict_exp_keys(file, "file",
+        for _,f in ipairs(l.files) do
+            rc, re = e2lib.vrfy_dict_exp_keys(f, "file",
                 { "server", "location", "sha1" })
             if not rc then
                 return false, e:cat(re)
@@ -243,11 +235,11 @@ function licence.load_licence_config(info)
             }
 
 
-            rc, re = e2lib.vrfy_table_attributes(file, keys, inherit)
+            rc, re = e2lib.vrfy_table_attributes(f, keys, inherit)
             if not rc then
                 return false, e:cat(re)
             end
-            if file.server ~= cache.server_names().dot and not file.sha1 then
+            if f.server ~= cache.server_names().dot and not f.sha1 then
                 return false, e:append(
                     "file entry for remote file without sha1 attribute")
             end
@@ -256,9 +248,8 @@ function licence.load_licence_config(info)
 
         licence.licences[name] = licence.licence:new(name)
 
-        for _,file in ipairs(l.files) do
-            licence.licences[name]:add_file(
-                file.location, file.server, file.sha1)
+        for _,f in ipairs(l.files) do
+            licence.licences[name]:add_file(f.location, f.server, f.sha1)
         end
     end
 
index 5561ca23c47dae800bef9880b8632abc27a6c4f5..63fe6337240b8c7ca8ac1a11b9defb9a62a83fe4 100644 (file)
@@ -289,11 +289,7 @@ function project.projid(info)
         local location, file, fileid
         if not e2lib.is_backup_file(f) then
             location = e2lib.join("proj/init", f)
-            file = {
-                server = cache.server_names().dot,
-                location = location,
-            }
-
+            file = e2tool.file_class:new(cache.server_names().dot, location)
             fileid, re = e2tool.fileid(info, file)
             if not fileid then
                 return false, re
index 574cfaf9536c5bfcf0332ab1175aa14123bfd417..d7ec61f0d3d40f9179b846bdfccdb68fb993a296 100644 (file)
@@ -503,10 +503,10 @@ function result.result_class:buildid()
     hash.hash_append(hc, self:merged_env():id())
 
     -- buildscript
-    local file = {
-        server = cache.server_names().dot,
-        location = e2tool.resultbuildscript(self:get_name_as_path()),
-    }
+    local file = e2tool.file_class:new(
+        cache.server_names().dot,
+        e2tool.resultbuildscript(self:get_name_as_path())
+        )
 
     id, re = e2tool.fileid(info, file)
     if not id then
index 9a36ad8582cff7d5b97b807270b73e1512b83c0a..765cf0f22adac21c4ac3de33f23349769dbed740 100644 (file)
@@ -173,10 +173,10 @@ local function _build_collect_project(self, res, return_flags)
         string.format("chroot_arch='%s'\n", project.chroot_arch())
     }
 
-    local file, destdir
+    local fn, destdir
     destdir = e2lib.join(bc.T, "project/proj")
-    file = e2lib.join(destdir, "config")
-    rc, re = eio.file_write(file, table.concat(out))
+    fn = e2lib.join(destdir, "config")
+    rc, re = eio.file_write(fn, table.concat(out))
     if not rc then
         return false, e:cat(re)
     end
@@ -196,17 +196,17 @@ local function _build_collect_project(self, res, return_flags)
 
         for file in grp:file_iter() do
             local cache_flags = {}
-            rc, re = cache.fetch_file(info.cache, file.server,
-                file.location, destdir, nil, cache_flags)
+            rc, re = cache.fetch_file(info.cache, file:server(),
+                file:location(), destdir, nil, cache_flags)
             if not rc then
                 return false, e:cat(re)
             end
-            if file.sha1 then
+            if file:sha1() then
                 local checksum_file = string.format(
-                    "%s/%s.sha1", destdir, e2lib.basename(file.location))
-                local filename = e2lib.basename(file.location)
+                    "%s/%s.sha1", destdir, e2lib.basename(file:location()))
+                local filename = e2lib.basename(file:location())
                 rc, re = eio.file_write(checksum_file,
-                    string.format("%s  %s", file.sha1, filename))
+                    string.format("%s  %s", file:sha1(), filename))
                 if not rc then
                     return false, e:cat(re)
                 end
@@ -214,13 +214,13 @@ local function _build_collect_project(self, res, return_flags)
                     e2lib.basename(checksum_file)))
             end
             local tartype
-            tartype, re = e2lib.tartype_by_suffix(file.location)
+            tartype, re = e2lib.tartype_by_suffix(file:location())
             if not tartype then
                 return false, e:cat(re)
             end
             table.insert(out, string.format(
                 "\te2-su-2.2 extract_tar_2_3 $(chroot_base) \"%s\" '%s'\n",
-                tartype, e2lib.basename(file.location)))
+                tartype, e2lib.basename(file:location())))
         end
 
         local makefile = e2lib.join(destdir, "Makefile")
@@ -243,13 +243,13 @@ local function _build_collect_project(self, res, return_flags)
 
         for file in lic:file_iter() do
             local cache_flags = {}
-            if file.sha1 then
+            if file:sha1() then
                 rc, re = e2tool.verify_hash(info, file)
                 if not rc then
                     return false, e:cat(re)
                 end
             end
-            rc, re = cache.fetch_file(info.cache, file.server, file.location,
+            rc, re = cache.fetch_file(info.cache, file:server(), file:location(),
                 destdir, nil, cache_flags)
             if not rc then
                 return false, e:cat(re)
index 358b137133aad09b2c7779742b0cf541b1552993..e95ef1bf3ca85599034c11670a2048b43d324ec1 100644 (file)
@@ -199,36 +199,23 @@ function files.files_source:initialize(rawsrc)
             error(e:append("%s must be a table", laerr))
         end
 
+        local file
+        file = e2tool.file_class:new(f.server, f.location)
+        file:sha1(f.sha1)
+        file:licences(f.licences)
+
         if f.unpack then
             assert(type(f.unpack) == "string")
-
-            table.insert(self._files, {
-                location=f.location,
-                server=f.server,
-                sha1=f.sha1,
-                unpack=f.unpack,
-                licences=f.licences,
-            })
+            file:unpack(f.unpack)
+            table.insert(self._files, file)
         elseif f.copy then
             assert(type(f.copy) == "string")
-
-            table.insert(self._files, {
-                location=f.location,
-                server=f.server,
-                sha1=f.sha1,
-                copy=f.copy,
-                licences=f.licences,
-            })
+            file:copy(f.copy)
+            table.insert(self._files, file)
         elseif f.patch then
             assert(type(f.patch) == "string")
-
-            table.insert(self._files, {
-                location=f.location,
-                server=f.server,
-                sha1=f.sha1,
-                patch=f.patch,
-                licences=f.licences,
-            })
+            file:patch(f.patch)
+            table.insert(self._files, file)
         else
             assert("internal error" == true)
         end
@@ -242,20 +229,7 @@ function files.files_source:file_iter()
         i = i + 1
 
         if self._files[i] then
-            -- return a copy so nobody can mess with the internals
-            local f = {
-                location = self._files[i].location,
-                server = self._files[i].server,
-                sha1 = self._files[i].sha1,
-                licences = self._files[i].licences:copy()
-            }
-            for _,attr in ipairs({ "copy", "unpack", "patch" }) do
-                if self._files[i][attr] then
-                    f[attr] = self._files[i][attr]
-                    break
-                end
-            end
-            return f
+            return self._files[i]:instance_copy()
         end
 
         return nil
@@ -286,20 +260,20 @@ function files.files_source:sourceid(sourceset --[[always ignored for files]])
         hash.hash_append(hc, lid)
     end
 
-    for f in self:file_iter() do
-        local fileid, re = e2tool.fileid(info, f)
+    for file in self:file_iter() do
+        local fileid, re = e2tool.fileid(info, file)
         if not fileid then
             return false, re
         end
         hash.hash_append(hc, fileid)
-        hash.hash_append(hc, f.location)
-        hash.hash_append(hc, f.server)
-        hash.hash_append(hc, tostring(f.unpack))
-        hash.hash_append(hc, tostring(f.patch))
-        hash.hash_append(hc, tostring(f.copy))
+        hash.hash_append(hc, file:location())
+        hash.hash_append(hc, file:server())
+        hash.hash_append(hc, tostring(file:unpack()))
+        hash.hash_append(hc, tostring(file:patch()))
+        hash.hash_append(hc, tostring(file:copy()))
 
         -- per file licence list
-        for licencename in f.licences:iter() do
+        for licencename in file:licences():iter() do
             local lid, re = licence.licences[licencename]:licenceid(info)
             if not lid then
                 return false, re
@@ -325,11 +299,11 @@ function files.files_source:display()
     table.insert(d, string.format("licences   = %s",
         self:get_licences():concat(" ")))
 
-    for f in self:file_iter() do
-        s = string.format("file       = %s:%s", f.server, f.location)
+    for file in self:file_iter() do
+        s = string.format("file       = %s:%s", file:server(), file:location())
         table.insert(d, s)
         table.insert(d, string.format("licences   = %s",
-            f.licences:concat(" ")))
+            file:licences():concat(" ")))
     end
 
     if self._sourceid then
@@ -349,17 +323,17 @@ function files.cache_source(info, sourcename)
     local src = source.sources[sourcename]
 
     -- cache all files for this source
-    for f in src:file_iter() do
-        if cache.cache_enabled(info.cache, f.server) then
+    for file in src:file_iter() do
+        if cache.cache_enabled(info.cache, file:server()) then
             e2lib.logf(3, "files.cache_source: caching file %s:%s",
-                f.server, f.location)
-            rc, re = cache.fetch_file_path(info.cache, f.server, f.location)
+                file:server(), file:location())
+            rc, re = cache.fetch_file_path(info.cache, file:server(), file:location())
             if not rc then
                 return false, re
             end
         else
-            e2lib.logf(3, "not caching %s:%s (stored locally)", f.server,
-                f.location)
+            e2lib.logf(3, "not caching %s:%s (stored locally)", file:server(),
+                file:location())
         end
     end
     return true
@@ -383,7 +357,7 @@ function files.has_working_copy(info, sourcename)
     return false
 end
 
---- Handle file.copy in a way that appears intuitive to the user. Returns
+--- 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).
@@ -542,15 +516,15 @@ function files.prepare_source(info, sourcename, sourceset, buildpath)
     local src = source.sources[sourcename]
 
     for file in src:file_iter() do
-        if file.sha1 then
+        if file:sha1() then
             rc, re = e2tool.verify_hash(info, file)
             if not rc then
                 return false, e:cat(re)
             end
         end
-        if file.unpack then
+        if file:unpack() then
             local path, re = cache.fetch_file_path(info.cache,
-                file.server, file.location)
+                file:server(), file:location())
             if not path then
                 return false, e:cat(re)
             end
@@ -567,7 +541,7 @@ function files.prepare_source(info, sourcename, sourceset, buildpath)
                 return false, e:cat(re)
             end
 
-            local expected_location = e2lib.join(buildpath, file.unpack)
+            local expected_location = e2lib.join(buildpath, file:unpack())
             if not e2lib.stat(expected_location) then
                 return false, err.new("expected unpack location '%s' does not exist",
                     expected_location)
@@ -575,8 +549,8 @@ function files.prepare_source(info, sourcename, sourceset, buildpath)
 
             if not symlink then
                 symlink = buildpath .. "/" .. sourcename
-                if file.unpack ~= sourcename then
-                    rc, re = e2lib.symlink(file.unpack, symlink)
+                if file:unpack() ~= sourcename then
+                    rc, re = e2lib.symlink(file:unpack(), symlink)
                     if not rc then
                         return false, e:cat(re)
                     end
@@ -592,22 +566,22 @@ function files.prepare_source(info, sourcename, sourceset, buildpath)
                     return false, e:cat(re)
                 end
             end
-            if file.patch then
+            if file:patch() then
                 local path, re = cache.fetch_file_path(info.cache,
-                    file.server, file.location)
+                    file:server(), file:location())
                 if not path then
                     return false, e:append(re)
                 end
-                local argv = { "-p", file.patch, "-d", symlink, "-i", path }
+                local argv = { "-p", file:patch(), "-d", symlink, "-i", path }
                 rc, re = patch_tool(argv)
                 if not rc then
-                    e:append("applying patch: \"%s:%s\"", file.server, file.location)
+                    e:append("applying patch: \"%s:%s\"", file:server(), file:location())
                     return false, e:cat(re)
                 end
-            elseif file.copy then
+            elseif file:copy() then
                 local destdir, destname
                 destdir, destname = gen_dest_dir_name(buildpath, sourcename,
-                    file.copy, file.location)
+                    file:copy(), file:location())
 
                 rc, re = e2lib.mkdir_recursive(destdir)
                 if not rc then
@@ -615,14 +589,14 @@ function files.prepare_source(info, sourcename, sourceset, buildpath)
                     return false, e:cat(re)
                 end
 
-                local rc, re = cache.fetch_file(info.cache, file.server,
-                    file.location, destdir, destname, {})
+                local rc, re = cache.fetch_file(info.cache, file:server(),
+                    file:location(), destdir, destname, {})
                 if not rc then
                     return false, e:cat(re)
                 end
             else
                 return false, err.new("missing destination for file %s (%s)",
-                    file.location, file.server)
+                    file:location(), file:server())
             end
         end
     end
@@ -648,9 +622,9 @@ function files.toresult(info, sourcename, sourceset, directory)
 
     out = { ".PHONY: place\n\nplace:\n" }
     for file in src:file_iter() do
-        e2lib.logf(4, "export file: %s", file.location)
+        e2lib.logf(4, "export file: %s", file:location())
         local destdir = string.format("%s/%s", directory, source)
-        local destname = e2lib.basename(file.location)
+        local destname = e2lib.basename(file:location())
 
         rc, re = e2lib.mkdir_recursive(destdir)
         if not rc then
@@ -663,26 +637,26 @@ function files.toresult(info, sourcename, sourceset, directory)
                 sourcename, destname)
         end
 
-        rc, re = cache.fetch_file(info.cache, file.server, file.location,
+        rc, re = cache.fetch_file(info.cache, file:server(), file:location(),
             destdir, destname, {})
         if not rc then
             return false, e:cat(re)
         end
-        if file.sha1 then
-            local filename = e2lib.basename(file.location)
+        if file:sha1() then
+            local filename = e2lib.basename(file:location())
             local checksum_file = string.format("%s/%s.sha1",
                 destdir, filename)
             rc, re = eio.file_write(checksum_file,
-                string.format("%s  %s", file.sha1, filename))
+                string.format("%s  %s", file:sha1(), filename))
             if not rc then
                 return false, e:cat(re)
             end
             table.insert(out, string.format("\tcd source && sha1sum -c '%s'\n",
                 e2lib.basename(checksum_file)))
         end
-        if file.unpack then
-            local physpath = e2lib.join(destdir, e2lib.basename(file.location))
-            local virtpath = e2lib.join(source, e2lib.basename(file.location))
+        if file:unpack() then
+            local physpath = e2lib.join(destdir, e2lib.basename(file:location()))
+            local virtpath = e2lib.join(source, e2lib.basename(file:location()))
             local rc, re = gen_unpack_command(physpath, virtpath, "$(BUILD)")
             if not rc then
                 e:cat("unable to generate unpack command")
@@ -701,18 +675,18 @@ function files.toresult(info, sourcename, sourceset, directory)
             end
             table.insert(out, "\n")
 
-            if file.unpack ~= sourcename then
+            if file:unpack() ~= sourcename then
                 table.insert(out, string.format("\tln -s %s $(BUILD)/%s\n",
-                    file.unpack, sourcename))
+                    file:unpack(), sourcename))
             end
         end
-        if file.copy then
+        if file:copy() then
             local to, from
             from = e2lib.shquote(
-                e2lib.join(source, e2lib.basename(file.location)))
+                e2lib.join(source, e2lib.basename(file:location())))
 
             local destdir, destname = gen_dest_dir_name("/", sourcename,
-                file.copy, file.location, "isdir")
+                file:copy(), file:location(), "isdir")
             --
             -- is a directory?
             --
@@ -726,8 +700,8 @@ function files.toresult(info, sourcename, sourceset, directory)
             --
             -- not a directory
             --
-            destdir, destname = gen_dest_dir_name("/", sourcename, file.copy,
-                file.location, "no")
+            destdir, destname = gen_dest_dir_name("/", sourcename, file:copy(),
+                file:location(), "no")
 
             to = string.format('"$(BUILD)"%s', e2lib.shquote(destdir))
             table.insert(out, string.format('\t\tmkdir -p %s; \\\n', to))
@@ -737,16 +711,16 @@ function files.toresult(info, sourcename, sourceset, directory)
             table.insert(out, string.format('\t\tcp %s %s; \\\n', from, to))
             table.insert(out, '\tfi\n')
         end
-        if file.patch then
+        if file:patch() then
             table.insert(out, string.format(
                 "\tpatch -p%s -d \"$(BUILD)/%s\" -i \"$(shell pwd)/%s/%s\"\n",
-                file.patch, sourcename, source, e2lib.basename(file.location)))
+                file:patch(), sourcename, source, e2lib.basename(file:location())))
         end
         -- write licences
         local destdir = string.format("%s/licences", directory)
         local fname = string.format("%s/%s.licences", destdir,
-            e2lib.basename(file.location))
-        local licence_list = file.licences:concat("\n") .. "\n"
+            e2lib.basename(file:location()))
+        local licence_list = file:licences():concat("\n") .. "\n"
         rc, re = e2lib.mkdir_recursive(destdir)
         if not rc then
             return false, e:cat(re)
@@ -755,7 +729,7 @@ function files.toresult(info, sourcename, sourceset, directory)
         if not rc then
             return false, e:cat(re)
         end
-        e2lib.logf(4, "export file: %s done", file.location)
+        e2lib.logf(4, "export file: %s done", file:location())
     end
 
     rc, re = eio.file_write(makefile, table.concat(out))