Required: a new way to manage dependencies and version control

Hello everyone!

In first, Required isn’t finished yet, but a lot of things are already here. I want discuss with you about the project for doing something really useful for the community.

So, what is exactly Required?

Dependencies

It’s a program for manage dependencies. More and more libraries are developed by all the community : buttons, graphs, structures, shaders, … But, I think, a lot are not used because the way to share it isn’t a right one. With Required, you need to describe your project in a file named ‘package’ like this little example:

return json.decode([[{
	"id":"7802bd00e7d56d480379",
	"name":"Required",
	"description":"Required is a little framework for Codea to manage local and gist dependencies",
	"author":"HyroVitalyProtago",
	"version":"0.0.30",
	"codea":"2.3.1",
	"ignore":["local"],
	"dependencies":[
		"gist@HyroVitalyProtago:Btn:*"
	]
}]])

With the Required project as a dependency, when you launch your project, all dependencies are preloaded and you can access it with
require.import 'HyroVitalyProtago.Btn.Btn' -- owner.project.file

Versions can be defined like:

  • ‘*’ : the last version
  • ‘1.*’ : the last version with 1 as major number
  • ‘1.0.*’ : the last version with 1 as major number and 0 as minor number
  • ‘1.0.3’ : the specific version

Modules

One constraint is about the module definition. I totally dislike the principle of tab orders (even if it’s more practical for some little projects). So, all modules needs to be defined like this :

return (function() -- required line

	-- example of a class module

	-- load others module
	local AnotherFileInProject = required.import 'AnotherFileInProject'

	-- create a new class
	local MyFirstModule = class(AnotherFileInProject)

	-- Write your classe like before
	function MyFirstModule:init() AnotherFileInProject.init(self) end
	function MyFirstModule:doNothing() end

	-- return the module
	return MyFirstModule

end) -- required line

In the function encapsulation, you can do what you want, if you return nothing, the environment is return, like in the example below:

return (function() -- Main
	function setup() end
	function draw() end
	function touched() end
end)
(required.import 'Main').setup() -- call the setup function of Main

There is some exception with the Main file. It’s not a mandatory to write it as a module, but you can’t use required.import outside a function

Something = required.import 'Something' -- bad, doesn't work...

local Something -- define as local best practices
function setup()
	Something = required.import 'Something' -- good, work like a charm!
end

Repositories for sharing

After think a little about a beautiful to share things, this is what I’ve found. There is one main repository (the mine by default),
who contains all public release for each modules like this :

{
	"Required":{
		"id":"7802bd00e7d56d480379",
		"versions":{
			"1.0.0":"8c783334045e456bc765ca27ed9d5b12db03aac6"
		}
	},
	"Btn":{
		"id":"055093e0ec4f511e8fb6",
		"versions":{
			"1.0.0":"a3f69a1d889883bcf376964c49671fad66e8f0d9"
		}
	}
}

All repositories are defined for one user: the owner. All repositories is a fork from the main repository. For found all projects, start from the main and go into each children (forked repositories).

This procedure needs to be automated (and this is not very difficult). After, all needs to be in a file (like a cache or “cookie”) in local for a faster search the next time…

Version control

Required allows you to directly push a new revision into the same gist and increase the major, minor or patch version number. For the moment I use parameters. You can also download a project with required.fetch 'HyroVitalyProtago.Btn.*' -- owner.project.version.

Todo list

  • Support multiple dependencies with context
  • Support repositories process (with publishing, updating, …)
  • Add auto update protocol for Required (at least)
  • Do an installer (Downloader is already done)
  • Support assets with Dropbox ? (I don’t know for the moment what it’s possible to do with gist, but I know it will possible with Dropbox)
  • Support Github, README, …
  • Clean code
  • Test, test, test, … (test?)

You can test the current version:

function setup()
  http.request("https://api.github.com/gists/7802bd00e7d56d480379", function(data, status, headers)
    http.request(json.decode(data).files["Installer.lua"].raw_url, function(data)
      (assert(loadstring(data))()()).download()
    end, alert)
  end, alert)
end

You can PM me or write in this Thread for more precisions, questions, etc…

What do you think about? suggestions? critics?

Thanks in advance!

Can you give some more details please about a few things?

With the Required project as a dependency, when you launch your project, all dependencies are preloaded and you can access it with require.import ‘HyroVitalyProtago.Btn.Btn’ – owner.project.file

How do I declare in my project what the dependencies are? Is ‘HyroVitalyProtago.Btn.Btn’ the name of a dependency that you are declaring? What is the significance of the .btn.btn suffix?

all modules needs to be defined like this

What do you mean by modules, do you mean dependency projects (or the individual lua files within those projects)?

I’m sure I’m probably totally misunderstanding, but it sounds as if all projects would have to conform to this spec in order to be version controlled by this system, is that correct?

I don’t know whether this is useful to you, but you can read a project’s info.plist file to find a list of the tabs in order, as well as the names of all of its dependencies.

@yojimbo2000 - Sorry, it’s difficult to me to explain, so, I will try to do my best for a better explanation.

Required is based upon the require command for load Lua files only on time and use the memoization after.

When you write a new project, sometimes, another user of the community have write a good library like a gui, button or other. Today, you download the project and add it as a dependency managed by Codea. My system is inspired of Maven, Gradle, … and download automatically the latest wanted version on gist. For example, I’ve write a tiny library for buttons. If you want to use it, with Required, you can add it in the package file, and required automatically download it. When you call require.import 'HyroVitalyProtago.Btn.Btn', the module (or lua file) named Btn in the project Btn from the owner HyroVitalyProtago is loaded.

For the moment, the projects needs to conform to the spec in order to be use as library (dependency), but not really for the version control (it only needs the package file).

I expect my explanation is a little more understandable…

Thanks for reading and for your time!