NetBSD Problem Report #48301

From rhialto@falu.nl  Fri Oct 11 13:26:47 2013
Return-Path: <rhialto@falu.nl>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
	(Client CN "mail.NetBSD.org", Issuer "Postmaster NetBSD.org" (verified OK))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 7A3C472613
	for <gnats-bugs@gnats.NetBSD.org>; Fri, 11 Oct 2013 13:26:47 +0000 (UTC)
Message-Id: <201310111326.r9BDQbAU018736@murthe.falu.nl>
Date: Fri, 11 Oct 2013 15:26:37 +0200 (CEST)
From: rhialto@falu.nl
Reply-To: rhialto@falu.nl
To: gnats-bugs@gnats.NetBSD.org
Cc: rhialto@falu.nl
Subject: Make devel/monotone build with lua 5.2 (with patch)
X-Send-Pr-Version: 3.95

>Number:         48301
>Category:       pkg
>Synopsis:       Make devel/monotone build with lua 5.2 (with patch)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    rhialto
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Oct 11 13:30:01 +0000 2013
>Closed-Date:    Mon Dec 20 14:49:44 +0000 2021
>Last-Modified:  Mon Dec 20 14:49:44 +0000 2021
>Originator:     Rhialto
>Release:        NetBSD 6.1.1
>Organization:

>Environment:


System: NetBSD murthe.falu.nl 6.1.1 NetBSD 6.1.1 (GENERIC) amd64
Architecture: x86_64
Machine: amd64
>Description:
	devel/monotone doesn't build with the lua which is currently
	in pkgsrc (5.2.x). This is with the current stable branch
	2013Q3.
>How-To-Repeat:
	Just try to build devel/monotone.
>Fix:
	After submitting a monotone bug report
	    https://code.monotone.ca/p/monotone/issues/224/
	I was pointed to a patch which was almost immediately usable.
	See below.
	I added it as patches/patch-monotone-1.0-lua-5.2.patch.

	I've been told that a next release of monotone won't need this patch
	any more.


$Id$

Source: http://pkgs.fedoraproject.org/cgit/monotone.git/plain/monotone-1.0-lua-5.2.patch
via http://pkgs.fedoraproject.org/cgit/monotone.git/tree/

Edited path names to make them apply without -p1.

From: Thomas Moschny <thomas.moschny@gmx.de>
Subject: [PATCH] lua-5.2

Support Lua 5.2.

Apply patches from these upstream commits:
53e02eaa302bc05e96a18e3882b0e9843b53cf9a (partially)
fd98d953ca93454c66a55aadf2adbeb87de86f69 (with some tweaking)
fe1180f754da5d552c308b61e8129e59039bc559

---
 extra/mtn-hooks/monotone-cvs-ignore.lua            |  2 +-
 src/lua.cc                                         | 40 +++++++++++---
 src/lua.hh                                         | 14 ++---
 src/luaext_parse_basic_io.cc                       |  4 ++
 src/luaext_platform.cc                             | 62 ++++++++++++++++------
 src/std_hooks.lua                                  |  9 +++-
 test/func-testsuite.lua                            |  7 +++
 test/func/automate_get_attributes/__driver__.lua   |  2 +-
 .../func/automate_interface_version/__driver__.lua |  2 +-
 .../automate_inventory_ignore_dirs/__driver__.lua  |  2 +-
 test/func/automate_put_revision/__driver__.lua     |  2 +-
 .../automate_set_drop_attribute/__driver__.lua     |  4 +-
 .../func/automate_stdio_band_output/__driver__.lua | 10 ++--
 test/func/clone_weird_branch_names/__driver__.lua  |  2 +-
 test/func/list_databases/__driver__.lua            |  6 +--
 test/func/list_workspaces/__driver__.lua           |  8 +--
 .../log_--no-files_and_--merges/__driver__.lua     |  4 +-
 test/func/manpage/__driver__.lua                   |  2 +-
 test/func/netsync_negotiation/__driver__.lua       |  8 +--
 test/func/serve-automate-single-run/__driver__.lua |  2 +-
 test/func/serve-automate/__driver__.lua            |  4 +-
 test/func/ssh_agent/__driver__.lua                 |  8 +--
 .../__driver__.lua                                 |  4 +-
 test/func/user_commands/extra_rc                   |  3 +-
 test/src/testlib.lua                               | 39 +++++++-------
 25 files changed, 161 insertions(+), 89 deletions(-)

diff --git a/extra/mtn-hooks/monotone-cvs-ignore.lua b/extra/mtn-hooks/monotone-cvs-ignore.lua
index 6a59d12..0e9feb5 100644
--- extra/mtn-hooks/monotone-cvs-ignore.lua
+++ extra/mtn-hooks/monotone-cvs-ignore.lua
@@ -23,7 +23,7 @@ do

       local handle, msg = io.open(dir .. ".cvsignore")
       if (handle) then
-	 for line in handle:lines(dir .. ".cvsignore") do
+	 for line in handle:lines() do
 	    pat2 = _glob_to_pattern(line) .. "$"
 	    if (string.find(name, pat1 .. pat2)) then
 	       return true
diff --git a/src/lua.cc b/src/lua.cc
index 29f1033..9456c64 100644
--- src/lua.cc
+++ src/lua.cc
@@ -44,7 +44,11 @@ dump_stack(lua_State * st)
     switch (t) {
     case LUA_TSTRING:  /* strings */
       out += '`';
+#ifdef lua_strlen
       out += string(lua_tostring(st, i), lua_strlen(st, i));
+#else
+      out += string(lua_tostring(st, i), lua_rawlen(st, i));
+#endif
       out += '\'';
       break;

@@ -95,7 +99,11 @@ void
 Lua::report_error()
 {
 //  I(lua_isstring(st, -1));
+#ifdef lua_strlen
   string err = string(lua_tostring(st, -1), lua_strlen(st, -1));
+#else
+  string err = string(lua_tostring(st, -1), lua_rawlen(st, -1));
+#endif
   W(i18n_format("%s") % err);
   L(FL("lua stack: %s") % dump_stack(st));
   lua_pop(st, 1);
@@ -107,7 +115,11 @@ Lua::check_stack(int count)
 {
   if (!lua_checkstack(st, count))
     {
+#ifdef LUAI_MAXCSTACK
       fail((FL("lua stack limit '%d' reached") % LUAI_MAXCSTACK).str());
+#else
+      fail((FL("lua stack limit '%d' reached") % LUAI_MAXSTACK).str());
+#endif
       return false;
     }
   return true;
@@ -119,17 +131,27 @@ Lua &
 Lua::get(int idx)
 {
   if (failed) return *this;
-  if (!lua_istable (st, idx))
-    {
-      fail("istable() in get");
-      return *this;
-    }
   if (lua_gettop (st) < 1)
     {
       fail("stack top > 0 in get");
       return *this;
     }
-  lua_gettable(st, idx);
+  if (idx)
+    {
+      if (!lua_istable (st, idx))
+        {
+          fail("istable() in get");
+          return *this;
+        }
+      lua_gettable(st, idx);
+    }
+  else
+    {
+      string name;
+      extract_str(name);
+      pop();
+      lua_getglobal(st, name.c_str());
+    }
   return *this;
 }

@@ -194,7 +216,11 @@ Lua::extract_str_nolog(string & str)
       fail("isstring() in extract_str");
       return *this;
     }
+#ifdef lua_strlen
   str = string(lua_tostring(st, -1), lua_strlen(st, -1));
+#else
+  str = string(lua_tostring(st, -1), lua_rawlen(st, -1));
+#endif
   return *this;
 }

@@ -460,7 +486,7 @@ void add_functions(lua_State * st)
         {
           lua_newtable(st);
           lua_pushvalue(st, -1);
-          lua_setfield(st, LUA_GLOBALSINDEX, table.c_str());
+          lua_setglobal(st, table.c_str());
         }
       for (luaext::fmap::const_iterator j = i->second.begin();
            j != i->second.end(); ++j)
diff --git a/src/lua.hh b/src/lua.hh
index ae87329..6f9783a 100644
--- src/lua.hh
+++ src/lua.hh
@@ -37,13 +37,13 @@ Lua
   void report_error();
   bool check_stack(int count);

-  // getters
-  Lua & get(int idx = LUA_GLOBALSINDEX);
-  Lua & get_fn(int idx = LUA_GLOBALSINDEX);
-  Lua & get_tab(int idx = LUA_GLOBALSINDEX);
-  Lua & get_str(int idx = LUA_GLOBALSINDEX);
-  Lua & get_num(int idx = LUA_GLOBALSINDEX);
-  Lua & get_bool(int idx = LUA_GLOBALSINDEX);
+  // getters (0 is an invalid index in lua, and is used here to represent the global table)
+  Lua & get(int idx = 0);
+  Lua & get_fn(int idx = 0);
+  Lua & get_tab(int idx = 0);
+  Lua & get_str(int idx = 0);
+  Lua & get_num(int idx = 0);
+  Lua & get_bool(int idx = 0);

   // extractors
   Lua & extract_str_nolog(std::string & str);
diff --git a/src/luaext_parse_basic_io.cc b/src/luaext_parse_basic_io.cc
index 84cea98..4d2308a 100644
--- src/luaext_parse_basic_io.cc
+++ src/luaext_parse_basic_io.cc
@@ -23,7 +23,11 @@ LUAEXT(parse_basic_io, )
   // followed by one or more string or hex values. It returns a table of
   // lines.
   vector<pair<string, vector<string> > > res;
+#ifdef lua_strlen
   const string str(luaL_checkstring(LS, -1), lua_strlen(LS, -1));
+#else
+  const string str(luaL_checkstring(LS, -1), lua_rawlen(LS, -1));
+#endif
   basic_io::input_source in(str, "monotone_parse_basic_io_for_lua");
   in.made_from = origin::user;
   basic_io::tokenizer tok(in);
diff --git a/src/luaext_platform.cc b/src/luaext_platform.cc
index 643250c..c89b45a 100644
--- src/luaext_platform.cc
+++ src/luaext_platform.cc
@@ -96,31 +96,58 @@ LUAEXT(spawn_redirected, )
   return 1;
 }

-// borrowed from lua/liolib.cc
-// Note that making C functions that return FILE* in Lua is tricky
+// Making C functions that return FILE* in Lua is tricky. Especially if it
+// actually needs to work with multiple lua versions.
+//
+// The following routines are inspired by lua/liolib.c from both versions.
+// The mtn_lua_Stream struct is closer to the 5.2 variant, but the
+// additional field compared to 5.1 (which only uses FILE*) shouldn't hurt
+// in Lua 5.1.
+//
 // There is a Lua FAQ entitled:
 // "Why does my library-created file segfault on :close() but work otherwise?"
