Autoupdater - Versionsvergleich

Moin,

hat jemand von euch den Versionvergleich des Gluonautoupdaters verstanden?

Ich hatte zwischendurch mal ein paar Knoten von v2016.1.3 auf v2016.1.x aktualisiert. Also mit x meine ich den entsprechenden Git-Zweig.

Dazu musste ich damals das Manifest manipulieren. Jetzt wollte ich zurück auf v2016.1.5 und muss scheinbar wieder das Manifest manipulieren, weil die Knoten die neue Version nicht ziehen. Eigentlich müssten doch Buchstaben vor Zahlen kommen, dass heißt, wenn ich von v2016.1.x+1.1.3 auf v2016.1.5+1.1.4 aktualisieren will, müsste der Autoupdater das als neuer anerkennen? (Versionsnummerierung Schema Münsterland)

Hier mal der Code aus dem Gluon-Paket:

$ cat version.lua 
module 'autoupdater.version'


-- version comparison is based on dpkg code
local function isdigit(s, i)
  local c = s:sub(i, i)
  return c and c:match('^%d$')
end

local function char_value(s, i)
  return s:byte(i, i) or 0
end

local function char_order(s, i)
  local c = s:sub(i, i)

  if c == '' or c:match('^%d$') then
    return 0
  elseif c:match('^%a$') then
    return c:byte()
  elseif c == '~' then
    return -1
  else
    return c:byte() + 256
  end
end

-- returns true when a is a higher version number than b
function newer_than(a, b)
  local apos = 1
  local bpos = 1

  while apos <= a:len() or bpos <= b:len() do
    local first_diff = 0

    while (apos <= a:len() and not isdigit(a, apos)) or (bpos <= b:len() and not isdigit(b, bpos)) do
      local ac = char_order(a, apos)
      local bc = char_order(b, bpos)

      if ac ~= bc then
    return ac > bc
      end

      apos = apos + 1
      bpos = bpos + 1
    end

    while a:sub(apos, apos) == '0' do
      apos = apos + 1
    end

    while b:sub(bpos, bpos) == '0' do
      bpos = bpos + 1
    end

    while isdigit(a, apos) and isdigit(b, bpos) do
      if first_diff == 0 then
    first_diff = char_value(a, apos) - char_value(b, bpos)
      end

      apos = apos + 1
      bpos = bpos + 1
    end

    if isdigit(a, apos) then
      return true
    end

    if isdigit(b, bpos) then
      return false
    end

    if first_diff ~= 0 then
      return first_diff > 0
    end
  end

  return false
end

Sieht jemand, warum es in beide Richtungen nicht geht?

Liebe Grüße
Matthias

Wenn die Version wirklich „v2016.1.x+1.1.3“ ist dann wirst du davon nur mit v2016.1.y+1.1.4 oder v2016.1.z+1.1.4 updaten können.
Die Zeichen werden wie Zahlen angesehen, y bzw z ist größer als x.

Ja, mit dem y funktioniert es. Das Problem an manipulierten Manifesten ist, dass die Geräte dann in eine Updateschleife geschickt werden, wenn man nicht daneben sitzt und die IPV6s einzeln sperrt.

Warum ist denn 5 nicht größer x? Ich dachte es wäre a-z0-9?

Warum ist denn 5 nicht größer x? Ich dachte es wäre a-z0-9?

Weil in den Zeichentabellen die Zahlen vor den Buchstaben angesiedelt sind :slight_smile:

Hier im Fall von Ascii:

2 Likes

Okay, dann verstehe ich immer noch nicht, warum ich damals das Manifest manipulieren musste um von v2016.1.2+1.1.0 auf v2016.1.x+1.1.3 zu aktualisieren.

