summaryrefslogtreecommitdiff
path: root/testing/gitano-test-tool.in
blob: e8924740c18ffca81ff00a2c8a90676925431c6c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
-- @@SHEBANG
-- -*- lua -*-
-- gitano-test-tool
--
-- Git (with) Augmented network operations -- testing tool
--
-- Copyright 2012 Daniel Silverstone <dsilvers@digital-scurf.org>
--
--

-- @@GITANO_LUA_PATH

local gitano = require "gitano"
local gall = require "gall"
local luxio = require "luxio"
local sio = require "luxio.simple"
local sp = require "luxio.subprocess"

-- @@GITANO_BIN_PATH
-- @@GITANO_SHARE_PATH

local argv = {...}
local basedir = (luxio.getenv "DATADIR") .. "/"

local function user_home(username)
   return basedir .. "user-home-" .. username
end

local function ssh_base(username)
   return user_home(username) .. "/.ssh"
end

local function ssh_key_file(username, keyname)
   return ssh_base(username) .. "/" .. keyname
end

local function unix_assert(ret, errno)
   if ret ~= 0 then
      error(luxio.strerror(errno))
   end
end

local function run_program(t)
   local proc = sp.spawn_simple(t)
   local how, why = proc:wait()
   if how == -1 then
      unix_assert(how, why)
   end
   if not (how == "exit" and why == 0) then
      io.stderr:write(how .. ":" .. tostring(why).."\n")
      os.exit(1)
   end
end

local function esc_quote_all(t)
   local tt = {}
   for i = 1, #t do
      tt[i] = ("%q"):format(t[i])
   end
   return table.concat(tt, " ")
end

local function load_auth(fname)
   local fh = io.open(fname, "r")
   local line = fh:read("*l")
   local ret = {}
   while line do
      line = line:gsub("^ *", "")
      line = line:gsub(" *$", "")
      line = line:gsub("^#.*", "")
      if line ~= "" then
	 local repopath, user, keyset, key =
	    line:match('^[^\\]+\\"([^"]+)\\" \\"([^"]+)\\" \\"([^"]+)\\""[^ ]+ (.+)$')
	 assert(repopath, line)
	 ret[#ret+1] = {
	    repopath = repopath,
	    user = user,
	    keyset = keyset,
	    key = key
	 }
	 ret[key] = ret[#ret]
      end
      line = fh:read("*l")
   end
   fh:close()
   return ret
end

local function generate_exturl(user, key, repo)
   local authkeys = load_auth(ssh_key_file("testinstance", "authorized_keys"))
   local pubkey = (sio.open(ssh_key_file(user, key) .. ".pub", "r")):read("*l")
   local authline = assert(authkeys[pubkey])
   local extfmt = "ext::env HOME=%s SSH_CLIENT=%s SSH_ORIGINAL_COMMAND=%s %s %s %s %s"
   local function esc(s)
      return ((s:gsub("%%", "%%%%")):gsub(" ", "%% "))
   end
   return (extfmt):format(esc(user_home("testinstance")),
                          esc("10.0.0.1 1234"),
			  "%S% " .. esc(repo),
			  esc(gitano.config.lib_bin_path() .. "/gitano-auth"),
			  esc(authline.repopath),
			  esc(authline.user), esc(authline.keyset))
end

function cmd_createunixuser(username)
   assert(sio.mkdir(user_home(username), "0755"))
   assert(sio.mkdir(ssh_base(username), "0755"))
end

function cmd_createsshkey(username, keyname, optionaltype)
   optionaltype = optionaltype or "rsa"
   local targetkey = ssh_key_file(username, keyname)
   local sourcekey = table.concat {
      "testing/keys/", username, "@", keyname, "_", optionaltype }
   local fh = io.open(sourcekey, "r")
   if not fh then
      run_program {
	 "ssh-keygen", "-q",
	 "-t", optionaltype,
	 "-C", username .. "-" .. optionaltype .. "@" .. keyname,
	 "-f", sourcekey,
	 "-N", "" }
      fh = assert(io.open(sourcekey, "r"))
   end
   local ofh = assert(io.open(targetkey, "w"))
   ofh:write(fh:read("*a"))
   fh:close()
   ofh:close()
   fh = assert(io.open(sourcekey .. ".pub", "r"))
   ofh = assert(io.open(targetkey .. ".pub", "w"))
   ofh:write(fh:read("*a"))
   fh:close()
   ofh:close()
end

function cmd_setupstandard(owning_user, master_key)
   local clodname = basedir .. "setup.clod"
   local fh = io.open(clodname, "w")
   fh:write('setup.batch "true"\n')
   fh:write(('paths.pubkey %q\n'):format(ssh_key_file(owning_user, master_key) .. ".pub"))
   fh:write(('paths.repos %q\n'):format(user_home(owning_user) .. "/repos"))
   fh:write('site.name "Gitano Test Instance"\n')
   fh:write('log.prefix "gitano-test"\n')
   fh:write(('admin.keyname %q\n'):format(master_key))
   fh:close()
   run_program {
      "gitano-setup", clodname,
      exe = gitano.config.lib_bin_path() .. "/gitano-setup",
      env = { HOME = user_home(owning_user) }
   }
end

function cmd_cloneviassh(user, key, repo, localname)
   local exturl = generate_exturl(user, key, repo)
   run_program {
      "git", "clone", exturl, user_home(user) .. "/" .. localname,
   }
end

function cmd_cloneexists(user, localname)
   run_program {
      "git", "fsck", user_home(user) .. "/" .. localname
   }
end

function cmd_pubkeyfilename(user, key)
   print(ssh_key_file(user, key) .. ".pub")
end

function cmd_runcommand(user, key, ...)
   local authkeys = load_auth(ssh_key_file("testinstance", "authorized_keys"))
   local pubkey = (sio.open(ssh_key_file(user, key) .. ".pub", "r")):read("*l")
   local authline = assert(authkeys[pubkey])
   local cmdline = {
      gitano.config.lib_bin_path() .. "/gitano-auth",
      authline.repopath, authline.user, authline.keyset,
      env = {HOME = user_home("testinstance"), SSH_CLIENT="10.0.0.1 1234"}
   }
   cmdline.env.SSH_ORIGINAL_COMMAND = esc_quote_all({...})
   run_program(cmdline)
end

function cmd_clonelocation(user, localname)
   print(user_home(user) .. "/" .. localname)
end

function cmd_findtoken()
   local input = sio.stdin:read("*a")
   local token = input:match("("..("[0-9a-f]"):rep(40)..")")
   assert(token, "Cannot find a token")
   print(token)
end

function cmd_serverlocation(repo)
   local h = user_home("testinstance")
   print(table.concat({h, "repos", repo}, "/"))
end

local cmd = table.remove(argv, 1)
if _G['cmd_' .. cmd] then
   _G['cmd_' .. cmd](unpack(argv))
else
   error("Unknown command: " .. cmd)
end