+//
+// However, it's advice seems out-dated and applies more to 5.1.
+
+typedef struct mtn_lua_Stream {
+  FILE *f;
+  lua_CFunction closef;
+} mtn_lua_Stream;
+
+#define topfile(LS)     ((mtn_lua_Stream *)luaL_checkudata(LS, 1, LUA_FILEHANDLE))

-#define topfile(LS)     ((FILE **)luaL_checkudata(LS, 1, LUA_FILEHANDLE))
+static int io_pclose (lua_State *LS) {
+  mtn_lua_Stream *s = topfile(LS);
+
+  // Note that in Lua 5.2, aux_close() already resets s->closef to NULL and for
+  // Lua 5.1, it's not relevant, at all. But we've set it to &io_pclose(), so
+  // contents of s->closef different between Lua versions.
+
+  int ok;
+  if (s->f != NULL)
+    ok = (pclose(s->f) == 0);
+
+  s->f = NULL;
+  s->closef = NULL;  // just to be extra sure this won't do any harm

-static int io_fclose (lua_State *LS) {
-  FILE **p = topfile(LS);
-  int ok = (fclose(*p) == 0);
-  *p = NULL;
   lua_pushboolean(LS, ok);
   return 1;
 }

-static FILE **newfile (lua_State *LS) {
-  FILE **pf = (FILE **)lua_newuserdata(LS, sizeof(FILE *));
-  *pf = NULL;  /* file handle is currently `closed' */
+static mtn_lua_Stream *newstream (lua_State *LS) {
+  mtn_lua_Stream *s = (mtn_lua_Stream *)lua_newuserdata(LS, sizeof(mtn_lua_Stream));
+  s->f = NULL;  /* file handle is currently `closed' */
+  s->closef = NULL;
   luaL_getmetatable(LS, LUA_FILEHANDLE);
   lua_setmetatable(LS, -2);

-  lua_pushcfunction(LS, io_fclose);
+#ifdef LUA_ENVIRONINDEX
+  // Lua 5.2 removes C function environments
+  lua_pushcfunction(LS, io_pclose);
   lua_setfield(LS, LUA_ENVIRONINDEX, "__close");
+#endif

-  return pf;
+  return s;
 }

 LUAEXT(spawn_pipe, )
@@ -136,12 +163,13 @@ LUAEXT(spawn_pipe, )
   for (i=0; i<n; i++) argv[i] = (char*)luaL_checkstring(LS,  i+1);
   argv[i] = NULL;

-  int infd;
-  FILE **inpf = newfile(LS);
-  int outfd;
-  FILE **outpf = newfile(LS);
+  mtn_lua_Stream *ins = newstream(LS);
+  ins->closef = &io_pclose;
+
+  mtn_lua_Stream *outs = newstream(LS);
+  outs->closef = &io_pclose;

-  pid = process_spawn_pipe(argv, inpf, outpf);
+  pid = process_spawn_pipe(argv, &ins->f, &outs->f);
   free(argv);

   lua_pushnumber(LS, pid);
diff --git a/src/std_hooks.lua b/src/std_hooks.lua
index bfef561..7099f83 100644
--- src/std_hooks.lua
+++ src/std_hooks.lua
@@ -10,6 +10,13 @@
 -- this is the standard set of lua hooks for monotone;
 -- user-provided files can override it or add to it.

+-- Since Lua 5.2, unpack and loadstrings are deprecated and are either moved
+-- to table.unpack() or replaced by load(). If lua was compiled without
+-- LUA_COMPAT_UNPACK and/or LUA_COMPAT_LOADSTRING, these two are not
+-- available and we add a similar compatibility layer, ourselves.
+unpack = unpack or table.unpack
+loadstring = loadstring or load
+
 function temp_file(namehint)
    local tdir
    tdir = os.getenv("TMPDIR")
@@ -1465,7 +1472,7 @@ do
       return true, warning
    end
    function push_hook_functions(functions)
-      local n = table.maxn(hook_functions) + 1
+      local n = #hook_functions + 1
       return add_hook_functions(functions, n)
    end

diff --git a/test/func-testsuite.lua b/test/func-testsuite.lua
index 64a6f26..454cd9c 100755
--- test/func-testsuite.lua
+++ test/func-testsuite.lua
@@ -10,6 +10,13 @@
 monotone_path = nil
 no_network_tests = false

+-- Since Lua 5.2, unpack and loadstrings are deprecated and are either moved
+-- to table.unpack() or replaced by load(). If lua was compiled without
+-- LUA_COMPAT_UNPACK and/or LUA_COMPAT_LOADSTRING, these two are not
+-- available and we add a similar compatibility layer, ourselves.
+unpack = unpack or table.unpack
+loadstring = loadstring or load
+
 function safe_mtn(...)
   if monotone_path == nil then
     monotone_path = os.getenv("mtn")
diff --git a/test/func/automate_get_attributes/__driver__.lua b/test/func/automate_get_attributes/__driver__.lua
index 2e92654..eb91015 100644
--- test/func/automate_get_attributes/__driver__.lua
+++ test/func/automate_get_attributes/__driver__.lua
@@ -28,7 +28,7 @@ check(mtn("automate", "get_attributes", "testfile"), 0, true, true)
 check(fsize("stderr") == 0)
 parsed = parse_basic_io(readfile("stdout"))
 -- make sure the output generated 8 stanzas
-check(table.getn(parsed) == 8)
+check(#parsed == 8)
 lastkey = ""
 checked = {}
 for _,l in pairs(parsed) do
diff --git a/test/func/automate_interface_version/__driver__.lua b/test/func/automate_interface_version/__driver__.lua
index d969d7d..7ff79e9 100644
--- test/func/automate_interface_version/__driver__.lua
+++ test/func/automate_interface_version/__driver__.lua
@@ -7,4 +7,4 @@ rename("stdout", "a_v")
 -- MinGW's wc produces "      1" as output.  Arithmetic comparison works, string comparison doesn't
 check(numlines("a_v") == 1)
 -- This is really ^[0-9]+\.[0-9]+$, but m4 is obfuscatory.
-check(qgrep("^[0-9]+\.[0-9]+$", "a_v"))
+check(qgrep("^[0-9]+\\.[0-9]+$", "a_v"))
diff --git a/test/func/automate_inventory_ignore_dirs/__driver__.lua b/test/func/automate_inventory_ignore_dirs/__driver__.lua
index bfb5c25..72a89bb 100644
--- test/func/automate_inventory_ignore_dirs/__driver__.lua
+++ test/func/automate_inventory_ignore_dirs/__driver__.lua
@@ -14,7 +14,7 @@ function sortContentsByLine(input)
   table.insert(lines, string.sub(input, theStart))
   table.sort(lines)

-  local len = table.getn(lines)
+  local len = #lines
   local output = lines[1]
   for i = 2, len do
     output = output .. delimiter .. lines[i]
diff --git a/test/func/automate_put_revision/__driver__.lua b/test/func/automate_put_revision/__driver__.lua
index 2626ec3..32bdacb 100644
--- test/func/automate_put_revision/__driver__.lua
+++ test/func/automate_put_revision/__driver__.lua
@@ -33,5 +33,5 @@ check(mtn("automate", "put_revision", rev), 3, false, false)
 -- but this should work (tests that we can use put_revision to commit a
 -- single-parent revision)
 check(mtn("automate", "put_file", ""), 0, false, false)
-rev = "format_version \"1\"\n\nnew_manifest [0000000000000000000000000000000000000000]\n\nold_revision [4c2c1d846fa561601254200918fba1fd71e6795d]\n\patch \"foo\"\n from [5bf1fd927dfb8679496a2e6cf00cbe50c1c87145] to [da39a3ee5e6b4b0d3255bfef95601890afd80709]\n"
+rev = "format_version \"1\"\n\nnew_manifest [0000000000000000000000000000000000000000]\n\nold_revision [4c2c1d846fa561601254200918fba1fd71e6795d]\n\npatch \"foo\"\n from [5bf1fd927dfb8679496a2e6cf00cbe50c1c87145] to [da39a3ee5e6b4b0d3255bfef95601890afd80709]\n"
 check(mtn("automate", "put_revision", rev), 0, false, false)
diff --git a/test/func/automate_set_drop_attribute/__driver__.lua b/test/func/automate_set_drop_attribute/__driver__.lua
index 5369cd9..12ff4dc 100644
--- test/func/automate_set_drop_attribute/__driver__.lua
+++ test/func/automate_set_drop_attribute/__driver__.lua
@@ -25,7 +25,7 @@ check(mtn("automate", "set_attribute", "testfile", "foo", "bar"), 0, false, fals
 check(mtn("automate", "get_attributes", "testfile"), 0, true, false)
 parsed = parse_basic_io(readfile("stdout"))

-check(table.getn(parsed) == 2)
+check(#parsed == 2)
 for _,l in pairs(parsed) do
     if l.name == "attr" then
         key = l.values[1]
@@ -44,7 +44,7 @@ check(mtn("automate", "drop_attribute", "testfile", "foo"), 0, true, true)
 -- check if it has been really dropped
 check(mtn("automate", "get_attributes", "testfile"), 0, true, false)
 parsed = parse_basic_io(readfile("stdout"))
-check(table.getn(parsed) == 0)
+check(#parsed == 0)

 -- check if it escalates properly if there is no such attr to drop
 check(mtn("automate", "drop_attribute", "testfile", "foo"), 1, false, true)
diff --git a/test/func/automate_stdio_band_output/__driver__.lua b/test/func/automate_stdio_band_output/__driver__.lua
index 4262d0e..88c8d63 100755
--- test/func/automate_stdio_band_output/__driver__.lua
+++ test/func/automate_stdio_band_output/__driver__.lua
@@ -4,13 +4,13 @@ mtn_setup()

 -- check informational messages, warnings and errors
 out = run_stdio("l8:bandtest4:infoe", 0, 0, "p")
-check(type(out) == "table" and table.maxn(out) == 1)
+check(type(out) == "table" and #out == 1)

 out = run_stdio("l8:bandtest7:warninge", 0, 0, "w")
-check(type(out) == "table" and table.maxn(out) == 1)
+check(type(out) == "table" and #out == 1)

 out = run_stdio("l8:bandtest5:errore", 2, 0, "e")
-check(type(out) == "table" and table.maxn(out) == 1)
+check(type(out) == "table" and #out == 1)

 -- check tickers
 tickers = run_stdio("l8:bandtest6:tickere", 0, 0, "t")
@@ -38,7 +38,7 @@ end
 ticker_data = {}
 for _,tick in ipairs(tickers) do
     ticks = split(tick, ";")
-    check(table.maxn(ticks) > 0)
+    check(#ticks > 0)
     for _,mtick in ipairs(ticks) do
         if string.len(mtick) > 0 then
             local begin,End,short,ticktype,content =
@@ -78,6 +78,6 @@ for _,tick in ipairs(tickers) do
 end

 -- finally check if all tickers are completed
-check(table.maxn(ticker_data) == 0)
+check(#ticker_data == 0)


diff --git a/test/func/clone_weird_branch_names/__driver__.lua b/test/func/clone_weird_branch_names/__driver__.lua
index 4948a72..a97c6ea 100644
--- test/func/clone_weird_branch_names/__driver__.lua
+++ test/func/clone_weird_branch_names/__driver__.lua
@@ -7,7 +7,7 @@ commit("my-branch[1,2]-1^3")

 copy("test.db", "test-clone.db")
 -- some of the special chars need to get double-escaped to get "through"
-testURI="file://" .. test.root .. "/test-clone.db?my-branch\\\[1,2\\\]-1^3"
+testURI="file://" .. test.root .. "/test-clone.db?my-branch\\[1,2\\]-1^3"

 check(nodb_mtn("clone", testURI), 0, false, false)
 check(exists("my-branch[1,2]-1^3"))
diff --git a/test/func/list_databases/__driver__.lua b/test/func/list_databases/__driver__.lua
index e3da0e9..48cd75c 100644
--- test/func/list_databases/__driver__.lua
+++ test/func/list_databases/__driver__.lua
@@ -25,15 +25,15 @@ check(mt("db", "init", "-d", ":bar"), 0, false, false)
 check(exists("managed_databases/bar.mtn"))

 check(mt("ls", "dbs"), 0, true, false)
-check(qgrep(":bar.mtn.+in.+list_databases\/managed_databases", "stdout"))
+check(qgrep(":bar.mtn.+in.+list_databases/managed_databases", "stdout"))
 check(qgrep("\tno known valid workspaces", "stdout"))

 check(mt("setup", "-d", ":bar", "-b", "test.foo.branch", "test_foo"), 0, false, false)

 check(mt("ls", "dbs"), 0, true, false)
 check(not qgrep("\tno known valid workspaces", "stdout"))
-check(qgrep("\ttest.foo.branch.+in.+list_databases\/test_foo", "stdout"))
+check(qgrep("\ttest.foo.branch.+in.+list_databases/test_foo", "stdout"))

 check(rename("managed_databases/bar.mtn", "managed_databases/bar.db"))
 check(mt("ls", "dbs"), 0, true, false)
-check(qgrep(":bar.db.+in.+list_databases\/managed_databases", "stdout"))
+check(qgrep(":bar.db.+in.+list_databases/managed_databases", "stdout"))
diff --git a/test/func/list_workspaces/__driver__.lua b/test/func/list_workspaces/__driver__.lua
index 06dbfef..8895ed4 100644
--- test/func/list_workspaces/__driver__.lua
+++ test/func/list_workspaces/__driver__.lua
@@ -10,17 +10,17 @@ check(samelines("stdout", {"no known valid workspaces"}))
 check(raw_mtn("setup", "-d", "test.mtn", "-b", "test.branch1", "work1"), 0, false, false)

 check(raw_mtn("ls", "workspaces", "-d", "test.mtn"), 0, true, false)
-check(qgrep("test.branch1.+in.+list_workspaces\/work1", "stdout"))
+check(qgrep("test.branch1.+in.+list_workspaces/work1", "stdout"))

 check(raw_mtn("setup", "-d", "test.mtn", "-b", "test.branch2", "work2"), 0, false, false)
 check(rename("work1", "work3"))

 check(raw_mtn("ls", "workspaces", "-d", "test.mtn"), 0, true, false)
-check(qgrep("test.branch2.+in.+list_workspaces\/work2", "stdout"))
-check(not qgrep("test.branch1.+in.+list_workspaces\/work1", "stdout"))
+check(qgrep("test.branch2.+in.+list_workspaces/work2", "stdout"))
+check(not qgrep("test.branch1.+in.+list_workspaces/work1", "stdout"))

 check(indir("work3", raw_mtn("register_workspace", "-d", "../test.mtn")), 0, false, false)

 check(raw_mtn("ls", "workspaces", "-d", "test.mtn"), 0, true, false)
-check(qgrep("test.branch1.+in.+list_workspaces\/work3", "stdout"))
+check(qgrep("test.branch1.+in.+list_workspaces/work3", "stdout"))

diff --git a/test/func/log_--no-files_and_--merges/__driver__.lua b/test/func/log_--no-files_and_--merges/__driver__.lua
index b27551e..de4d26d 100644
--- test/func/log_--no-files_and_--merges/__driver__.lua
+++ test/func/log_--no-files_and_--merges/__driver__.lua
@@ -29,8 +29,8 @@ R2=base_revision()

 -- check that merge is included by default
 check(mtn("log"), 0, true, false)
-check(qgrep("^[\\|\\\\\/ ]+Revision.*"..R2, "stdout"))
+check(qgrep("^[\\|\\\\/ ]+Revision.*"..R2, "stdout"))

 -- and that it is excluded by --no-merges
 check(mtn("log", "--no-merges"), 0, true, false)
-check(not qgrep("^[\\|\\\\\/ ]+Revision.*"..R2, "stdout"))
+check(not qgrep("^[\\|\\\\/ ]+Revision.*"..R2, "stdout"))
diff --git a/test/func/manpage/__driver__.lua b/test/func/manpage/__driver__.lua
index 775714e..38e5ee7 100644
--- test/func/manpage/__driver__.lua
+++ test/func/manpage/__driver__.lua
@@ -5,7 +5,7 @@ rename("stdout", "manpage")

 -- check for a proper header line
 check(mtn("version"), 0, true, false)
-local s,e,version = string.find(readfile("stdout"), "(monotone %d+\.%d+%S*)")
+local s,e,version = string.find(readfile("stdout"), "(monotone %d+%.%d+%S*)")
 check(qgrep(".TH \"monotone\" 1 \"[0-9]{4}-[0-9]{2}-[0-9]{2}\" \"" .. version .. "\"", "manpage"))

 -- check required sections
diff --git a/test/func/netsync_negotiation/__driver__.lua b/test/func/netsync_negotiation/__driver__.lua
index 2efe421..c776f93 100644
--- test/func/netsync_negotiation/__driver__.lua
+++ test/func/netsync_negotiation/__driver__.lua
@@ -87,10 +87,10 @@ function check_same_revs(cmd1, cmd2)
    check(cmd2, 0, true, false)
    local data2 = {}
    for l in io.lines("stdout") do table.insert(data2, l) end
-   L("Command 1 has ", table.getn(data1), " lines.")
-   L("Command 2 has ", table.getn(data2), " lines.")
-   check(table.getn(data1) == table.getn(data2))
-   for i = 1, table.getn(data1) do
+   L("Command 1 has ", #data1, " lines.")
+   L("Command 2 has ", #data2, " lines.")
+   check(#data1 == #data2)
+   for i = 1, #data1 do
       local hash_len = 40
       check(data1[i]:sub(1, hash_len) == data2[i]:sub(1, hash_len))
    end
diff --git a/test/func/serve-automate-single-run/__driver__.lua b/test/func/serve-automate-single-run/__driver__.lua
index 87b1ab7..b65b9c1 100644
--- test/func/serve-automate-single-run/__driver__.lua
+++ test/func/serve-automate-single-run/__driver__.lua
@@ -28,7 +28,7 @@ server = netsync.start({"--rcfile=allow-automate.lua"})

 check(mtn2("automate", "remote", "--remote-stdio-host", server.address,
     "interface_version"), 0, true, false)
-check(qgrep("^[0-9]{2,}\.[0-9]+$", "stdout"))
+check(qgrep("^[0-9]{2,}\\.[0-9]+$", "stdout"))

 check(mtn2("automate", "remote", "--remote-stdio-host", server.address,
     "leaves"), 0, true, false)
diff --git a/test/func/serve-automate/__driver__.lua b/test/func/serve-automate/__driver__.lua
index 32b2eaf..9e993dc 100644
--- test/func/serve-automate/__driver__.lua
+++ test/func/serve-automate/__driver__.lua
@@ -14,7 +14,7 @@ server = netsync.start({"--rcfile=deny-automate.lua"})

 local errors = run_remote_stdio(server, "l17:interface_versione", 1, 0, "e")
 check(
-    table.maxn(errors) == 1 and
+    #errors == 1 and
     errors[1] == "misuse: Sorry, you aren't allowed to do that."
 )

@@ -45,7 +45,7 @@ check(

 local errors = run_remote_stdio(server, "l5:stdioe", 1, 0, "e")
 check(
-    table.maxn(errors) == 1 and
+    #errors == 1 and
     errors[1] == "error: sorry, that can't be run remotely or over stdio"
 )

diff --git a/test/func/ssh_agent/__driver__.lua b/test/func/ssh_agent/__driver__.lua
index d927360..a36ce90 100644
--- test/func/ssh_agent/__driver__.lua
+++ test/func/ssh_agent/__driver__.lua
@@ -81,7 +81,7 @@ end

 check({"ssh-agent"}, 0, true, false)
 for line in io.lines("stdout") do
-   for k, v in string.gmatch(line, "([%w_]+)=([%w/\.-]+)") do
+   for k, v in string.gmatch(line, "([%w_]+)=([%w/%.-]+)") do
       set_env(k, v)
    end
 end
@@ -91,7 +91,7 @@ check(mtn("ssh_agent_add"), 0, false, false)
 check({"ssh-add", "-l"}, 0, true, false)
 ok = false
 for line in io.lines("stdout") do
-    for k in string.gmatch(line, "tester@test\.net") do
+    for k in string.gmatch(line, "tester@test%.net") do
     	ok = true
     end
 end
@@ -288,7 +288,7 @@ check(mtn("ssh_agent_add", "--key", "test2@tester.net"), 0, false, false)
 check({"ssh-add", "-l"}, 0, true, false)
 ok = false
 for line in io.lines("stdout") do
-    for k in string.gmatch(line, "test2@tester\.net") do
+    for k in string.gmatch(line, "test2@tester%.net") do
     	ok = true
     end
 end
@@ -338,7 +338,7 @@ check(mtn("ssh_agent_add", "--key", "test_pass@tester.net"), 0, false, false, "p
 check({"ssh-add", "-l"}, 0, true, false)
 ok = false
 for line in io.lines("stdout") do
-    for k in string.gmatch(line, "test_pass@tester\.net") do
+    for k in string.gmatch(line, "test_pass@tester%.net") do
     	ok = true
     end
 end
diff --git a/test/func/two_parent_workspace_inodeprints/__driver__.lua b/test/func/two_parent_workspace_inodeprints/__driver__.lua
index bd6c558..66d5150 100644
--- test/func/two_parent_workspace_inodeprints/__driver__.lua
+++ test/func/two_parent_workspace_inodeprints/__driver__.lua
@@ -19,13 +19,13 @@ check(mtn("merge_into_workspace", other), 0, false, false)

 -- check that we've got the expected initial status
 check(mtn("status"), 0, true, false)
-check(qgrep("patched[ 	]\+foo", "stdout"))
+check(qgrep("patched[ 	]+foo", "stdout"))

 -- enable inodeprints
 writefile("_MTN/inodeprints")

 check(mtn("status"), 0, true, false)
-check(qgrep("patched[ 	]\+foo", "stdout"))
+check(qgrep("patched[ 	]+foo", "stdout"))

 sleep(5)

diff --git a/test/func/user_commands/extra_rc b/test/func/user_commands/extra_rc
index 2ec5f9f..aad3764 100644
--- test/func/user_commands/extra_rc
+++ test/func/user_commands/extra_rc
@@ -5,7 +5,8 @@ function check_head(...)
       io.stderr:write("automate call failed\n")
       return
     end
-    arghead = unpack(arg)
+    local arg = {...}
+    arghead = arg[1]
     heads = heads:gsub("^%s*(.-)%s*$", "%1")	-- trim leading and trailing whitespace
     if (heads == arghead) then
         io.write("heads are equal\n")
diff --git a/test/src/testlib.lua b/test/src/testlib.lua
index 6d21a93..19eb278 100644
--- test/src/testlib.lua
+++ test/src/testlib.lua
@@ -30,6 +30,13 @@ files = {stdout = nil, stdin = nil, stderr = nil}
 -- for convenience, this is the first word of what get_ostype() returns.
 ostype = string.sub(get_ostype(), 1, string.find(get_ostype(), " ")-1)

+-- Since Lua 5.2, unpack and loadstrings are deprecated and are either moved
+-- to table.unpack() or replaced by load(). If lua was compiled without
+-- LUA_COMPAT_UNPACK and/or LUA_COMPAT_LOADSTRING, these two are not
+-- available and we add a similar compatibility layer, ourselves.
+unpack = unpack or table.unpack
+loadstring = loadstring or load
+
 -- table of per-test values
 test = {}
 -- misc per-test values
@@ -310,17 +317,11 @@ end
 -- to want to include from the dir for the current test,
 -- since in that case it could just go in the driver file.
 function include(name)
-  local func, e = loadfile(testdir.."/"..name)
-  if func == nil then err(e, 2) end
-  setfenv(func, getfenv(2))
-  func()
+  dofile(testdir.."/"..name)
 end

 function includecommon(name)
-  local func, e = loadfile(srcdir.."/common/"..name)
-  if func == nil then err(e, 2) end
-  setfenv(func, getfenv(2))
-  func()
+  dofile(srcdir.."/common/"..name)
 end

 function trim(str)
@@ -479,12 +480,11 @@ end
 function samelines(f, t)
   local fl = {}
   for l in io.lines(f) do table.insert(fl, l) end
-  if not (table.getn(fl) == table.getn(t)) then
-    L(locheader(), string.format("file has %s lines; table has %s\n",
-                                 table.getn(fl), table.getn(t)))
+  if not (#fl == #t) then
+    L(locheader(), string.format("file has %s lines; table has %s\n", #fl, #t))
     return false
   end
-  for i=1,table.getn(t) do
+  for i=1,#t do
     if fl[i] ~= t[i] then
       if fl[i] then
         L(locheader(), string.format("file[%d] = '%s'; table[%d] = '%s'\n",
@@ -502,12 +502,11 @@ end
 function greplines(f, t)
   local fl = {}
   for l in io.lines(f) do table.insert(fl, l) end
-  if not (table.getn(fl) == table.getn(t)) then
-    L(locheader(), string.format("file has %s lines; table has %s\n",
-                                 table.getn(fl), table.getn(t)))
+  if not (#fl == #t) then
+    L(locheader(), string.format("file has %s lines; table has %s\n", #fl, #t))
     return false
   end
-  for i=1,table.getn(t) do
+  for i=1,#t do
     if not regex.search(t[i], fl[i]) then
       L(locheader(), string.format("file[i] = '%s'; table[i] = '%s'\n",
                                    fl[i], t[i]))
@@ -577,7 +576,7 @@ function tail(...)
     local mylines = {}
     for l in io.lines(file) do
       table.insert(mylines, l)
-      if table.getn(mylines) > num then
+      if #mylines > num then
         table.remove(mylines, 1)
       end
     end
@@ -932,8 +931,8 @@ function run_tests(debugging, list_only, run_dir, logname, args, progress)
     if _1 then
       l = l + 0
       r = r + 0
-      if l < 1 then l = table.getn(tests) + l + 1 end
-      if r < 1 then r = table.getn(tests) + r + 1 end
+      if l < 1 then l = #tests + l + 1 end
+      if r < 1 then r = #tests + r + 1 end
       if l > r then l,r = r,l end
       for j = l,r do
         torun[j] = tests[j]
@@ -941,7 +940,7 @@ function run_tests(debugging, list_only, run_dir, logname, args, progress)
       run_all = false
     elseif string.find(a, "^-?%d+$") then
       r = a + 0
-      if r < 1 then r = table.getn(tests) + r + 1 end
+      if r < 1 then r = #tests + r + 1 end
       torun[r] = tests[r]
       run_all = false
     else
-- 
tg: (1150daa..) lua-5.2 (depends on: master)



-Olaf.
-- 
___ Olaf 'Rhialto' Seibert  -- The Doctor: No, 'eureka' is Greek for
\X/ rhialto/at/xs4all.nl    -- 'this bath is too hot.'

>Release-Note:

>Audit-Trail:
From: Rhialto <rhialto@falu.nl>
To: gnats-bugs@NetBSD.org
Cc: rhialto@falu.nl
Subject: Re: pkg/48301: Make devel/monotone build with lua 5.2 (with patch)
Date: Sun, 20 Oct 2013 22:20:07 +0200

 --KsGdsel6WgEHnImy
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable

 I have two additional changes to the patch I presented before.

 - pclose -> fclose
 - initialize ok in io_pclose().

 For reference here is the full thing again, with those changes:


 $Id$

 Source: http://pkgs.fedoraproject.org/cgit/monotone.git/plain/monotone-1.0-=
 lua-5.2.patch
 via http://pkgs.fedoraproject.org/cgit/monotone.git/tree/

 - Edited path names to make them apply without -p1.
 - pclose -> fclose
 - initialize ok in io_pclose().

 =46rom: Thomas Moschny <thomas.moschny@gmx.de>
 Subject: [PATCH] lua-5.2

 Support Lua 5.2.

 Apply patches from these upstream commits:
 53e02eaa302bc05e96a18e3882b0e9843b53cf9a (partially)
 fd98d953ca93454c66a55aadf2adbeb87de86f69 (with some tweaking)
 fe1180f754da5d552c308b61e8129e59039bc559

 ---
  extra/mtn-hooks/monotone-cvs-ignore.lua            |  2 +-
  src/lua.cc                                         | 40 +++++++++++---
  src/lua.hh                                         | 14 ++---
  src/luaext_parse_basic_io.cc                       |  4 ++
  src/luaext_platform.cc                             | 62 ++++++++++++++++--=
 ----
  src/std_hooks.lua                                  |  9 +++-
  test/func-testsuite.lua                            |  7 +++
  test/func/automate_get_attributes/__driver__.lua   |  2 +-
  .../func/automate_interface_version/__driver__.lua |  2 +-
  .../automate_inventory_ignore_dirs/__driver__.lua  |  2 +-
  test/func/automate_put_revision/__driver__.lua     |  2 +-
  .../automate_set_drop_attribute/__driver__.lua     |  4 +-
  .../func/automate_stdio_band_output/__driver__.lua | 10 ++--
  test/func/clone_weird_branch_names/__driver__.lua  |  2 +-
  test/func/list_databases/__driver__.lua            |  6 +--
  test/func/list_workspaces/__driver__.lua           |  8 +--
  .../log_--no-files_and_--merges/__driver__.lua     |  4 +-
  test/func/manpage/__driver__.lua                   |  2 +-
  test/func/netsync_negotiation/__driver__.lua       |  8 +--
  test/func/serve-automate-single-run/__driver__.lua |  2 +-
  test/func/serve-automate/__driver__.lua            |  4 +-
  test/func/ssh_agent/__driver__.lua                 |  8 +--
  .../__driver__.lua                                 |  4 +-
  test/func/user_commands/extra_rc                   |  3 +-
  test/src/testlib.lua                               | 39 +++++++-------
  25 files changed, 161 insertions(+), 89 deletions(-)

 diff --git a/extra/mtn-hooks/monotone-cvs-ignore.lua b/extra/mtn-hooks/mono=
 tone-cvs-ignore.lua
 index 6a59d12..0e9feb5 100644
 --- extra/mtn-hooks/monotone-cvs-ignore.lua
 +++ extra/mtn-hooks/monotone-cvs-ignore.lua
 @@ -23,7 +23,7 @@ do
 =20
        local handle, msg =3D io.open(dir .. ".cvsignore")
        if (handle) then
 -	 for line in handle:lines(dir .. ".cvsignore") do
 +	 for line in handle:lines() do
  	    pat2 =3D _glob_to_pattern(line) .. "$"
  	    if (string.find(name, pat1 .. pat2)) then
  	       return true
 diff --git a/src/lua.cc b/src/lua.cc
 index 29f1033..9456c64 100644
 --- src/lua.cc
 +++ src/lua.cc
 @@ -44,7 +44,11 @@ dump_stack(lua_State * st)
      switch (t) {
      case LUA_TSTRING:  /* strings */
        out +=3D '`';
 +#ifdef lua_strlen
        out +=3D string(lua_tostring(st, i), lua_strlen(st, i));
 +#else
 +      out +=3D string(lua_tostring(st, i), lua_rawlen(st, i));
 +#endif
        out +=3D '\'';
        break;
 =20
 @@ -95,7 +99,11 @@ void
  Lua::report_error()
  {
  //  I(lua_isstring(st, -1));
 +#ifdef lua_strlen
    string err =3D string(lua_tostring(st, -1), lua_strlen(st, -1));
 +#else
 +  string err =3D string(lua_tostring(st, -1), lua_rawlen(st, -1));
 +#endif
    W(i18n_format("%s") % err);
    L(FL("lua stack: %s") % dump_stack(st));
    lua_pop(st, 1);
 @@ -107,7 +115,11 @@ Lua::check_stack(int count)
  {
    if (!lua_checkstack(st, count))
      {
 +#ifdef LUAI_MAXCSTACK
        fail((FL("lua stack limit '%d' reached") % LUAI_MAXCSTACK).str());
 +#else
 +      fail((FL("lua stack limit '%d' reached") % LUAI_MAXSTACK).str());
 +#endif
        return false;
      }
    return true;
 @@ -119,17 +131,27 @@ Lua &
  Lua::get(int idx)
  {
    if (failed) return *this;
 -  if (!lua_istable (st, idx))
 -    {
 -      fail("istable() in get");
 -      return *this;
 -    }
    if (lua_gettop (st) < 1)
      {
        fail("stack top > 0 in get");
        return *this;
      }
 -  lua_gettable(st, idx);
 +  if (idx)
 +    {
 +      if (!lua_istable (st, idx))
 +        {
 +          fail("istable() in get");
 +          return *this;
 +        }
 +      lua_gettable(st, idx);
 +    }
 +  else
 +    {
 +      string name;
 +      extract_str(name);
 +      pop();
 +      lua_getglobal(st, name.c_str());
 +    }
    return *this;
  }
 =20
 @@ -194,7 +216,11 @@ Lua::extract_str_nolog(string & str)
        fail("isstring() in extract_str");
        return *this;
      }
 +#ifdef lua_strlen
    str =3D string(lua_tostring(st, -1), lua_strlen(st, -1));
 +#else
 +  str =3D string(lua_tostring(st, -1), lua_rawlen(st, -1));
 +#endif
    return *this;
  }
 =20
 @@ -460,7 +486,7 @@ void add_functions(lua_State * st)
          {
            lua_newtable(st);
            lua_pushvalue(st, -1);
 -          lua_setfield(st, LUA_GLOBALSINDEX, table.c_str());
 +          lua_setglobal(st, table.c_str());
          }
        for (luaext::fmap::const_iterator j =3D i->second.begin();
             j !=3D i->second.end(); ++j)
 diff --git a/src/lua.hh b/src/lua.hh
 index ae87329..6f9783a 100644
 --- src/lua.hh
 +++ src/lua.hh
 @@ -37,13 +37,13 @@ Lua
    void report_error();
    bool check_stack(int count);
 =20
 -  // getters
 -  Lua & get(int idx =3D LUA_GLOBALSINDEX);
 -  Lua & get_fn(int idx =3D LUA_GLOBALSINDEX);
 -  Lua & get_tab(int idx =3D LUA_GLOBALSINDEX);
 -  Lua & get_str(int idx =3D LUA_GLOBALSINDEX);
 -  Lua & get_num(int idx =3D LUA_GLOBALSINDEX);
 -  Lua & get_bool(int idx =3D LUA_GLOBALSINDEX);
 +  // getters (0 is an invalid index in lua, and is used here to represent =
 the global table)
 +  Lua & get(int idx =3D 0);
 +  Lua & get_fn(int idx =3D 0);
 +  Lua & get_tab(int idx =3D 0);
 +  Lua & get_str(int idx =3D 0);
 +  Lua & get_num(int idx =3D 0);
 +  Lua & get_bool(int idx =3D 0);
 =20
    // extractors
    Lua & extract_str_nolog(std::string & str);
 diff --git a/src/luaext_parse_basic_io.cc b/src/luaext_parse_basic_io.cc
 index 84cea98..4d2308a 100644
 --- src/luaext_parse_basic_io.cc
 +++ src/luaext_parse_basic_io.cc
 @@ -23,7 +23,11 @@ LUAEXT(parse_basic_io, )
    // followed by one or more string or hex values. It returns a table of
    // lines.
    vector<pair<string, vector<string> > > res;
 +#ifdef lua_strlen
    const string str(luaL_checkstring(LS, -1), lua_strlen(LS, -1));
 +#else
 +  const string str(luaL_checkstring(LS, -1), lua_rawlen(LS, -1));
 +#endif
    basic_io::input_source in(str, "monotone_parse_basic_io_for_lua");
    in.made_from =3D origin::user;
    basic_io::tokenizer tok(in);
 diff --git a/src/luaext_platform.cc b/src/luaext_platform.cc
 index 643250c..c89b45a 100644
 --- src/luaext_platform.cc
 +++ src/luaext_platform.cc
 @@ -96,31 +96,58 @@ LUAEXT(spawn_redirected, )
    return 1;
  }
 =20
 -// borrowed from lua/liolib.cc
 -// Note that making C functions that return FILE* in Lua is tricky
 +// Making C functions that return FILE* in Lua is tricky. Especially if it
 +// actually needs to work with multiple lua versions.
 +//
 +// The following routines are inspired by lua/liolib.c from both versions.
 +// The mtn_lua_Stream struct is closer to the 5.2 variant, but the
 +// additional field compared to 5.1 (which only uses FILE*) shouldn't hurt
 +// in Lua 5.1.
 +//
  // There is a Lua FAQ entitled:
  // "Why does my library-created file segfault on :close() but work otherwi=
 se?"
 +//
 +// However, it's advice seems out-dated and applies more to 5.1.
 +
 +typedef struct mtn_lua_Stream {
 +  FILE *f;
 +  lua_CFunction closef;
 +} mtn_lua_Stream;
 +
 +#define topfile(LS)     ((mtn_lua_Stream *)luaL_checkudata(LS, 1, LUA_FILE=
 HANDLE))
 =20
 -#define topfile(LS)     ((FILE **)luaL_checkudata(LS, 1, LUA_FILEHANDLE))
 +static int io_pclose (lua_State *LS) {
 +  mtn_lua_Stream *s =3D topfile(LS);
 +
 +  // Note that in Lua 5.2, aux_close() already resets s->closef to NULL an=
 d for
 +  // Lua 5.1, it's not relevant, at all. But we've set it to &io_pclose(),=
  so
 +  // contents of s->closef different between Lua versions.
 +
 +  int ok =3D 1;
 +  if (s->f !=3D NULL)
 +    ok =3D (fclose(s->f) =3D=3D 0);
 +
 +  s->f =3D NULL;
 +  s->closef =3D NULL;  // just to be extra sure this won't do any harm
 =20
 -static int io_fclose (lua_State *LS) {
 -  FILE **p =3D topfile(LS);
 -  int ok =3D (fclose(*p) =3D=3D 0);
 -  *p =3D NULL;
    lua_pushboolean(LS, ok);
    return 1;
  }
 =20
 -static FILE **newfile (lua_State *LS) {
 -  FILE **pf =3D (FILE **)lua_newuserdata(LS, sizeof(FILE *));
 -  *pf =3D NULL;  /* file handle is currently `closed' */
 +static mtn_lua_Stream *newstream (lua_State *LS) {
 +  mtn_lua_Stream *s =3D (mtn_lua_Stream *)lua_newuserdata(LS, sizeof(mtn_l=
 ua_Stream));
 +  s->f =3D NULL;  /* file handle is currently `closed' */
 +  s->closef =3D NULL;
    luaL_getmetatable(LS, LUA_FILEHANDLE);
    lua_setmetatable(LS, -2);
 =20
 -  lua_pushcfunction(LS, io_fclose);
 +#ifdef LUA_ENVIRONINDEX
 +  // Lua 5.2 removes C function environments
 +  lua_pushcfunction(LS, io_pclose);
    lua_setfield(LS, LUA_ENVIRONINDEX, "__close");
 +#endif
 =20
 -  return pf;
 +  return s;
  }
 =20
  LUAEXT(spawn_pipe, )
 @@ -136,12 +163,13 @@ LUAEXT(spawn_pipe, )
    for (i=3D0; i<n; i++) argv[i] =3D (char*)luaL_checkstring(LS,  i+1);
    argv[i] =3D NULL;
 =20
 -  int infd;
 -  FILE **inpf =3D newfile(LS);
 -  int outfd;
 -  FILE **outpf =3D newfile(LS);
 +  mtn_lua_Stream *ins =3D newstream(LS);
 +  ins->closef =3D &io_pclose;
 +
 +  mtn_lua_Stream *outs =3D newstream(LS);
 +  outs->closef =3D &io_pclose;
 =20
 -  pid =3D process_spawn_pipe(argv, inpf, outpf);
 +  pid =3D process_spawn_pipe(argv, &ins->f, &outs->f);
    free(argv);
 =20
    lua_pushnumber(LS, pid);
 diff --git a/src/std_hooks.lua b/src/std_hooks.lua
 index bfef561..7099f83 100644
 --- src/std_hooks.lua
 +++ src/std_hooks.lua
 @@ -10,6 +10,13 @@
  -- this is the standard set of lua hooks for monotone;
  -- user-provided files can override it or add to it.
 =20
 +-- Since Lua 5.2, unpack and loadstrings are deprecated and are either mov=
 ed
 +-- to table.unpack() or replaced by load(). If lua was compiled without
 +-- LUA_COMPAT_UNPACK and/or LUA_COMPAT_LOADSTRING, these two are not
 +-- available and we add a similar compatibility layer, ourselves.
 +unpack =3D unpack or table.unpack
 +loadstring =3D loadstring or load
 +
  function temp_file(namehint)
     local tdir
     tdir =3D os.getenv("TMPDIR")
 @@ -1465,7 +1472,7 @@ do
        return true, warning
     end
     function push_hook_functions(functions)
 -      local n =3D table.maxn(hook_functions) + 1
 +      local n =3D #hook_functions + 1
        return add_hook_functions(functions, n)
     end
 =20
 diff --git a/test/func-testsuite.lua b/test/func-testsuite.lua
 index 64a6f26..454cd9c 100755
 --- test/func-testsuite.lua
 +++ test/func-testsuite.lua
 @@ -10,6 +10,13 @@
  monotone_path =3D nil
  no_network_tests =3D false
 =20
 +-- Since Lua 5.2, unpack and loadstrings are deprecated and are either mov=
 ed
 +-- to table.unpack() or replaced by load(). If lua was compiled without
 +-- LUA_COMPAT_UNPACK and/or LUA_COMPAT_LOADSTRING, these two are not
 +-- available and we add a similar compatibility layer, ourselves.
 +unpack =3D unpack or table.unpack
 +loadstring =3D loadstring or load
 +
  function safe_mtn(...)
    if monotone_path =3D=3D nil then
      monotone_path =3D os.getenv("mtn")
 diff --git a/test/func/automate_get_attributes/__driver__.lua b/test/func/a=
 utomate_get_attributes/__driver__.lua
 index 2e92654..eb91015 100644
 --- test/func/automate_get_attributes/__driver__.lua
 +++ test/func/automate_get_attributes/__driver__.lua
 @@ -28,7 +28,7 @@ check(mtn("automate", "get_attributes", "testfile"), 0, t=
 rue, true)
  check(fsize("stderr") =3D=3D 0)
  parsed =3D parse_basic_io(readfile("stdout"))
  -- make sure the output generated 8 stanzas
 -check(table.getn(parsed) =3D=3D 8)
 +check(#parsed =3D=3D 8)
  lastkey =3D ""
  checked =3D {}
  for _,l in pairs(parsed) do
 diff --git a/test/func/automate_interface_version/__driver__.lua b/test/fun=
 c/automate_interface_version/__driver__.lua
 index d969d7d..7ff79e9 100644
 --- test/func/automate_interface_version/__driver__.lua
 +++ test/func/automate_interface_version/__driver__.lua
 @@ -7,4 +7,4 @@ rename("stdout", "a_v")
  -- MinGW's wc produces "      1" as output.  Arithmetic comparison works, =
 string comparison doesn't
  check(numlines("a_v") =3D=3D 1)
  -- This is really ^[0-9]+\.[0-9]+$, but m4 is obfuscatory.
 -check(qgrep("^[0-9]+\.[0-9]+$", "a_v"))
 +check(qgrep("^[0-9]+\\.[0-9]+$", "a_v"))
 diff --git a/test/func/automate_inventory_ignore_dirs/__driver__.lua b/test=
 /func/automate_inventory_ignore_dirs/__driver__.lua
 index bfb5c25..72a89bb 100644
 --- test/func/automate_inventory_ignore_dirs/__driver__.lua
 +++ test/func/automate_inventory_ignore_dirs/__driver__.lua
 @@ -14,7 +14,7 @@ function sortContentsByLine(input)
    table.insert(lines, string.sub(input, theStart))
    table.sort(lines)
 =20
 -  local len =3D table.getn(lines)
 +  local len =3D #lines
    local output =3D lines[1]
    for i =3D 2, len do
      output =3D output .. delimiter .. lines[i]
 diff --git a/test/func/automate_put_revision/__driver__.lua b/test/func/aut=
 omate_put_revision/__driver__.lua
 index 2626ec3..32bdacb 100644
 --- test/func/automate_put_revision/__driver__.lua
 +++ test/func/automate_put_revision/__driver__.lua
 @@ -33,5 +33,5 @@ check(mtn("automate", "put_revision", rev), 3, false, fal=
 se)
  -- but this should work (tests that we can use put_revision to commit a
  -- single-parent revision)
  check(mtn("automate", "put_file", ""), 0, false, false)
 -rev =3D "format_version \"1\"\n\nnew_manifest [000000000000000000000000000=
 0000000000000]\n\nold_revision [4c2c1d846fa561601254200918fba1fd71e6795d]\n=
 \patch \"foo\"\n from [5bf1fd927dfb8679496a2e6cf00cbe50c1c87145] to [da39a3=
 ee5e6b4b0d3255bfef95601890afd80709]\n"
 +rev =3D "format_version \"1\"\n\nnew_manifest [000000000000000000000000000=
 0000000000000]\n\nold_revision [4c2c1d846fa561601254200918fba1fd71e6795d]\n=
 \npatch \"foo\"\n from [5bf1fd927dfb8679496a2e6cf00cbe50c1c87145] to [da39a=
 3ee5e6b4b0d3255bfef95601890afd80709]\n"
  check(mtn("automate", "put_revision", rev), 0, false, false)
 diff --git a/test/func/automate_set_drop_attribute/__driver__.lua b/test/fu=
 nc/automate_set_drop_attribute/__driver__.lua
 index 5369cd9..12ff4dc 100644
 --- test/func/automate_set_drop_attribute/__driver__.lua
 +++ test/func/automate_set_drop_attribute/__driver__.lua
 @@ -25,7 +25,7 @@ check(mtn("automate", "set_attribute", "testfile", "foo",=
  "bar"), 0, false, fals
  check(mtn("automate", "get_attributes", "testfile"), 0, true, false)
  parsed =3D parse_basic_io(readfile("stdout"))
 =20
 -check(table.getn(parsed) =3D=3D 2)
 +check(#parsed =3D=3D 2)
  for _,l in pairs(parsed) do
      if l.name =3D=3D "attr" then
          key =3D l.values[1]
 @@ -44,7 +44,7 @@ check(mtn("automate", "drop_attribute", "testfile", "foo"=
 ), 0, true, true)
  -- check if it has been really dropped
  check(mtn("automate", "get_attributes", "testfile"), 0, true, false)
  parsed =3D parse_basic_io(readfile("stdout"))
 -check(table.getn(parsed) =3D=3D 0)
 +check(#parsed =3D=3D 0)
 =20
  -- check if it escalates properly if there is no such attr to drop
  check(mtn("automate", "drop_attribute", "testfile", "foo"), 1, false, true)
 diff --git a/test/func/automate_stdio_band_output/__driver__.lua b/test/fun=
 c/automate_stdio_band_output/__driver__.lua
 index 4262d0e..88c8d63 100755
 --- test/func/automate_stdio_band_output/__driver__.lua
 +++ test/func/automate_stdio_band_output/__driver__.lua
 @@ -4,13 +4,13 @@ mtn_setup()
 =20
  -- check informational messages, warnings and errors
  out =3D run_stdio("l8:bandtest4:infoe", 0, 0, "p")
 -check(type(out) =3D=3D "table" and table.maxn(out) =3D=3D 1)
 +check(type(out) =3D=3D "table" and #out =3D=3D 1)
 =20
  out =3D run_stdio("l8:bandtest7:warninge", 0, 0, "w")
 -check(type(out) =3D=3D "table" and table.maxn(out) =3D=3D 1)
 +check(type(out) =3D=3D "table" and #out =3D=3D 1)
 =20
  out =3D run_stdio("l8:bandtest5:errore", 2, 0, "e")
 -check(type(out) =3D=3D "table" and table.maxn(out) =3D=3D 1)
 +check(type(out) =3D=3D "table" and #out =3D=3D 1)
 =20
  -- check tickers
  tickers =3D run_stdio("l8:bandtest6:tickere", 0, 0, "t")
 @@ -38,7 +38,7 @@ end
  ticker_data =3D {}
  for _,tick in ipairs(tickers) do
      ticks =3D split(tick, ";")
 -    check(table.maxn(ticks) > 0)
 +    check(#ticks > 0)
      for _,mtick in ipairs(ticks) do
          if string.len(mtick) > 0 then
              local begin,End,short,ticktype,content =3D
 @@ -78,6 +78,6 @@ for _,tick in ipairs(tickers) do
  end
 =20
  -- finally check if all tickers are completed
 -check(table.maxn(ticker_data) =3D=3D 0)
 +check(#ticker_data =3D=3D 0)
 =20
 =20
 diff --git a/test/func/clone_weird_branch_names/__driver__.lua b/test/func/=
 clone_weird_branch_names/__driver__.lua
 index 4948a72..a97c6ea 100644
 --- test/func/clone_weird_branch_names/__driver__.lua
 +++ test/func/clone_weird_branch_names/__driver__.lua
 @@ -7,7 +7,7 @@ commit("my-branch[1,2]-1^3")
 =20
  copy("test.db", "test-clone.db")
  -- some of the special chars need to get double-escaped to get "through"
 -testURI=3D"file://" .. test.root .. "/test-clone.db?my-branch\\\[1,2\\\]-1=
 ^3"
 +testURI=3D"file://" .. test.root .. "/test-clone.db?my-branch\\[1,2\\]-1^3"
 =20
  check(nodb_mtn("clone", testURI), 0, false, false)
  check(exists("my-branch[1,2]-1^3"))
 diff --git a/test/func/list_databases/__driver__.lua b/test/func/list_datab=
 ases/__driver__.lua
 index e3da0e9..48cd75c 100644
 --- test/func/list_databases/__driver__.lua
 +++ test/func/list_databases/__driver__.lua
 @@ -25,15 +25,15 @@ check(mt("db", "init", "-d", ":bar"), 0, false, false)
  check(exists("managed_databases/bar.mtn"))
 =20
  check(mt("ls", "dbs"), 0, true, false)
 -check(qgrep(":bar.mtn.+in.+list_databases\/managed_databases", "stdout"))
 +check(qgrep(":bar.mtn.+in.+list_databases/managed_databases", "stdout"))
  check(qgrep("\tno known valid workspaces", "stdout"))
 =20
  check(mt("setup", "-d", ":bar", "-b", "test.foo.branch", "test_foo"), 0, f=
 alse, false)
 =20
  check(mt("ls", "dbs"), 0, true, false)
  check(not qgrep("\tno known valid workspaces", "stdout"))
 -check(qgrep("\ttest.foo.branch.+in.+list_databases\/test_foo", "stdout"))
 +check(qgrep("\ttest.foo.branch.+in.+list_databases/test_foo", "stdout"))
 =20
  check(rename("managed_databases/bar.mtn", "managed_databases/bar.db"))
  check(mt("ls", "dbs"), 0, true, false)
 -check(qgrep(":bar.db.+in.+list_databases\/managed_databases", "stdout"))
 +check(qgrep(":bar.db.+in.+list_databases/managed_databases", "stdout"))
 diff --git a/test/func/list_workspaces/__driver__.lua b/test/func/list_work=
 spaces/__driver__.lua
 index 06dbfef..8895ed4 100644
 --- test/func/list_workspaces/__driver__.lua
 +++ test/func/list_workspaces/__driver__.lua
 @@ -10,17 +10,17 @@ check(samelines("stdout", {"no known valid workspaces"}=
 ))
  check(raw_mtn("setup", "-d", "test.mtn", "-b", "test.branch1", "work1"), 0=
 , false, false)
 =20
  check(raw_mtn("ls", "workspaces", "-d", "test.mtn"), 0, true, false)
 -check(qgrep("test.branch1.+in.+list_workspaces\/work1", "stdout"))
 +check(qgrep("test.branch1.+in.+list_workspaces/work1", "stdout"))
 =20
  check(raw_mtn("setup", "-d", "test.mtn", "-b", "test.branch2", "work2"), 0=
 , false, false)
  check(rename("work1", "work3"))
 =20
  check(raw_mtn("ls", "workspaces", "-d", "test.mtn"), 0, true, false)
 -check(qgrep("test.branch2.+in.+list_workspaces\/work2", "stdout"))
 -check(not qgrep("test.branch1.+in.+list_workspaces\/work1", "stdout"))
 +check(qgrep("test.branch2.+in.+list_workspaces/work2", "stdout"))
 +check(not qgrep("test.branch1.+in.+list_workspaces/work1", "stdout"))
 =20
  check(indir("work3", raw_mtn("register_workspace", "-d", "../test.mtn")), =
 0, false, false)
 =20
  check(raw_mtn("ls", "workspaces", "-d", "test.mtn"), 0, true, false)
 -check(qgrep("test.branch1.+in.+list_workspaces\/work3", "stdout"))
 +check(qgrep("test.branch1.+in.+list_workspaces/work3", "stdout"))
 =20
 diff --git a/test/func/log_--no-files_and_--merges/__driver__.lua b/test/fu=
 nc/log_--no-files_and_--merges/__driver__.lua
 index b27551e..de4d26d 100644
 --- test/func/log_--no-files_and_--merges/__driver__.lua
 +++ test/func/log_--no-files_and_--merges/__driver__.lua
 @@ -29,8 +29,8 @@ R2=3Dbase_revision()
 =20
  -- check that merge is included by default
  check(mtn("log"), 0, true, false)
 -check(qgrep("^[\\|\\\\\/ ]+Revision.*"..R2, "stdout"))
 +check(qgrep("^[\\|\\\\/ ]+Revision.*"..R2, "stdout"))
 =20
  -- and that it is excluded by --no-merges
  check(mtn("log", "--no-merges"), 0, true, false)
 -check(not qgrep("^[\\|\\\\\/ ]+Revision.*"..R2, "stdout"))
 +check(not qgrep("^[\\|\\\\/ ]+Revision.*"..R2, "stdout"))
 diff --git a/test/func/manpage/__driver__.lua b/test/func/manpage/__driver_=
 _.lua
 index 775714e..38e5ee7 100644
 --- test/func/manpage/__driver__.lua
 +++ test/func/manpage/__driver__.lua
 @@ -5,7 +5,7 @@ rename("stdout", "manpage")
 =20
  -- check for a proper header line
  check(mtn("version"), 0, true, false)
 -local s,e,version =3D string.find(readfile("stdout"), "(monotone %d+\.%d+%=
 S*)")
 +local s,e,version =3D string.find(readfile("stdout"), "(monotone %d+%.%d+%=
 S*)")
  check(qgrep(".TH \"monotone\" 1 \"[0-9]{4}-[0-9]{2}-[0-9]{2}\" \"" .. vers=
 ion .. "\"", "manpage"))
 =20
  -- check required sections
 diff --git a/test/func/netsync_negotiation/__driver__.lua b/test/func/netsy=
 nc_negotiation/__driver__.lua
 index 2efe421..c776f93 100644
 --- test/func/netsync_negotiation/__driver__.lua
 +++ test/func/netsync_negotiation/__driver__.lua
 @@ -87,10 +87,10 @@ function check_same_revs(cmd1, cmd2)
     check(cmd2, 0, true, false)
     local data2 =3D {}
     for l in io.lines("stdout") do table.insert(data2, l) end
 -   L("Command 1 has ", table.getn(data1), " lines.")
 -   L("Command 2 has ", table.getn(data2), " lines.")
 -   check(table.getn(data1) =3D=3D table.getn(data2))
 -   for i =3D 1, table.getn(data1) do
 +   L("Command 1 has ", #data1, " lines.")
 +   L("Command 2 has ", #data2, " lines.")
 +   check(#data1 =3D=3D #data2)
 +   for i =3D 1, #data1 do
        local hash_len =3D 40
        check(data1[i]:sub(1, hash_len) =3D=3D data2[i]:sub(1, hash_len))
     end
 diff --git a/test/func/serve-automate-single-run/__driver__.lua b/test/func=
 /serve-automate-single-run/__driver__.lua
 index 87b1ab7..b65b9c1 100644
 --- test/func/serve-automate-single-run/__driver__.lua
 +++ test/func/serve-automate-single-run/__driver__.lua
 @@ -28,7 +28,7 @@ server =3D netsync.start({"--rcfile=3Dallow-automate.lua"=
 })
 =20
  check(mtn2("automate", "remote", "--remote-stdio-host", server.address,
      "interface_version"), 0, true, false)
 -check(qgrep("^[0-9]{2,}\.[0-9]+$", "stdout"))
 +check(qgrep("^[0-9]{2,}\\.[0-9]+$", "stdout"))
 =20
  check(mtn2("automate", "remote", "--remote-stdio-host", server.address,
      "leaves"), 0, true, false)
 diff --git a/test/func/serve-automate/__driver__.lua b/test/func/serve-auto=
 mate/__driver__.lua
 index 32b2eaf..9e993dc 100644
 --- test/func/serve-automate/__driver__.lua
 +++ test/func/serve-automate/__driver__.lua
 @@ -14,7 +14,7 @@ server =3D netsync.start({"--rcfile=3Ddeny-automate.lua"})
 =20
  local errors =3D run_remote_stdio(server, "l17:interface_versione", 1, 0, =
 "e")
  check(
 -    table.maxn(errors) =3D=3D 1 and
 +    #errors =3D=3D 1 and
      errors[1] =3D=3D "misuse: Sorry, you aren't allowed to do that."
  )
 =20
 @@ -45,7 +45,7 @@ check(
 =20
  local errors =3D run_remote_stdio(server, "l5:stdioe", 1, 0, "e")
  check(
 -    table.maxn(errors) =3D=3D 1 and
 +    #errors =3D=3D 1 and
      errors[1] =3D=3D "error: sorry, that can't be run remotely or over std=
 io"
  )
 =20
 diff --git a/test/func/ssh_agent/__driver__.lua b/test/func/ssh_agent/__dri=
 ver__.lua
 index d927360..a36ce90 100644
 --- test/func/ssh_agent/__driver__.lua
 +++ test/func/ssh_agent/__driver__.lua
 @@ -81,7 +81,7 @@ end
 =20
  check({"ssh-agent"}, 0, true, false)
  for line in io.lines("stdout") do
 -   for k, v in string.gmatch(line, "([%w_]+)=3D([%w/\.-]+)") do
 +   for k, v in string.gmatch(line, "([%w_]+)=3D([%w/%.-]+)") do
        set_env(k, v)
     end
  end
 @@ -91,7 +91,7 @@ check(mtn("ssh_agent_add"), 0, false, false)
  check({"ssh-add", "-l"}, 0, true, false)
  ok =3D false
  for line in io.lines("stdout") do
 -    for k in string.gmatch(line, "tester@test\.net") do
 +    for k in string.gmatch(line, "tester@test%.net") do
      	ok =3D true
      end
  end
 @@ -288,7 +288,7 @@ check(mtn("ssh_agent_add", "--key", "test2@tester.net")=
 , 0, false, false)
  check({"ssh-add", "-l"}, 0, true, false)
  ok =3D false
  for line in io.lines("stdout") do
 -    for k in string.gmatch(line, "test2@tester\.net") do
 +    for k in string.gmatch(line, "test2@tester%.net") do
      	ok =3D true
      end
  end
 @@ -338,7 +338,7 @@ check(mtn("ssh_agent_add", "--key", "test_pass@tester.n=
 et"), 0, false, false, "p
  check({"ssh-add", "-l"}, 0, true, false)
  ok =3D false
  for line in io.lines("stdout") do
 -    for k in string.gmatch(line, "test_pass@tester\.net") do
 +    for k in string.gmatch(line, "test_pass@tester%.net") do
      	ok =3D true
      end
  end
 diff --git a/test/func/two_parent_workspace_inodeprints/__driver__.lua b/te=
 st/func/two_parent_workspace_inodeprints/__driver__.lua
 index bd6c558..66d5150 100644
 --- test/func/two_parent_workspace_inodeprints/__driver__.lua
 +++ test/func/two_parent_workspace_inodeprints/__driver__.lua
 @@ -19,13 +19,13 @@ check(mtn("merge_into_workspace", other), 0, false, fal=
 se)
 =20
  -- check that we've got the expected initial status
  check(mtn("status"), 0, true, false)
 -check(qgrep("patched[ 	]\+foo", "stdout"))
 +check(qgrep("patched[ 	]+foo", "stdout"))
 =20
  -- enable inodeprints
  writefile("_MTN/inodeprints")
 =20
  check(mtn("status"), 0, true, false)
 -check(qgrep("patched[ 	]\+foo", "stdout"))
 +check(qgrep("patched[ 	]+foo", "stdout"))
 =20
  sleep(5)
 =20
 diff --git a/test/func/user_commands/extra_rc b/test/func/user_commands/ext=
 ra_rc
 index 2ec5f9f..aad3764 100644
 --- test/func/user_commands/extra_rc
 +++ test/func/user_commands/extra_rc
 @@ -5,7 +5,8 @@ function check_head(...)
        io.stderr:write("automate call failed\n")
        return
      end
 -    arghead =3D unpack(arg)
 +    local arg =3D {...}
 +    arghead =3D arg[1]
      heads =3D heads:gsub("^%s*(.-)%s*$", "%1")	-- trim leading and trailin=
 g whitespace
      if (heads =3D=3D arghead) then
          io.write("heads are equal\n")
 diff --git a/test/src/testlib.lua b/test/src/testlib.lua
 index 6d21a93..19eb278 100644
 --- test/src/testlib.lua
 +++ test/src/testlib.lua
 @@ -30,6 +30,13 @@ files =3D {stdout =3D nil, stdin =3D nil, stderr =3D nil}
  -- for convenience, this is the first word of what get_ostype() returns.
  ostype =3D string.sub(get_ostype(), 1, string.find(get_ostype(), " ")-1)
 =20
 +-- Since Lua 5.2, unpack and loadstrings are deprecated and are either mov=
 ed
 +-- to table.unpack() or replaced by load(). If lua was compiled without
 +-- LUA_COMPAT_UNPACK and/or LUA_COMPAT_LOADSTRING, these two are not
 +-- available and we add a similar compatibility layer, ourselves.
 +unpack =3D unpack or table.unpack
 +loadstring =3D loadstring or load
 +
  -- table of per-test values
  test =3D {}
  -- misc per-test values
 @@ -310,17 +317,11 @@ end
  -- to want to include from the dir for the current test,
  -- since in that case it could just go in the driver file.
  function include(name)
 -  local func, e =3D loadfile(testdir.."/"..name)
 -  if func =3D=3D nil then err(e, 2) end
 -  setfenv(func, getfenv(2))
 -  func()
 +  dofile(testdir.."/"..name)
  end
 =20
  function includecommon(name)
 -  local func, e =3D loadfile(srcdir.."/common/"..name)
 -  if func =3D=3D nil then err(e, 2) end
 -  setfenv(func, getfenv(2))
 -  func()
 +  dofile(srcdir.."/common/"..name)
  end
 =20
  function trim(str)
 @@ -479,12 +480,11 @@ end
  function samelines(f, t)
    local fl =3D {}
    for l in io.lines(f) do table.insert(fl, l) end
 -  if not (table.getn(fl) =3D=3D table.getn(t)) then
 -    L(locheader(), string.format("file has %s lines; table has %s\n",
 -                                 table.getn(fl), table.getn(t)))
 +  if not (#fl =3D=3D #t) then
 +    L(locheader(), string.format("file has %s lines; table has %s\n", #fl,=
  #t))
      return false
    end
 -  for i=3D1,table.getn(t) do
 +  for i=3D1,#t do
      if fl[i] ~=3D t[i] then
        if fl[i] then
          L(locheader(), string.format("file[%d] =3D '%s'; table[%d] =3D '%s=
 '\n",
 @@ -502,12 +502,11 @@ end
  function greplines(f, t)
    local fl =3D {}
    for l in io.lines(f) do table.insert(fl, l) end
 -  if not (table.getn(fl) =3D=3D table.getn(t)) then
 -    L(locheader(), string.format("file has %s lines; table has %s\n",
 -                                 table.getn(fl), table.getn(t)))
 +  if not (#fl =3D=3D #t) then
 +    L(locheader(), string.format("file has %s lines; table has %s\n", #fl,=
  #t))
      return false
    end
 -  for i=3D1,table.getn(t) do
 +  for i=3D1,#t do
      if not regex.search(t[i], fl[i]) then
        L(locheader(), string.format("file[i] =3D '%s'; table[i] =3D '%s'\n",
                                     fl[i], t[i]))
 @@ -577,7 +576,7 @@ function tail(...)
      local mylines =3D {}
      for l in io.lines(file) do
        table.insert(mylines, l)
 -      if table.getn(mylines) > num then
 +      if #mylines > num then
          table.remove(mylines, 1)
        end
      end
 @@ -932,8 +931,8 @@ function run_tests(debugging, list_only, run_dir, logna=
 me, args, progress)
      if _1 then
        l =3D l + 0
        r =3D r + 0
 -      if l < 1 then l =3D table.getn(tests) + l + 1 end
 -      if r < 1 then r =3D table.getn(tests) + r + 1 end
 +      if l < 1 then l =3D #tests + l + 1 end
 +      if r < 1 then r =3D #tests + r + 1 end
        if l > r then l,r =3D r,l end
        for j =3D l,r do
          torun[j] =3D tests[j]
 @@ -941,7 +940,7 @@ function run_tests(debugging, list_only, run_dir, logna=
 me, args, progress)
        run_all =3D false
      elseif string.find(a, "^-?%d+$") then
        r =3D a + 0
 -      if r < 1 then r =3D table.getn(tests) + r + 1 end
 +      if r < 1 then r =3D #tests + r + 1 end
        torun[r] =3D tests[r]
        run_all =3D false
      else
 --=20
 tg: (1150daa..) lua-5.2 (depends on: master)

 --KsGdsel6WgEHnImy
 Content-Type: application/pgp-signature

 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.14 (NetBSD)

 iQEcBAEBAgAGBQJSZDr3AAoJEJmJxkVhw/vTFNIIALHOyZzTNFIgCBhkrhss+yQ/
 yMnf1p/htngBDyOpt/1/u78WZDUHJoxeYfYAhJqRDGSU1uvtcDf8Tp4G3L+cZjBz
 hnu8N0HTj+naSMCbR90z5SwRjZ7iOpM6mbvifdJMPrjiosfdb/vilk9vaWUkz+ZE
 F/ilzOtsE+5n2vm4kyzIg4xDSRxfcrhVfU/3bLTuUcLASxGvBe3aTT7fQyaXF4PC
 l18OErhe9bzuB3KsSWFXsqpztXVF8St39yHT7wscRwsheWG+1kNv/zeJ8o+tqA09
 URYfgaibJp5u+DRt2DxzM4vNzcqtzoaN6wRiM+5AwtH3amckeF9zjfc2d+F3ev4=
 =0dp0
 -----END PGP SIGNATURE-----

 --KsGdsel6WgEHnImy--

State-Changed-From-To: open->feedback
State-Changed-By: obache@NetBSD.org
State-Changed-When: Fri, 07 Feb 2014 09:12:32 +0000
State-Changed-Why:
After 2013Q4, multi version lua is supported, and monotone is marked as lua51
only.  So you can use current as-is except you really want to use it with lua52.


From: Rhialto <rhialto@falu.nl>
To: gnats-bugs@NetBSD.org
Cc: pkg-manager@netbsd.org, pkgsrc-bugs@netbsd.org, gnats-admin@netbsd.org,
        obache@NetBSD.org, rhialto@falu.nl
Subject: Re: pkg/48301 (Make devel/monotone build with lua 5.2 (with patch))
Date: Wed, 5 Mar 2014 17:40:57 +0100

 On Fri 07 Feb 2014 at 09:12:32 +0000, obache@NetBSD.org wrote:
 > After 2013Q4, multi version lua is supported, and monotone is marked as l=
 ua51
 > only.  So you can use current as-is except you really want to use it with=
  lua52.

 Indeed, I see that monotone now builds lua 5.1 as a prerequisite.
 Unfortunately it doesn't co-exist with lua 5.2, if that was built for
 some other packages. They both install a "bin/lua" file.

 =3D=3D=3D> su-real-package-install [lua51-5.1.5 monotone-1.0nb14] =3D=3D=3D=
 > Install
 binary=20
 package of lua51-5.1.5=20
 pkg_add: Conflicting PLIST with lua52-5.2.2: bin/lua
 pkg_add: 1 package addition failed
 *** Error code 1

 I have set LUA_VERSION_DEFAULT=3D51 for my next quarterly update cycle.
 A quick check of my installed packages that use lua 5.2 suggests that
 they should also work with 5.1.

 At some point in the future there might be a release of monotone which
 works with lua 5.2. It may be a while though...

 -Olaf.
 --=20
 ___ Olaf 'Rhialto' Seibert  -- The Doctor: No, 'eureka' is Greek for
 \X/ rhialto/at/xs4all.nl    -- 'this bath is too hot.'

State-Changed-From-To: feedback->open
State-Changed-By: obache@NetBSD.org
State-Changed-When: Thu, 06 Mar 2014 01:36:40 +0000
State-Changed-Why:
lua multi-version issues remain


From: Rhialto <rhialto@falu.nl>
To: gnats-bugs@NetBSD.org
Cc: pkg-manager@netbsd.org, pkgsrc-bugs@netbsd.org, gnats-admin@netbsd.org,
        obache@NetBSD.org, rhialto@falu.nl
Subject: Re: pkg/48301 (Make devel/monotone build with lua 5.2 (with patch))
Date: Sun, 6 Apr 2014 11:13:04 +0200

 On Thu 06 Mar 2014 at 01:36:40 +0000, obache@NetBSD.org wrote:
 > Synopsis: Make devel/monotone build with lua 5.2 (with patch)
 > 
 > lua multi-version issues remain

 They got worse in pkgsrc-2013Q4.

 Because my patches to make monotone work with Lua 5.2 were not committed
 to pkgsrc, I have to build with LUA_VERSION_DEFAULT=51.

 However, graphics/graphviz does not work with Lua 5.1 and requires 5.2.
 (Probably because of the same incompatabilities in Lua that plague
 monotone)

 Now, monotone-viz requires bith monotone and graphviz.

 The only way out is to allow monotone to work with Lua 5.2. Which
 requires some patches, such as the ones I submitted.

 -Olaf.
 -- 
 ___ Olaf 'Rhialto' Seibert  -- The Doctor: No, 'eureka' is Greek for
 \X/ rhialto/at/xs4all.nl    -- 'this bath is too hot.'

From: Rhialto <rhialto@falu.nl>
To: gnats-bugs@NetBSD.org
Cc: pkg-manager@netbsd.org, pkgsrc-bugs@netbsd.org, gnats-admin@netbsd.org,
        obache@NetBSD.org, rhialto@falu.nl
Subject: Re: pkg/48301 (Make devel/monotone build with lua 5.2 (with patch))
Date: Sun, 6 Apr 2014 12:28:36 +0200

 On Sun 06 Apr 2014 at 11:13:04 +0200, Rhialto wrote:
 > They got worse in pkgsrc-2013Q4.

 Sorry, I mistyped, of course I meant the currently new branch, 2014Q1.

Responsible-Changed-From-To: pkg-manager->rhialto
Responsible-Changed-By: bsiegert@NetBSD.org
Responsible-Changed-When: Fri, 17 Dec 2021 16:24:02 +0000
Responsible-Changed-Why:
Rhialto, here's your bug back :)

Feel free to close this if obsolete.


State-Changed-From-To: open->closed
State-Changed-By: rhialto@NetBSD.org
State-Changed-When: Mon, 20 Dec 2021 14:49:44 +0000
State-Changed-Why:
obsolete; the current version builds.


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: gnats-precook-prs,v 1.4 2018/12/21 14:20:20 maya Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2017 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.