inexorgame-obsolete / deprecated-cube-engine-inexor

UNMAINTAINED: Please have a look at the vulkan-renderer
https://inexor.org
zlib License
11 stars 1 forks source link

Add version_manager for inexorCore versions #478

Closed a-teammate closed 6 years ago

a-teammate commented 7 years ago

Currently we have the instancemanager, which is responsible for starting inexorcore instances. We furthermore have the first approach to download InexorCore in InexorFlex from GitHub (#440). Whats missing is a system which tries to do more than "get the one binary folder from GitHub, replace the old one". And its needed; currently all our wikis are broken because make install && cd flex && npm start won't bring you anywhere, as there is no real organisation of the binary dir - an environment var is needed to be set every time before that (or globally) to point to the binary dir you want to start -.

What should this system do?

First of all is the goal to have one (or more, see add_remote) folder for all inexor-core packages (each of them with a bin/ subfolder with included binaries according to #430)

whats missing in here is metainfo bundled with the inexorcore versions: e.g. a specific core version is not ultimately compatible with a media or flex version. but i think that's another improvement for later


IMHO we should include this to the 0.9 milestone, as this is currently something broken (in my eyes - since I can't tell new devs how to setup their toolset and others do not provide clear instructions to them either. so why not fix this instead of telling them the nasty workaround?)

Fohlen commented 7 years ago

This needs #430 in order to work

Fohlen commented 7 years ago

Also I disagree with adding this to the milestone. Let's don't blow this up. Nearly zero commits have been going to Inexor during August and we want to add stuff on top? I dislike that idea.

a-teammate commented 7 years ago

This is actually a solution for #419 which exists in the issue tracker for ages. why not add it now? its not too much work and fills exactly the whole we (or more precisely the inexor-core devs) have atm.

I made a pseudocode draft this morning. (pseudo since im a js noob and this is neither tested, nor has the full functionality done)

const fs = require('fs');
const semver = require('semver');

/*
* This is the class responsible for handling different versions of inexor-core.
* It can add different remotes (locally and really on another server).
* If the version is not locally available it can download it from GITHUB/releases or from a prepared server with inexor-core-archives.
* It downloads it to the first remote of type REMOTE_TYPE.LOCAL.
* It reacts on semantic version strings see https://github.com/npm/node-semver
* Note: We do not perform any checks whether the version is really correct (i.e. has a bin subfolder with binaries named correctly). maybe just yet?
* TODO: cache results, async checks?
*/
class VersionManager
{
    const REMOTE_TYPE = {
        LOCAL : 0,  // You can add various local directories, it assumes all subfolders to be versions.
        URL : 1,    // A Server can provide a json with a "os/arch/versions" array field. The remote then points to the json file on the server.
        GITHUB : 2  // A github repository e.g. https://github.com/inexorgame/inexor-core we assume all release folders
    };

    /*   Remotes:
    *    remotes is a map with 3 fields remotes[REMOTE_TYPE.LOCAL], remotes[REMOTE_TYPE.URL], remotes[REMOTE_TYPE.GITHUB],
    *    each of these fields is a list of strings.
    */

    /*
    * list all locally and remotely available inexor-core versions
    * returns a list of objects with .name and .remote_type and .path
    * what is a version? (local: subfolders, url: a field in a json, github: the answer of a GET request for releases)
    */
    list_versions() {
        let versions = _list_local_versions();
        versions += _list_url_versions();
        versions += _list_github_versions();
        // todo: wait here if we do it async?
        return versions;
    }

    /*
    * add a storage where one can find a package with a "bin" subfolder
    * hence a version of inexorcore
    * type is one of REMOTE_TYPE.LOCAL, REMOTE_TYPE.URL or REMOTE_TYPE.GITHUB
    * if insert is true, we add it at the beginning of the list
    */
    add_remote(type, path, insert=false) {
        if(type != REMOTE_TYPE.LOCAL && type != REMOTE_TYPE.URL && type != REMOTE_TYPE.GITHUB)
            /*TODO echo error this is not a valid REMOTE_TYPE*/;
        if(!insert)
            this.remotes[type] += [path];       // ????
        else
            this.remotes[type].insert(0, path); // ???? sth like that probably
    }

    /*
    * Gives back an object of a version fulfilling the semversion (the best).
    * Allows semversion stuff like "^0.1.2", see https://github.com/npm/node-semver.
    * returns a node with .name and .remote_type and .path
    * allows also names like "a_teammate_little_fix_branch"
    * this way we can just rename the "build" folder in which devs build into.
    */
    get_exact_version(semversion_string, nodownload = false) {
        let out = { name:"", remote_type:-1, path:"" };
        for(let version in (nodownload ? _list_local_versions() : list_versions()))
                if out.name is not set
                //    if semversion fulfilled: set out
                // if out.name is set:
                if(semver.satisfies(version.name, semversion_string))
                {
                    if(out.name == "") // first entry
                        out = version;
                    else // out is already set
                    {
                        if(semver.gt(out.name, version.name)                                    // better fulfills semversion (i.e. newer version)
                            || (semver.eq(version.name, out.name) && version.type == REMOTE_TYPE.LOCAL)) // already downloaded
                            out = version;
                    }
                }
        return out;
    }

    /*
    * semversion_string can be available locally or just on a non-local remote.
    * if only on non-local remote, we download it according to the flag
    * @returns the path to the binary folder on your harddisk.
    */
    aquire_version(semversion_string, nodownload = false) {
        const version = get_exact_version_name(semversion_string, nodownload);
        if(version.name == "")
            /* error no version found */;
        switch(version.remote_type)
        {
            case REMOTE_TYPE.LOCAL:
                return version.path;
            case REMOTE_TYPE.URL:
            case REMOTE_TYPE.GITHUB:
                // pseudocode:

                const first_local_remote = remotes[REMOTE_TYPE.LOCAL][0];
                // TODO: check if we have a local remote
                // const download_folder = first_local_remote; // i.e. "C://inexor/inexor-core-versions"
                // const temparchivefile = tempfolder + version.name;
                // const output_folder = download_folder + version.name; // i.e. C://inexor/inexor-core-versions/0.9.2-alpha
                // download(version.path, temparchivefile).then(
                //    decompress(temparchivefile, output_folder)
                // });
                return downloaded_folder;
        }
    }

    /*
    * list all locally available inexor-core binary folders
    * returns a list of nodes with .name, .remote_type and .path
    * TODO: make that object maybe a class?
    */
    _list_local_versions() {
        // for(let remote in this.remotes[REMOTE_TYPE.LOCAL])
            // check if remote is a directory
            // if yes: returns list of subfolders
            // optional maybe check for validity of the folder
    }

    /*
    * list all files in a specific remotely available url.
    * returns a list of nodes with .name, .remote_type and .path
    */
    _list_url_versions() {
        // for(let remote in this.remotes[REMOTE_TYPE.URL])
            // download json at the remote url
            // extract the correct "os/arch/versions" array field
    }

    /*
    * list all files in a specific remotely available url.
    * returns a list of nodes with .name, .remote_type and .path
    */
    _list_github_versions() {
        // for(let remote in this.remotes[REMOTE_TYPE.GITHUB])
            // use github api to check for versions for our os and arch.
    }
}

module.exports = VersionManager;

I understand that we still need to

Fohlen commented 7 years ago

This will at least require some serious changes on the instances code base to handle different binary types, I think

a-teammate commented 7 years ago

"to handle different binary types"? plz elaborate

The instance manager has a version_name field, e.g. "0.8.1". It asks the version manager for the bin folder of "0.8.1". It gets the bin folder. It starts the stuff in there. (Or e.g. `""` for the latest version)*

a-teammate commented 6 years ago

This is done with the providers of the ReleaseManager