Ich halte es für durchaus überlegenswert, den Versionsnummernvergleich mit etwas mehr Intelligenz zu versehen.
Statt also zeichenweise nach numerischem char-Wert zu vergleichen zunächst einmal „numerische Blöcke“ zu bilden (Trennzeichen dabei z.B. eine Sammlung von „.,:\ /)(“) und der Übergang zwischen Ziffern und Buchstaben vice versa, ohne das Trennzeichen selbst aber als Sortierzeichen erster Ordnung einzubezieh, sondern eben nur als Trenner)
Und dann die diese Blöcke dann numerisch zu betrachten (also „123“>„13“. Und zudem Buchstaben davor. Also „0“ > „a“, so dass eine „0.11-a“ als älter eingeschätzt wird als eine „0.11.2“.

Ich kann was Versionierung angeht das hier als Leitfaden empfehlen:

Für Düsseldorf verwenden wir z.b. das folgende Schema:

v1.2.5-r2

Also [Versionsnummer]-r[Buildnummer], so können wir für die selbe Version mehrere Builds haben, normalerweise macht man nämlich nur neue Versionsnummern wenn sich was ändert :).

1 Like

Ich weiss nicht, ob Du gelesen hast, was ich geschrieben habe.

Aber um aus dem von Dir refernzeierten Leitfaden zu zitieren:

A normal version number MUST take the form X.Y.Z where X, Y, and Z are
non-negative integers, and MUST NOT contain leading zeroes. X is the
major version, Y is the minor version, and Z is the patch version.
Each element MUST increase numerically. For instance: 1.9.0 → 1.10.0 → 1.11.0.

Und genau das leistet der Autoupdater derzeit leider nicht.
Denn für ihn ist „1.10.0“ < „1.9.0“
Denn es findet kein numerischer Vergleich (und damit notwendigerweise auch vorher eine syntaktische Analyse des Versionsstrings) statt. Sonder ein alfanumerischer Vergleich, Buchstabe für Buchstabe. (Was bei UTF8 passieren würde möchte ich gar nicht wissen…)

Ich möchte an dieser Stelle auf das Versionierungskonzept der Frankfurter verweisen:

Vieleicht mag @Jason dazu etwas aus der Praxis sagen.

Der Autoupdater folgt afaik den Debian-Versionsvergleichsregeln:
https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version

First the initial part of each string consisting entirely of non-digit characters is determined. These two parts (one of which may be empty) are compared lexically. If a difference is found it is returned. The lexical comparison is a comparison of ASCII values modified so that all the letters sort earlier than all the non-letters and so that a tilde sorts before anything, even the end of a part. For example, the following parts are in sorted order from earliest to latest: ~~, ~~a, ~, the empty part, a.

Then the initial part of the remainder of each string which consists entirely of digit characters is determined. The numerical values of these two parts are compared, and any difference found is returned as the result of the comparison. For these purposes an empty string (which can only occur at the end of one or both version strings being compared) counts as zero.

These two steps (comparing and removing initial non-digit strings and initial digit strings) are repeated until a difference is found or both strings are exhausted.

1 Like

Wir hier in Frankfurt verwenden seit neuestem folgendes Versions-Schema:

<Versionsnummer>-<Branch Name>-<Branch Buildnummer>

So wie ich den Autoupdater kennengelernt habe, und das hat bei mir weh getan, so vergleicht er von links nach rechts die einzelnen Abschnitte, bis er einen Unterschied festgestellt hat.

Der Vergleich findet zeichenweise statt, solange es sich um keinen numerischen Ausdruck handelt.

  • Treffen bei einem Vergleich zwei numerische Ausdrücke aufeinander, so gewinnt der grössere. Bei Gleichheit wird dann der nächste Vergleich mit den auf die jeweiligen numerischen Ausdrücke folgenden Zeichen durchgeführt.

@adorfer Daher ist für den autoupdater „1.10.0“ > „1.9.0“ (er stellt fest, das 10 > 9 ist)

  • Treffen bei einem Vergleich ein Buchstabe bzw. ein Zeichen und die erste Ziffer eines numerischen Ausdruckes aufeinander, so wird die ASCII-Tabelle zur Hand genommen.

  • Alles was keine Ziffer ist wird als (Trenn-)Zeichen interpretiert und einzeln nach der ASCII-Tabelle ausgewertet.

