Hello all,

### TLDR

Repo version tracking is somewhat broken due to a single feature
(commit versions).  To solve this, I propose that:

1. We remove the concept of version.yml files
2. Commit versions now conflict with ALL other versions.

I'll try to distill my thoughts into something readable below.

### DEFINITIONS

REPO DEPENDENCY (dep): A dependency on a specific version of a Mynewt
                       repo.

FIXED VERSION: An exact repo version number.
    Examples:
        1.0.1
        2.0.0

FLOATING VERSION: A partial repo version number with a "stability
                  specifier".
    Examples:
        1-latest      # (1.x.x)
        0-dev         # (0.x.x)
        1.1-latest    # (1.1.x)

COMMIT VERSION: Points to a git object (branch/tag/hash) of a repo.
                Uses the "commit" stability specifier.
    Examples:
        7088a7c029b5cc48efa079f5b6bb25e4a5414d24-commit
        mynewt_1_7_0_tag-commit
        master-commit

ROOT DEPENDENCY (ROOTDEP): A repo dependency expressed in `project.yml`

INTER DEPENDENCY (INTERDEP): A dependency of one repo on another.
                             These are expressed in the depending
                             repo's `repository.yml` file.

### CURRENT IMPLEMENTATION

When the user runs `newt upgrade`, the newt tool calculates which git
hash to check out for each repo.  The process goes like this:

1. Start with an empty working set of deps.
2. Add all rootdeps to the working set.
3. For each unvisited dep `d` in the working set:
    a. Add all of d's interdeps to the working set.
4. Repeat step 3 until all deps have been visited.

I think that procedure is pretty simple and straightforward (if a
little tedious to read).  Things get weird in the process that follows:
conflict detection.

A "conflict" is when the working set contains more than one version of
the same repo.  In other words, someone wants version X while someone
else wants version Y.  Newt can only check out a single version of a
given repo, so it reports a conflict and aborts the upgrade.  So far,
this probably sounds reasonable.  Unfortunately, the process gets
really convoluted due to commit versions.

Commit versions are problematic because they aren't linked to a version
numbers.  For example, repo R has a tag defining version 1.2.0.  What
version number should be assigned to the parent commit of this tag?
What about commits on their own branches?

The way newt solves this is by requiring a `version.yml` file in each
repo.  This file contains a single fixed version.  To determine the
version of a particular commit, newt checks out that commit and reads
the contents of `version.yml`.  When a maintainer releases a new
version of a repo, they have to update `version.yml` before creating
the tag.

I think this version.yml idea was a mistake.  The entire reason this
idea was introduced was to make it possible to gauge compatibility when
commit versions are used.  But that motivation is itself flawed; the
notion of "compatibility" is not valid when dealing with commit
versions because arbitrary commits don't come with any compatibility
guarantees.

Secondary problems with the `version.yml` idea is that it is error
prone and requires extra work for a Mynewt repo maintainer.

### PROPOSAL

1. No more version.yml files.
2. Commit versions conflict with ALL other versions.

In other words, newt doesn't try to figure out what a commit version's
"real version number" is.  One way to think of it is: each commit
version has its own unique version number.  As a consequence, different
commit versions always conflict with each other.

I should also mention that newt allows the `project.yml` file to
override any interdep with a commit version rootdep.  Newt accepts the
rootdep and does not report a conflict.

All comments welcome.

Thanks,
Chris

Reply via email to