diff options
-rw-r--r-- | bin/gitano-post-receive-hook.in | 3 | ||||
-rw-r--r-- | bin/gitano-pre-receive-hook.in | 3 | ||||
-rw-r--r-- | bin/gitano-setup.in | 9 | ||||
-rw-r--r-- | lib/gitano.lua | 5 | ||||
-rw-r--r-- | lib/gitano/actions.lua | 5 | ||||
-rw-r--r-- | lib/gitano/admincommand.lua | 31 | ||||
-rw-r--r-- | lib/gitano/command.lua | 15 | ||||
-rw-r--r-- | lib/gitano/config.lua | 17 | ||||
-rw-r--r-- | lib/gitano/lace.lua | 3 | ||||
-rw-r--r-- | lib/gitano/patterns.lua | 74 | ||||
-rw-r--r-- | lib/gitano/plugins.lua | 5 | ||||
-rw-r--r-- | lib/gitano/repository.lua | 54 | ||||
-rw-r--r-- | lib/gitano/supple.lua | 3 | ||||
-rw-r--r-- | lib/gitano/usercommand.lua | 5 | ||||
-rw-r--r-- | testing/02-commands-user.yarn | 12 |
15 files changed, 179 insertions, 65 deletions
diff --git a/bin/gitano-post-receive-hook.in b/bin/gitano-post-receive-hook.in index 3386e71..cb77e06 100644 --- a/bin/gitano-post-receive-hook.in +++ b/bin/gitano-post-receive-hook.in @@ -36,6 +36,7 @@ -- @@GITANO_LUA_PATH local gitano = require "gitano" +local pat = gitano.patterns local gall = require "gall" local luxio = require "luxio" local sio = require "luxio.simple" @@ -113,7 +114,7 @@ end -- emails, ensuring that new rules are applied, etc) local updates = {} -for oldsha, newsha, refname in (sio.stdin:read("*a")):gmatch("([^ ]+) ([^ ]+) ([^\n]+)\n?") do +for oldsha, newsha, refname in (sio.stdin:read("*a")):gmatch(pat.GITHOOK_PARSE_CHANGESET) do gitano.log.ddebug("post-receive:", oldsha, newsha, refname) updates[refname] = {oldsha, newsha, oldsha=oldsha, newsha=newsha} end diff --git a/bin/gitano-pre-receive-hook.in b/bin/gitano-pre-receive-hook.in index c244c47..a81f892 100644 --- a/bin/gitano-pre-receive-hook.in +++ b/bin/gitano-pre-receive-hook.in @@ -36,6 +36,7 @@ -- @@GITANO_LUA_PATH local gitano = require "gitano" +local pat = gitano.patterns local gall = require "gall" local luxio = require "luxio" local sio = require "luxio.simple" @@ -116,7 +117,7 @@ end -- you. local updates = {} -for oldsha, newsha, refname in (sio.stdin:read("*a")):gmatch("([^ ]+) ([^ ]+) ([^\n]+)") do +for oldsha, newsha, refname in (sio.stdin:read("*a")):gmatch(pat.GITHOOK_PARSE_CHANGESET) do gitano.log.ddebug("pre-receive:", oldsha, newsha, refname) updates[refname] = {oldsha, newsha, oldsha=oldsha, newsha=newsha} end diff --git a/bin/gitano-setup.in b/bin/gitano-setup.in index 86b2e08..209104d 100644 --- a/bin/gitano-setup.in +++ b/bin/gitano-setup.in @@ -36,6 +36,7 @@ -- @@GITANO_LUA_PATH local gitano = require "gitano" +local pat = gitano.patterns local gall = require "gall" local luxio = require "luxio" local sio = require "luxio.simple" @@ -170,8 +171,8 @@ function file_exists(path) return true end -function validate_name(n) - if not n:match("^[a-z_][a-z0-9_%-]*$") then +function validate_name(n, pattern) + if not n:match(pattern) then error(gitano.i18n.expand("SETUP_ERROR_INVALID_NAME", { name=n }), 2) end end @@ -214,7 +215,7 @@ ask_for("paths.repos", gitano.i18n.expand("SETUP_PATHS_REPOS_INFO"), get("paths.home") .. "/repos") validate_name(ask_for("admin.username", gitano.i18n.expand("SETUP_ADMIN_USERNAME_INFO"), - "admin")) + "admin"), pat.VALID_USERNAME) ask_for("admin.realname", gitano.i18n.expand("SETUP_ADMIN_REALNAME_INFO"), "Administrator") @@ -222,7 +223,7 @@ ask_for("admin.email", gitano.i18n.expand("SETUP_ADMIN_EMAIL_INFO"), "admin@administrator.local") validate_name(ask_for("admin.keyname", gitano.i18n.expand("SETUP_ADMIN_KEYNAME_INFO"), - "default")) + "default"), pat.VALID_SSHKEYNAME) ask_for("site.name", gitano.i18n.expand("SETUP_SITE_NAME_INFO"), "a random Gitano instance") ask_for("log.prefix", gitano.i18n.expand("SETUP_LOG_PREFIX_INFO"), "gitano") diff --git a/lib/gitano.lua b/lib/gitano.lua index 5abf8c8..5354a0f 100644 --- a/lib/gitano.lua +++ b/lib/gitano.lua @@ -41,7 +41,11 @@ local supple = require 'gitano.supple' local auth = require 'gitano.auth' local plugins = require 'gitano.plugins' local i18n = require 'gitano.i18n' +<<<<<<< HEAD +local patterns = require 'gitano.patterns' +======= local hooks = require 'gitano.hooks' +>>>>>>> dsilvers/hooks local _VERSION = {1, 1, 0} _VERSION.major = _VERSION[1] @@ -69,5 +73,6 @@ return { auth = auth, plugins = plugins, i18n = i18n, + patterns = patterns, hooks = hooks, } diff --git a/lib/gitano/actions.lua b/lib/gitano/actions.lua index 8568d72..dbb5fe1 100644 --- a/lib/gitano/actions.lua +++ b/lib/gitano/actions.lua @@ -34,6 +34,7 @@ local util = require "gitano.util" local log = require "gitano.log" local gall = require "gall" local config = require "gitano.config" +local pat = require "gitano.patterns" local i18n = require 'gitano.i18n' local sio = require 'luxio.simple' local supple = require 'gitano.supple' @@ -106,9 +107,9 @@ local function _curl_txn(url, headers, body, content_type) if (how ~= "exit" or why ~= 0) then return "500", err, {}, "" end - local code, msg, _headers, content = response:match("^HTTP/1.[01] (...) ?([^\r\n]+)\r?\n(.-)\r?\n\r?\n(.*)$") + local code, msg, _headers, content = response:match(pat.HTTP_RESPONSE) local headers = {} - for k, v in _headers:gmatch("([^:\r\n]+): *([^\r\n]+)") do + for k, v in _headers:gmatch(pat.HTTP_HEADER) do local r = headers[k] or {} r[#r+1] = v headers[k] = r diff --git a/lib/gitano/admincommand.lua b/lib/gitano/admincommand.lua index cb60851..e9f2fdf 100644 --- a/lib/gitano/admincommand.lua +++ b/lib/gitano/admincommand.lua @@ -34,6 +34,7 @@ local log = require 'gitano.log' local util = require 'gitano.util' local repository = require 'gitano.repository' local config = require 'gitano.config' +local pat = require 'gitano.patterns' local clod = require 'clod' local luxio = require 'luxio' local sio = require 'luxio.simple' @@ -176,7 +177,7 @@ local function builtin_user_validate(conf, _, cmdline) log.error("user add takes a username, email address and real name") return false end - if cmdline[2] == "add" and not cmdline[3]:match("^[a-z][a-z0-9_.-]+$") then + if cmdline[2] == "add" and not cmdline[3]:match(pat.VALID_USERNAME) then log.error("user name '" .. cmdline[3] .. "' not valid.") return false end @@ -343,6 +344,20 @@ local function builtin_user_run(conf, _, cmdline, env) log.fatal(commit) end log.state("Committed: " .. reason) + if cmdline[2] == "rename" then + local function reown_repo(_, repo) + if repo:conf_get("project.owner") == cmdline[3] then + local ok, msg = repo:conf_set_and_save( + "project.owner", cmdline[4], + env.GITANO_USER, env.GITANO_ORIG_USER) + if not ok then + log.error(msg) + return "exit", 1 + end + end + end + repository.foreach(conf, reown_repo) + end end return "exit", 0 end @@ -406,7 +421,7 @@ local function builtin_group_validate(conf, _, cmdline) log.error("Add takes a group name and a description") return false end - if cmdline[2] == "add" and not cmdline[3]:match("^[a-z][a-z0-9_.-]+$") then + if cmdline[2] == "add" and not cmdline[3]:match(pat.VALID_GROUPNAME) then log.error("group name '" .. cmdline[3] .. "' not valid.") return false end @@ -739,7 +754,7 @@ local function builtin_keyring_validate(conf, _, cmdline) if #cmdline > 3 then local ok = true for i = 4, #cmdline do - if not cmdline[i]:match("^" .. string.rep("[0-9A-Fa-f]", 40) .. "$") then + if not cmdline[i]:match(pat.VALID_KEY_FINGERPINRT) then log.error("error: '" .. cmdline[i] .. "' is not a valid fingerprint") ok = false end @@ -750,7 +765,7 @@ local function builtin_keyring_validate(conf, _, cmdline) end if cmdline[2] == "delkey" then if #cmdline == 4 or #cmdline == 5 then - if not cmdline[4]:match("^" .. string.rep("[0-9A-Fa-f]", 40) .. "$") then + if not cmdline[4]:match(pat.VALID_KEY_FINGERPRINT) then log.error("error: '" .. cmdline[i] .. "' is not a valid fingerprint") return false end @@ -795,7 +810,7 @@ local function builtin_keyring_run(conf, _, cmdline, env) log.error("Keyring " .. keyringname .. " already exists") return "exit", 1 end - if not keyringname:match("^[a-z][a-z0-9_.-]+$") then + if not keyringname:match(pat.VALID_KEYRING_NAME) then log.error("Keyring " .. keyringname .. " is not lower-alphanumeric") return "exit", 1 end @@ -867,7 +882,7 @@ local function builtin_keyring_run(conf, _, cmdline, env) if code ~= 0 then log.fatal("Unable to list keyring: GPG returned " .. tostring(code)) end - for fingerprint in alloutput:gmatch("fpr:::::::::([0-9A-F]+):") do + for fingerprint in alloutput:gmatch(pat.GPG_OUTPUT_FINGERPRINT_MATCH) do log.stdout(fingerprint) end end @@ -1149,7 +1164,7 @@ local function builtin_graveyard_run(conf, _, cmdline, env) repeat e, i = luxio.readdir(dirp) if e == 0 then - if not i.d_name:find("^%.") then + if not i.d_name:find(pat.DOTFILE) then log.stdout(i.d_name) end end @@ -1200,7 +1215,7 @@ local function builtin_graveyard_run(conf, _, cmdline, env) repeat e, i = luxio.readdir(dirp) if e == 0 then - if not i.d_name:find("^%.") then + if not i.d_name:find(pat.DOTFILE) then if not match or (match == i.d_name) then to_remove[#to_remove+1] = i.d_name end diff --git a/lib/gitano/command.lua b/lib/gitano/command.lua index f581dc1..3f433ca 100644 --- a/lib/gitano/command.lua +++ b/lib/gitano/command.lua @@ -33,6 +33,7 @@ local log = require 'gitano.log' local util = require 'gitano.util' local repository = require 'gitano.repository' +local pattern = require 'gitano.patterns' local sio = require "luxio.simple" @@ -241,7 +242,7 @@ local function builtin_help_run(config, repo, cmdline, env) log.state(cmd.name, do_sep(cmd), desc) if cmd.helptext then log.state("") - for line in (cmd.helptext):gmatch("([^\n]*)\n") do + for line in (cmd.helptext):gmatch(pattern.TEXT_LINE) do log.state("=>", line) end end @@ -453,9 +454,9 @@ local function builtin_config_validate(conf, repo, cmdline) return false end cmdline.orig_key = cmdline[4] - if cmdline[4]:match("%.%*$") then + if cmdline[4]:match(pattern.CONF_ENDS_WILDCARD) then -- Doing a wild removal, expand it now - local prefix = cmdline[4]:match("^(.+)%.%*$") + local prefix = cmdline[4]:match(pattern.CONF_WILDCARD) cmdline[4] = nil for k in repo.project_config:each(prefix) do cmdline[#cmdline+1] = k @@ -525,7 +526,7 @@ local function builtin_config_run(conf, repo, cmdline, env) for i = 1, #slist do local key = slist[i] local value = repo.project_config.settings[key] - local prefix = key:match("^(.+)%.i_[0-9]+$") + local prefix = key:match(pattern.CONF_ARRAY_INDEX) if prefix then local neatkey = prefix .. ".*" for i = 4, #cmdline do @@ -539,7 +540,7 @@ local function builtin_config_run(conf, repo, cmdline, env) end elseif cmdline[3] == "set" then local key, value = cmdline[4], cmdline[5] - local vtype, rest = value:match("^([sbi]):(.*)$") + local vtype, rest = value:match(pattern.CONF_SET_TYPE_PREFIX) if vtype then if vtype == "s" then value = rest @@ -839,9 +840,9 @@ local function builtin_ls_run(config, _, cmdline, env) pat = pat .. ".*" end if used_evil then - pat = "^/" .. pat .. "%.git$" + pat = "^/" .. pat .. pattern.GIT_REPO_SUFFIX else - pat = "/" .. pat .. "%.git$" + pat = "/" .. pat .. pattern.GIT_REPO_SUFFIX end log.debug("PAT:", pat) pats[#pats+1] = pat diff --git a/lib/gitano/config.lua b/lib/gitano/config.lua index a582db1..7227866 100644 --- a/lib/gitano/config.lua +++ b/lib/gitano/config.lua @@ -38,6 +38,7 @@ local gall = require 'gall' local log = require 'gitano.log' local lace = require 'gitano.lace' local i18n = require 'gitano.i18n' +local pat = require 'gitano.patterns' local luxio = require 'luxio' local sio = require 'luxio.simple' local clod = require 'clod' @@ -109,7 +110,7 @@ local function parse_admin_config(commit) -- Gather the users local users = {} for filename, obj in pairs(flat_tree) do - local prefix, username = filename:match("^(users/.-)([a-z][a-z0-9_.-]+)/user%.conf$") + local prefix, username = filename:match(pat.USER_CONF_MATCH) if prefix and username then if not is_blob(obj) then return nil, prefix .. username .. "/user.conf is not a blob?" @@ -144,7 +145,7 @@ local function parse_admin_config(commit) -- Now gather the users' keys local all_keys = {} for filename, obj in pairs(flat_tree) do - local prefix, username, keyname = filename:match("^(users/.-)([a-z][a-z0-9_.-]+)/([a-z][a-z0-9_.-]+)%.key$") + local prefix, username, keyname = filename:match(pat.USER_KEY_MATCH) if prefix and username and keyname then if not users[username] then return nil, i18n.expand("ERROR_ORPHAN_KEY", @@ -158,7 +159,7 @@ local function parse_admin_config(commit) return nil, i18n.expand("ERROR_BAD_KEY_NEWLINES", {filename=filename}) end - local keytype, keydata, keytag = this_key:match("^([^ ]+) ([^ ]+) ([^ ].*)$") + local keytype, keydata, keytag = this_key:match(pat.SSH_KEY_CONTENTS) if not (keytype and keydata and keytag) then return nil, i18n.expand("ERROR_BAD_KEY_SMELL", {filename=filename}) end @@ -190,7 +191,7 @@ local function parse_admin_config(commit) -- Now gather the groups local groups = {} for filename, obj in pairs(flat_tree) do - local prefix, groupname = filename:match("^(groups/.-)([a-z][a-z0-9_.-]+)%.conf$") + local prefix, groupname = filename:match(pat.GROUP_CONF_MATCH) if prefix and groupname then if groups[groupname] then return nil, i18n.expand("ERROR_DUPLICATE_GROUP", {name=groupname}) @@ -269,7 +270,7 @@ local function parse_admin_config(commit) -- Now gather the keyrings local keyrings = {} for filename, obj in pairs(flat_tree) do - local prefix, keyringname = filename:match("^(keyrings/.-)([a-z][a-z0-9_.-]+)%.gpg$") + local prefix, keyringname = filename:match(pat.KEYRING_MATCH) if prefix and keyringname then if keyrings[keyringname] then return nil, i18n.expand("ERROR_DUPLICATE_KEYRING", {name=keyringname}) @@ -440,9 +441,9 @@ local function commit_config_changes(conf, desc, author, committer) -- Shallow copy the tree ready for mods, skipping keyrings, users and groups for k,v in pairs(conf.content) do - if not (k:match("^users/") or - k:match("^groups/") or - k:match("^keyrings/")) then + if not (k:match(pat.USER_INFO_PREFIX) or + k:match(pat.GROUP_INFO_PREFIX) or + k:match(pat.KEYRING_INFO_PREFIX)) then newtree[k] = v end end diff --git a/lib/gitano/lace.lua b/lib/gitano/lace.lua index 2ba0634..685d625 100644 --- a/lib/gitano/lace.lua +++ b/lib/gitano/lace.lua @@ -35,6 +35,7 @@ local util = require 'gitano.util' local gall = require 'gall' local log = require 'gitano.log' local i18n = require 'gitano.i18n' +local pat = require 'gitano.patterns' local pcre = require "rex_pcre" @@ -45,7 +46,7 @@ include global:core } local function _loader(ctx, _name) - local global_name = _name:match("^global:(.+)$") + local global_name = _name:match(pat.LACE_GLOBAL_DEFINITION) local name, tree, sha = global_name or _name if not global_name then -- Project load diff --git a/lib/gitano/patterns.lua b/lib/gitano/patterns.lua new file mode 100644 index 0000000..e8527a0 --- /dev/null +++ b/lib/gitano/patterns.lua @@ -0,0 +1,74 @@ +-- gitano.patterns +-- +-- Centralised pattern definitions. Not stable ABI. +-- +-- Copyright 2017 Richard Maw <richard.maw@gmail.com> +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- 3. Neither the name of the author nor the names of their contributors +-- may be used to endorse or promote products derived from this software +-- without specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +-- ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +-- SUCH DAMAGE. +-- + +local _NICE_NAME = "[a-z][a-z0-9_.-]+" + +local USER_INFO_PREFIX = "^(users/.-)(".. _NICE_NAME .. ")/" +local GROUP_INFO_PREFIX = "^(groups/.-)(".. _NICE_NAME .. ")" +local KEYRING_INFO_PREFIX = "^(keyrings/.-)(".. _NICE_NAME .. ")" + +local CONF_ENDS_WILDCARD = "%.%*$" + +local GIT_REPO_SUFFIX = "%.git$" + +return { + TEXT_LINE = "([^\n]*)\n", + DOTFILE = "^%.", + VALID_USERNAME = "^" .. _NICE_NAME .. "$", + VALID_SSHKEYNAME = "^" .. _NICE_NAME .. "$", + USER_INFO_PREFIX = USER_INFO_PREFIX, + USER_CONF_MATCH = USER_INFO_PREFIX .. "user%.conf$", + USER_KEY_MATCH = USER_INFO_PREFIX .. "(" .. _NICE_NAME .. ")%.key$", + SSH_KEY_CONTENTS = "^([^ ]+) ([^ ]+) ([^ ].*)$", + VALID_GROUPNAME = "^" .. _NICE_NAME .. "$", + GROUP_INFO_PREFIX = GROUP_INFO_PREFIX, + GROUP_CONF_MATCH = GROUP_INFO_PREFIX .. "%.conf$", + VALID_KEY_FINGERPRINT = "^" .. string.rep("[0-9A-Fa-f]", 40) .. "$", + VALID_KEYRING_NAME = "^" .. _NICE_NAME .. "$", + KEYRING_INFO_PREFIX = KEYRING_INFO_PREFIX, + KEYRING_MATCH = KEYRING_INFO_PREFIX .. "%.gpg$", + GPG_OUTPUT_FINGERPRINT_MATCH = "fpr:::::::::([0-9A-F]+):", + HTTP_RESPONSE = "^HTTP/1.[01] (...) ?([^\r\n]+)\r?\n(.-)\r?\n\r?\n(.*)$", + HTTP_HEADER = "([^:\r\n]+): *([^\r\n]+)", + CONF_ENDS_WILDCARD = CONF_ENDS_WILDCARD, + CONF_WILDCARD = "^(.+)" .. CONF_ENDS_WILDCARD, + CONF_ARRAY_INDEX = "^(.+)%.i_[0-9]+$", + CONF_SET_TYPE_PREFIX = "^([sbi]):(.*)$", + GIT_REPO_SUFFIX = GIT_REPO_SUFFIX, + GIT_REPO_NAME_MATCH = "^(.+)" .. GIT_REPO_SUFFIX, + LACE_GLOBAL_DEFINITION = "^global:(.+)$", + PLUGIN_NAME = "^([^_]+)%.lua$", + REF_IS_NORMALISED = "^refs/", + PARSE_TIME_AND_TZOFFSET = "^([0-9]+) ([+-][0-9]+)$", + SUPPLE_MODULE_LOAD_MATCH = "^([^%.]+)%.(.+)$", + GITHOOK_PARSE_CHANGESET = "([^ ]+) ([^ ]+) ([^\n]+)\n?", +} diff --git a/lib/gitano/plugins.lua b/lib/gitano/plugins.lua index fd393ef..81546e6 100644 --- a/lib/gitano/plugins.lua +++ b/lib/gitano/plugins.lua @@ -33,14 +33,13 @@ local util = require "gitano.util" local log = require "gitano.log" local i18n = require "gitano.i18n" +local pat = require "gitano.patterns" local luxio = require "luxio" local sio = require "luxio.simple" local gfind = string.gfind -local plugin_name_pattern = "^([^_]+)%.lua$" - local function find_plugins(path) local ret = {} for _, entry in ipairs(path) do @@ -50,7 +49,7 @@ local function find_plugins(path) {dir=entry, reason=err})) else for filename, fileinfo in dirp:iterate() do - local plugin_name = filename:match(plugin_name_pattern) + local plugin_name = filename:match(pat.PLUGIN_NAME) if plugin_name then if not ret[plugin_name] then ret[plugin_name] = entry diff --git a/lib/gitano/repository.lua b/lib/gitano/repository.lua index b7e2ccc..be6a689 100644 --- a/lib/gitano/repository.lua +++ b/lib/gitano/repository.lua @@ -40,6 +40,7 @@ local config = require 'gitano.config' local util = require 'gitano.util' local lace = require 'gitano.lace' local i18n = require 'gitano.i18n' +local pat = require 'gitano.patterns' local clod = require 'clod' local base_rules = [[ @@ -455,8 +456,8 @@ function repo_method:populate_context(context) if not self.is_nascent then local lists_to_add = {} for k, v in self.project_config:each() do - if k:match("%.i_[0-9]+$") then - lists_to_add[k:gsub("%.i_[0-9]+$", "")] = true + if k:match(pat.CONF_ARRAY_INDEX) then + lists_to_add[k:match(pat.CONF_ARRAY_INDEX)] = true else local confkey = "config/" .. k:gsub("%.", "/") context[confkey] = v @@ -512,7 +513,7 @@ function repo_method:conf_set_and_save(conf, newvalue, author, committer) end function repo_method:set_head(newhead, author, committer) - if not newhead:match("^refs/") then + if not newhead:match(pat.REF_IS_NORMALISED) then newhead = "refs/heads/" .. newhead end local oldhead = self:conf_get "project.head" @@ -568,15 +569,27 @@ function repo_method:destroy_self(call_me) return true end +local function normalise_repo_path(reponame) + -- Inject a leading '/' + reponame = "/" .. reponame + -- Remove any spaces, tabs, newlines or nulls + reponame = reponame:gsub("[%s%z]+", "") + -- Remove any '.' which follows a '/' + reponame = reponame:gsub("/%.+", "/") + -- simplify any sequence of '/' to a single '/' + reponame = reponame:gsub("/+", "/") + -- Remove any leading or trailing / + reponame = reponame:match("^/*(.-)/*$") + -- Remove trailing .git if present. + if reponame:match("."..pat.GIT_REPO_SUFFIX) then + reponame = reponame:match(pat.GIT_REPO_NAME_MATCH) + end + return reponame +end + function repo_method:rename_to(somename) -- Same cleanup as in find... - if somename:match(".%.git$") then - somename = somename:match("^(.+)%.git$") - end - -- Remove any '.' - somename = somename:gsub("%.", "") - -- Remove any leading or trailing / - somename = somename:match("^/*(.-)/*$") + somename = normalise_repo_path(somename) local newpath = self.fs_path({name=somename,config=self.config}) @@ -679,7 +692,7 @@ function repo_method:update_modified_date(shas) if f then local s = f:read("*l") if s then - local cur_mod_time, cur_mod_offset = s:find("^([0-9]+) ([+-][0-9]+)$") + local cur_mod_time, cur_mod_offset = s:find(pat.PARSE_TIME_AND_TZOFFSET) if cur_mod_time then update_based_on(cur_mod_time, cur_mod_offset) end @@ -830,20 +843,7 @@ local function find_repository(config, reponame) -- -- If the repository exists, then it is examined and brought up-to-date -- with any global config changes before being returned. - -- Inject a leading '/' - reponame = "/" .. reponame - -- Remove any spaces, tabs, newlines or nulls - reponame = reponame:gsub("[%s%z]+", "") - -- Remove any '.' which follows a '/' - reponame = reponame:gsub("/%.+", "/") - -- simplify any sequence of '/' to a single '/' - reponame = reponame:gsub("/+", "/") - -- Remove any leading or trailing / - reponame = reponame:match("^/*(.-)/*$") - -- Remove trailing .git if present. - if reponame:match(".%.git$") then - reponame = reponame:match("^(.+)%.git$") - end + reponame = normalise_repo_path(reponame) -- Construct the repo local repo = setmetatable({config = config, name = reponame}, repo_meta) @@ -904,12 +904,12 @@ local function foreach_repository(conf, callback, filterfn) repeat e, i = luxio.readdir(dirp) if e == 0 then - if i.d_name:find("%.git$") then + if i.d_name:match(pat.GIT_REPO_SUFFIX) then -- Might be a repo, save for later all_repos[#all_repos+1] = (util.path_join(prefix, i.d_name) ):gsub("^/", "") else - if i.d_name:find("^[^%.]") then + if not i.d_name:match(pat.DOTFILE) then recurse[#recurse+1] = i.d_name end end diff --git a/lib/gitano/supple.lua b/lib/gitano/supple.lua index 79ca3b4..49d62b1 100644 --- a/lib/gitano/supple.lua +++ b/lib/gitano/supple.lua @@ -36,6 +36,7 @@ local supple = require 'supple' local log = require 'gitano.log' local config = require 'gitano.config' local i18n = require 'gitano.i18n' +local pat = require 'gitano.patterns' local repo_proxies = {} local proxied_repo = {} @@ -112,7 +113,7 @@ local function load_repo_module(fromrepo, prefix, module) end local function load_module_src(modname) - local pfx, mod = modname:match("^([^%.]+)%.(.+)$") + local pfx, mod = modname:match(pat.SUPPLE_MODULE_LOAD_MATCH) if not (pfx and mod) then error(i18n.expand("ERROR_NOT_RIGHT_NAME_FORMAT", {modname=modname})) end diff --git a/lib/gitano/usercommand.lua b/lib/gitano/usercommand.lua index 49f4694..5d3d7ac 100644 --- a/lib/gitano/usercommand.lua +++ b/lib/gitano/usercommand.lua @@ -34,6 +34,7 @@ local log = require 'gitano.log' local util = require 'gitano.util' local repository = require 'gitano.repository' local config = require 'gitano.config' +local pat = require 'gitano.patterns' local sio = require 'luxio.simple' local subprocess = require 'luxio.subprocess' @@ -155,7 +156,7 @@ local function builtin_sshkey_validate(config, _, cmdline) log.error("sshkey", cmdline[2] .. ": Expected tag and no more") return false end - if not cmdline[3]:match("^[a-z][a-z0-9_-]+$") then + if not cmdline[3]:match(pat.VALID_SSHKEYNAME) then log.error("sshkey:", cmdline[3], "is not a valid tag name.") log.state("Tag names start with a letter and may contain only letters") log.state("and numbers, underscores and dashes. Tag names must be at") @@ -211,7 +212,7 @@ local function builtin_sshkey_run(conf, _, cmdline, env) end elseif cmdline[2] == "add" then local sshkey = sio.stdin:read("*l") - local keytype, keydata, keytag = sshkey:match("^([^ ]+) ([^ ]+) ([^ ].*)$") + local keytype, keydata, keytag = sshkey:match(pat.SSH_KEY_CONTENTS) if not (keytype and keydata and keytag) then log.error("Unable to parse key,", filename, "did not smell like an OpenSSH v2 key") diff --git a/testing/02-commands-user.yarn b/testing/02-commands-user.yarn index 54f402b..e372918 100644 --- a/testing/02-commands-user.yarn +++ b/testing/02-commands-user.yarn @@ -74,6 +74,18 @@ but it is possible to rename users. THEN stdout contains ^robert THEN stdout does not contain ^bob +In addition, you might want rename a user which owns repositories. When that +is done, Gitano must re-own the repository in order that rules using the +project's owner work properly. + + WHEN testinstance adminkey runs create testrepo robert + AND testinstance adminkey runs config testrepo show project.owner + THEN stdout contains robert + + WHEN testinstance adminkey runs user rename robert bob --force + AND testinstance adminkey runs config testrepo show project.owner + THEN stdout contains bob + FINALLY the instance is torn down Deleting users |