Sharing code between projects

I was wondering how people go about sharing useful code between multiple projects.

Usually I symbolic link to the original file, which has the benefit that any bug fixes will be shared between projects. However it’s a pain if the code is split across multiple files. Also if that is the case if the files have require calls to each other, the project must respect the paths. 

I was wondering if a luarocks style tool might be the answer. I don’t want to share my code with everyone though, just manage the huge number of files I already have

I use Git submodules myself, but if the interest is to avoid pain, they’re certainly no better than symbolic links.  :slight_smile: (There was a short topic a couple years or so back that brought up these same choices, but I’m having no luck finding it.)

I’ve seen subtrees posed as better replacements for submodules, but haven’t found the case for them all that convincing (or honestly, the dangers of submodules all that insurmountable). The big hangup with submodules is that you need to manually update them. It’s perfectly valid for a project to want to stay on a given version of some piece of code, so Git assumes that until told otherwise.

Submodules/Subrepos are certainly a good option. +1 :slight_smile:

Thanks, for the tip! Turns out the git client I use, Tower, has supported submodules for a while. I just assumed it was one of those features for enterprise cases until now.

Do you know if the require supports relative paths? I’m assuming not, at least not with the standard . and … notation (that would be horrific).

I’m thinking of using the debug library to programatically work out the path for require calls within the module, so the code can be agnostic about where it is within the super project.

[lua]

  local full_path=debug.getinfo(1,‘S’).source

  local mod_start,mod_end=full_path:find(module_name)

  local last_slash_start,last_slash_end=full_path:find("/[^/]*$")

  local lua_subtree_path=full_path:sub(mod_end+2,last_slash_start-1):gsub("/",".")

[/lua]

It requires module_name to be set to the name of containing folder, so not perfect as it would need to be global or set by function call from the superproject, but after that all require calls within the subtree would take the form:

[lua]

  require lua_subtree_path … “.lua_file_internal_to_subtree”

[/lua] 

Overkill?

You might have some luck with that, though you’ll need to be careful if debug symbols get stripped out (see middle of the page or so here).

If you’re up for doing what you mention, you might also be able to extend the require() machinery itself. There’s a little more to it than is probably obvious (PiL has some on it, too).

Possibly relevant: The main chunk of a module, that is, the code that gets run when required, where you create your other functions and variables, will receive its own name as an argument (I’m trying to find where this is spelled out and not having much luck). So for instance if you require(“my.deep.nested.module”), you could do this inside of it:

local M = {} local name = ... -- will be "my.deep.nested.module" -- other module stuff return M

For now I’ve settled on creating an init.lua file within the submodule that fixes the path variable so that internal require calls work. It’s got lots of problems: it really could do with it’s own namespace provided by the standard naming convention. This approach has only worked so far with a relatively simple submodule (flat, no folders within it, no dependencies)

In future I’m going to have to think more about how to structure my code to facilitate submodules from the start

[lua]

local fullpath=debug.getinfo(1,‘S’).source

fullpath=fullpath:sub(2,-1)

local last_slash_start=fullpath:find("/[^/]*$")

local lua_subtree_path=fullpath:sub(1,last_slash_start-1)

package.path=package.path…";"…lua_subtree_path…"/?.lua"

[/lua]

You might want to look at CIPRalso. The project doesn’t seem to be maintained any longer, but I have been messing around with it and it has promise. 

I love that the history for that project includes commits such as “- Made too many changes that I didn’t commit”. Sound familiar

Nope the code I was using doesn’t work on the device as the Lua files are all moved. Had forgotten about that. Back to the drawing board.

This page held the answer!

So now rather than having an init file (deleted) each script in the subtree which requires other internal scripts does so programmatically.

[lua]

local folderOfThisFile = (…):match("(.-)[^%.]+$")

local script_one=require (folderOfThisFile…“script_one”)

local script_two=require (folderOfThisFile…“script_two”)

[/lua]

The linked page explains the mechanics. I have confirmed that it works on the device

I use Git submodules myself, but if the interest is to avoid pain, they’re certainly no better than symbolic links.  :slight_smile: (There was a short topic a couple years or so back that brought up these same choices, but I’m having no luck finding it.)

I’ve seen subtrees posed as better replacements for submodules, but haven’t found the case for them all that convincing (or honestly, the dangers of submodules all that insurmountable). The big hangup with submodules is that you need to manually update them. It’s perfectly valid for a project to want to stay on a given version of some piece of code, so Git assumes that until told otherwise.

Submodules/Subrepos are certainly a good option. +1 :slight_smile:

Thanks, for the tip! Turns out the git client I use, Tower, has supported submodules for a while. I just assumed it was one of those features for enterprise cases until now.

Do you know if the require supports relative paths? I’m assuming not, at least not with the standard . and … notation (that would be horrific).

I’m thinking of using the debug library to programatically work out the path for require calls within the module, so the code can be agnostic about where it is within the super project.

[lua]

  local full_path=debug.getinfo(1,‘S’).source

  local mod_start,mod_end=full_path:find(module_name)

  local last_slash_start,last_slash_end=full_path:find("/[^/]*$")

  local lua_subtree_path=full_path:sub(mod_end+2,last_slash_start-1):gsub("/",".")

[/lua]

It requires module_name to be set to the name of containing folder, so not perfect as it would need to be global or set by function call from the superproject, but after that all require calls within the subtree would take the form:

[lua]

  require lua_subtree_path … “.lua_file_internal_to_subtree”

[/lua] 

Overkill?

You might have some luck with that, though you’ll need to be careful if debug symbols get stripped out (see middle of the page or so here).

If you’re up for doing what you mention, you might also be able to extend the require() machinery itself. There’s a little more to it than is probably obvious (PiL has some on it, too).

Possibly relevant: The main chunk of a module, that is, the code that gets run when required, where you create your other functions and variables, will receive its own name as an argument (I’m trying to find where this is spelled out and not having much luck). So for instance if you require(“my.deep.nested.module”), you could do this inside of it:

local M = {} local name = ... -- will be "my.deep.nested.module" -- other module stuff return M

For now I’ve settled on creating an init.lua file within the submodule that fixes the path variable so that internal require calls work. It’s got lots of problems: it really could do with it’s own namespace provided by the standard naming convention. This approach has only worked so far with a relatively simple submodule (flat, no folders within it, no dependencies)

In future I’m going to have to think more about how to structure my code to facilitate submodules from the start

[lua]

local fullpath=debug.getinfo(1,‘S’).source

fullpath=fullpath:sub(2,-1)

local last_slash_start=fullpath:find("/[^/]*$")

local lua_subtree_path=fullpath:sub(1,last_slash_start-1)

package.path=package.path…";"…lua_subtree_path…"/?.lua"

[/lua]

You might want to look at CIPRalso. The project doesn’t seem to be maintained any longer, but I have been messing around with it and it has promise. 

I love that the history for that project includes commits such as “- Made too many changes that I didn’t commit”. Sound familiar

Nope the code I was using doesn’t work on the device as the Lua files are all moved. Had forgotten about that. Back to the drawing board.

This page held the answer!

So now rather than having an init file (deleted) each script in the subtree which requires other internal scripts does so programmatically.

[lua]

local folderOfThisFile = (…):match("(.-)[^%.]+$")

local script_one=require (folderOfThisFile…“script_one”)

local script_two=require (folderOfThisFile…“script_two”)

[/lua]

The linked page explains the mechanics. I have confirmed that it works on the device