EDIT: Edit gelöscht :o)

Da fehlt irgendwie eine Schlüssel-Information, hab aber keine Ahnung welche.
Kannst Du etwas Genaueres zur Behandlung und zur Manipulation der Manifestdatei in Münster sagen?

1 Like

Mit Manipulation meine ich, dass ich, wie oben vorgeschlagen in der Manifestdatei die Version auf z. B. 2016.1.y ändere, obwohl es nur 2016.1.5 ist. Man spielt also eine neuere Version vor.

Das haben wir früher auch so gemacht, allerdings ist das sehr unpraktisch wenn mal jemand von Stable zu Beta oder andersherum wechseln möchte, daher läuft es nun so:

So einfach ist das bei uns nicht. Wir haben das gerade deshalb so gemacht, damit man sehr einfach kreuz und quer, rauf und runter wechseln kann.

Siehe: DiesUndDas/konzept_versioning_policy.md at master · oszilloskop/DiesUndDas · GitHub

Bei uns sieht das Versions Schema letztendlich dann so aus:

1.11-stable-12 (neues Datum)
1.10.3-test-62 (nicht so neues Datum)
1.10.2.1-dev-106 (älteres Datum)
1.10-stable-11 (ganz altes Datum)

Das ist aber ein anderes Thema, da kann man Tage, ja Wochen bis zur Ohnmacht drüber philosophieren …

Vielleicht macht es auch Sinn, einfach die Anforderungen runterzuschrauben? Mit einem Schema 0.M.m~build und 0.M.m-rel kommt der bestehende Code doch klar, auf welcher Seite des Bildschirms existiert dann ein Problem? [M=Major, m=minor]

Ich habe vor Zeiten auf ein banales Timestamp (YYYYMMTThh) umgestellt mit einem suffix für sta/bet/exp.
Wer mehr wissen möchte, der soll gefälligst ins Git schauen. Außer den jeweiligen community-MaintainerInnen blickt in „1.0.51-rc3-stable“ sowieso niemand durch und alle anderen müssen (wer hätte es nicht anders vermutet) ins Git schauen.

Aber das ist doch totaler Mist, genau wie so etwas hier:
v1.10.3-test-83, das baut dann laut Daten in der Karte auf gluon-2016.1.4 auf.

Wenn dann mal, wie öfters, der Fall besteht bei Gluon Problemen zwischen den Communities zu vergleichen wird das selbst für an sich eingeweihte enorm schwierig.

Ist es wirklich zu viel verlangt dem Gluon Release Tag auf dem die Firmware basiert aufzunehmen?

Dazu falls fünf Minuten je Release Zeit sind noch eine Priese Doku, weil man im git bei weitem nicht alles sehen kann:
https://wiki.freifunk.net/Freifunk_Aachen/Firmware#Stable

Meine Frage ist beantwortet. Ihr könnt gerne noch über Versionsschemata diskutieren, ich wollte nur wissen, warum die Knoten bei uns nicht ziehen. Das ist gelöst.

1 Like

Provokante Frage, direkte Antwort: Ja.

Wir bauen nicht stumpf vanilla Gluon mit eigener site.conf, aktuell patchen wir auch das OpenWRT unter 2015.1.x. Insofern ist die Gluon-Basis nur ein Aspekt, und der wird in der minor number ausgewiesen. Unter anderem würde es die Nutzer zurecht verwirren, wenn wir Mitte 2016 eine Firmware aus 2015 rausbrächten … Suffixe für stable & Co. machen wir nicht, das würde einen neuen Build implizieren (oder andere Werte im Build und im Manifest) und damit etwas freigeben, was so nie getestet wurde. Aber das hat mit dem Versionsvergleich schon nichts mehr zu tun.

1 Like

Klingt vielversprechend, habt ihr eine Doku was ihr baut?
Könnte mir gut vorstellen, dass es sich lohnt etwas davon zu übernehmen.

Da OT, Info per PN.