alexlarsson/xdg-app

tag/branch redundancy in layout?

Closed this issue · 4 comments

trans commented

Just a little confused by the file system layout, e.g.

── app
│   └── org.gnome.GEdit
│       └── x86_64
│           └── master
│               ├── active -> cf22ec5c375bba629b33385a…
│               ├── cf22ec5c375bba629b33385a…
│               │   ├── export
│               │   ├── files
│               │   │   └┈
│               │   └── metadata
│               └── origin

Doesn't master point to a particular checkout/hash already (i.e. cf22ec...)? And in the runtime example:

├── runtime
│   └── org.gnome.Platform
│       └── x86_64
│           └── 3.14
│               ├── 71885e962e0daa8635cc7f33…
│               │   └── files
│               │       └┈
│               ├── active -> 71885e962e0daa8635cc7f33…
│               └── origin

Again, typically 3.14 is going to be tag in the repo that points to a checkout/hash (i.e. 71885e...).

So isn't it essentially redundant to have the tag and the only possible hash within it? In other words why not just:

├── runtime
│   └── org.gnome.Platform
│       └── x86_64
│           ├── 3.14
│           │   └── files
│           │       └┈
│           ├── active -> 3.14
│           └── origin

Of course, there is nothing stopping one from checking out an unnamed branch rather than a tag, and then it might look like this:

├── runtime
│   └── org.gnome.Platform
│       └── x86_64
│           ├── 71885e962e0daa8635cc7f33…
│           │   └── files
│           │       └┈
│           ├── active -> 71885e962e0daa8635cc7f33…
│           └── origin

But I imagine that would be fairly exceptional.

It may look redundant in the static case, but it is important during updates. When an older revision is on disk we check out the new revision right next to it, and then do a atomic reset of the symlink to switch the active one.

In fact, we even support atomic updates while the app is running, because after checking out the other directory we move the old one to ~/.local/share/xdg-app/.removed, and only delete it when the last running instance of that version stops running. This means you can finally do completely safe online updates.

If we were to use your model to update the 3.14 branch we would have to move the old 3.14 directory away before moving the new one in place, which is not atomic. I.e. if at the time inbetween someone would run "xdg-app run" on that app the directory would be empty.

trans commented

I would expect it to install, for example, 3.14.1 so there would be no need to move 3.14 out of the way. Even if it were a "between release" build, there could be a build number attached to the version or just use the ref itself at that level.

├── runtime
│   └── org.gnome.Platform
│       └── x86_64
│           ├── 3.14
│           │   └── files
│           │       └┈
│           ├── 71885e962e0daa8635cc7f33…
│               └── files
│                   └┈

I don't see why it couldn't still be atomic.

Update to "3.14.1" is not how ostree (or git for that matter) works. We're following a branch, which happens to be "3.14", it could also be called "master" or "unstable" or whatever. The main thing is that its a names branch we are following, and a branch is made up of a sequence of commits. At any time you can use ostree to update your local copy to the most recent commit of that branch upstream. This is how we do updates.

The actual ostree branch is called "runtime/org.gnome.Platform/x86_64/3.14" which is why we put the checkouts of that branch under that directory. Obviously it would work if we put it in the directory above too, but the it would not really make a difference and it would be a bit strange.

What wouldn't be atomic is replacing one directory with contents with another directory. So, you can't replace the "master" directory with another "master" directory atomically, which is what we want to do during upgrade. What you can do however is atomically replace a symlink that points to the first directory with one that points to the other directory, which is why we do this for updates.

You can actually install (and later update) completely different versions of an app in parallel, so you could have both "app/org.gimp.Gimp/x86_64/master" and "app/org.gimp.Gimp/x86_64/beta" installed. This would look somewhat similar to what you describe:

├── app
│ └── org.gimp.Gimp
│ └── x86_64
│ ├── 2.8
│ │ ├── 71885e962e0daa8635cc7f33
│ │ │ └── files
│ │ └ active -> 71885e962e0daa8635cc7f33
│ └── 2.10
│ ├── 81885e962e0daa8635cc7f33
│ │ └── files
│ └ active -> 81885e962e0daa8635cc7f33

In this setup only one of the versions is "current". This is the default version that is started when you do xdg-app run, and it is the only one that gets its files exported (so that it appears in the desktop shell menus, etc). You have to manually specify the version to start the other one.