This is a story about counter-intuitive probabilities and how a small bit of doubt turned out to be very justified.
It begins with the game To Court the King (German: Um Krone und Kragen ). It is a nice game with dice and cards, where you start with a few dice, and use your dice rolls to buy additional cards, which give you extra dice or special powers to modify the dice that you rolled. You can actually roll your dice many times, but every time, you have to set aside at least one die, which you can no longer change or reroll, until eventually all dice have been set aside.
A few years ago, I have played this game a lot, both online (on yucata.de) as well as in real life. It soon became apparent that it is almost always better to go for the cards that give you an extra die, instead of those that let you modify the dice. Intuitively, this is because every additional die allows you to re-roll your dice once more.
I concluded that if I have a certain number of dice (say, n), and I want to have a sum as high as possible at the end, then it may make sense to reroll as many dice as possible, setting aside only those showing a 6 (because that is the best you can get) or, if there is no dice showing a 6, then a single die with the best score. Besides for small number of dice (2 or 3), where even a 4 or 5 is worth keeping, this seemed to be a simple, obvious and correct strategy to maximize the expected outcome of this simplified game.
It is definitely simple and obvious. But some doubt that it was correct remained. Having one more die still in the game (i.e. not set aside) definitely improves your expected score, because you can reroll the dice more often. How large is this advantage? What if it ever exceeds 6 then it would make sense to reroll a 6. The thought was strange, but I could not dismiss it.
So I did what one does these days if one has a question: I posed it on the mathematics site of StackExchange. That was January 2015, and nothing happened.
I tried to answer it myself a month later, or at least work towards at an answer, and did that by brute force. Using a library for probabilistic calculations for Haskell I could write some code that simply calculated the various expected values of n dice for up to n = 9 (beyond that, my unoptimized code would take too long):
Note that this calculation, although printed as floating point numbers, is performed using fractions of unbounded integers, so there are no rounding issues that could skew the result.
The result supported the hypothesis that there is no point in rolling a 6 again: The value of an additional die grows and approaches 6 from beyond, but judging from these number is never going to reach it.
Then again nothing happened. Until 14 month later, when some Byron Schmuland came along, found this an interesting puzzle, and set out a 500 point bounty to whoever solved this problem. This attracted a bit attention, and a few not very successful attempts at solving this. Eventually it reached twitter, where Roman Cheplyaka linked to it.
Coincidally a day later some joriki came along, and he had a very good idea: Why not make our life easier and think about dice with less sides, and look at 3 instead of 6. This way, and using a more efficient implementation (but still properly using rationals), he could do a similar calculation for up to 50 dice. And it was very lucky that he went to 50, and not just 25, because up to 27, the results were very much as expected, approaching value of +3 from below. But then it surpassed +3 and became +3.000000008463403.
In other words: If you have roll 28 dice, and you have exactly two dice showing a 3, then it gives you better expected score if you set aside only one 3, and not both of them. The advantage is minuscule, but that does not matter it is there.
From then on, the results behaved strangely. Between 28 and 34, the additional value was larger than 3. Then, from 35 on again lower than 2. It oscillated. Something similar could be observed when the game is played with coins.
Eventually, joriki improved his code and applied enough tricks so that he could solve it also for the 6-sided die: The difference of the expected value of 198 dice and having 199 dice is larger than 6 (by 10 21...)!
The optimizations that allowed him to calculate these numbers in a reasonable amount of time unfortunately was to assume that my original hypothesis (never rerolling a 6 is optimal), which held until n < 199. But this meant that for n > 199, the code did not yield correct results.
What is the rationale of the story? Don t trust common sense when it comes to statistics; don t judge a sequence just from a few initial numbers; if you have an interesting question, post it online and wait for 16 months.
Author: ceridwen
The 0.1 alpha release of reprotest has been accepted into Debian
unstable and is available for install at
packages.debian.org or
through apt.
I've been working on redesigning reprotest so that it runs commands
through autopkgtest's adt_testbed interface. For the most part, I
needed to replace explicit calls to Python standard library functions
for copying files and directories with calls to
adt_testbed.Testbed.command() with copyup and copydown, and to
use Testbed.execute() and Testbed.check_exec() to run commands
instead of subprocess.
To test reprotest on the actual containers requires having containers
constructed for this purpose. autopkgtest has a test that builds a
minimal chroot. I considered doing something like this approach or
using BusyBox. However, I have a Python script that mocks a build
process, which requires having Python available in the container, and
while I looked into
busybox-python and
MicroPython to keep the
footprint small, I decided that for now this would take too much work
and decided to go straight to the autopkgtest recommendations for
building containers, mk-sbuild
and vmdebootstrap. (I also
ended up discovering a
bug
in debootstrap.) This means that to get the tests run requires some
manual setup at the moment. In the long run, I'd like to improve
that, but it's not an immediate priority. While working on adding
tests for the other containers supported by autopkgtest, I also
converted to py.test so that I
could use fixtures and
parametrization to run
the Cartesian product of each variation with each container.
With tests written, I started trying to verify that my new code
worked. One problem I encountered while trying to debug was that I
wasn't getting full error output. In VirtSubproc.check_exec(),
execute_timeout() acts something like a Popen() call:
(status, out, err) = execute_timeout(None, timeout, real_argv,
stdout=stdout, stderr=subprocess.PIPE)
if status:
bomb("%s%s failed (exit status %d)" %
((downp and "(down) " or ""), argv, status))
if err:
bomb("%s unexpectedly produced stderr output %s'" %
(argv, err))
The problem with this is that if the call returns a non-zero exit
code, which is typical for program failures, stderr doesn't get
included in the error message.
I changed the first if-block to:
if status:
bomb("%s%s failed (exit status %d)\n%s" %
((downp and "(down) " or ""), argv, status, err))
Another example is that autopkgtest calls schroot with the --quiet
flag, which in one case was making schroot fail without any output
due to a misconfiguration. I'm still trying to find and eliminate
more places where errors are silenced.
autopkgtest was designed to be installed with Debian's packaging
system, which handles arbitrary files and directory layouts.
Unfortunately, setuptools is completely different in a way that
doesn't work well with autopkgtest's design. (I'm sure this is partly
because setuptools has to support all the different major OSes that
run Python, including Windows.) As I discussed last
week,
autopkgtest has Python scripts in virt/ that are executed by
subprocess calls in adt_testbed. Because these scripts import
files from lib/, there needs to be an __init__.py in virt/ to
make it into a package and a sys.path hack in each script to allow
it to find modules in lib/. Unfortunately, setuptools will not
install this structure. First, setuptools will not install any file
without a .py extension into a package. Theoretically, this is
fixable, the files in virt/ are Python scripts so I could rename
them. (Theoretically, there's supposed to be some workaround
involving MANIFEST.in or package_data in setup.py, but I have
yet to find any documentation or explanation giving a method for
installing non-Python files inside a Python package.) Second,
however, setuptools does not preserve the executable bit when
installing package files. The obvious workaround, changing the
subprocess calls so that they invoke python virt/foo.py rather
than virt/foo.py requires changing all the internal calls in the
autopkgtest code, which I'm loathe to do for fear of breaking it.
(It's not clear to me I can easily find all of the calls, for
starters.)
There are about three solutions to this I see at the moment, all of
them difficult. The first involves using either the scripts keyword
or console_scripts entry point in setup.py, as explained
here.
The scripts keyword is supposed to preserve the executable bit
according to this StackExchange
question,
but I haven't verified this myself, and like everything to do with
setuptools I don't trust anything anyone says about it without testing
it myself. It also has the disadvantage of dumping them all into the
common scripts directory. Using console_scripts involves rewriting
all of them to have an executable function I can refer to in
setup.py. I worry that this would be both fragile and break
existing expectations in the rest of the autopkgtest code, but it
might be the best solution. The third solution involves refactoring
of all the autopkgtest code to import the code in the scripts rather
than running it through subprocess calls. I'm reluctant to do this
because I think it's almost certain to break things that will require
significant work to fix.
Getting setuptools to install the autopkgtest code correctly is one
blocker for the next release. Another is that autopkgtest's handling
of errors during the build process involves closing the
adt_testbed.Testbed so it won't take further commands.
Unfortunately, this handling runs before any cleanup code I write to
run outside it, which means that at the moment errors during the build
will result in things like disorderfs being left mounted.
The last release blocker is that adt_testbed doesn't have any way to
set a working directory when running commands. For instance, the
virt/schroot script always calls schroot with --directory=/. I
thought about trying to use absolute paths, but decided this was
unintuitive and impractical. For the user, this would mean that
instead of running something simple like make in the correct
directory, they would have to run make
--file=/absolute/path/to/Makefile or something similar, making all
paths absolute. I worry that some build scripts wouldn't handle this
correctly, either: for instance, running python setup.py from a
different directory can have different effects because Python's path
is initialized to contain the current directory. Changing this is
going to require going deeper into the autopkgtest code than I'd
hoped.
I intend to try to resolve these three issues over the next week and
then prepare the next release, though how much progress I make depends
on how thorny they turn out to be.
Out of 46,500,001 electorate 17,410,742 voted to leave, which is a mere 37.4% or just over a third. [source]. On my books this is not a clear expression of the UK wishes.
The reaction that the results have caused are devastating. The Scottish First Minister has announced plans for 2nd Scottish Independence referendum [source]. Londoners are filing petitions calling for Independent London [source, source]. The Prime Minister announced his resignation [source]. Things are not stable.
I do not believe that super majority of the electorate are in favor of leaving the EU. I don't even believe that those who voted to leave have considered the break up of the UK as the inevitable outcome of the leave vote. There are numerous videos on the internet about that, impossible to quantify or reliably cite, but for example this [source]
So What Now?
P R O T E S T
I urge everyone to start protesting the outcome of the mistake that happened last Thursday. 4th of July is a good symbolic date to show your discontent with the UK governemnt and a tiny minority who are about to cause the country to fall apart with no other benefits. Please stand up and make yourself heard.
There are 64,100,000 people living in the UK according to the World Bank, maybe the government should fear and listen to the unheard third. The current "majority" parliament was only elected by 24% of electorate.
It is time for people to actually take control, we can fix our parliament, we can stop austerity, we can prevent the break up of the UK, and we can stay in the EU. Over to you.
ps. How to elect next PM?
Electing next PM will be done within the Conservative Party, and that's kind of a bummer, given that the desperate state the country currently is in. It is not that hard to predict that Boris Johnson is a front-runner. If you wish to elect a different PM, I urge you to splash out 25 quid and register to be a member of the Conservative Party just for one year =) this way you will get a chance to directly elect the new Leader of the Conservative Party and thus the new Prime Minister. You can backdoor the Conservative election here.
Here comes my journey till the mid-term (June 21st) as a blog to share my experience.
I have previously worked on some social related projects such as smart guidance for blind and sensor based wireless controller . I have been selected as a speaker for FOSSASIA-16 (Asia s premier technological event)to talk on the project smart guidance for blind .FOSSASIA speakers. It was a great experience participating in the technological event in Singapore science centre.Got an opportunity to meet open source contributors from all over the world(even though it is an Asian event, participation was all over from the world). There were pre-meetups for FOSSASIA on the day before three-day event.I have attended the one organised by RedHat, Singapore.Discussed on many topics related to open source.
Three days of FOSSASIA event was a great experience.It was the second time as a speaker in an international conference.My talk was on the second day.Sharing is the best way to increase your knowledge. Talks and workshops were brainstorming.Learnt many new things and got the courage to contribute to the open source.Met Daniel Pocock in Debian exhibition table.Meeting awesome people can be the turning point of life.Had a discussion about the Debian projects and it motivated me for open source software.We have discussed about the Real Time Communication and was encouraged to apply for GSoC (Google Summer of Code). As per our discussion, prepared the project proposal on improving voice,video and chat communication with free software and submitted it for GSoC. I have been selected to contribute for Debian with stipend from Google.
This was my first application for GSoC and I have been selected to contribute for open source and free software. I would like to thank Google and Debian for giving this amazing experience.
Learning and coding have begun.Updated my laptop with Jessie, latest version of Debian.Get acquainted with the new platform.Got to learn many things about Real Time Communication.Learnt more about SIP, XMPP, peer-to-peer technology to work on my project.It s always better to be clear with theory before coding.When it comes to voice and video over IP, most people nowadays are quick to use Skype, Whatsapp, or Viber. My main goals of the project are helping people to avoid using proprietary communications tools like Skype, Viber and WhatsApp and simplifying the setup of free alternatives like Jitsi, Linphone, Ekiga, Tox (qtox), Mumble.Downloaded some of the already available open source VoIP to find the problems behind it and improve it further.Bootstrapping any business relevant network based on these free alternatives is still hard.
Would you like to list the senders, receivers and date of the messages in the inbox of your mail.Python has a library file IMAP which can be used to connect to an email account, examine every message in every folder and look at the To , From and CC headers of every email message in the folder.
Do you have phone numbers and other contact details in old emails? Would you like a quick way to data-mine your inbox to find them and help migrate them to your address book? Got the help from phonenumbers library for parsing, formatting, and validating international phone numbers.I would like to share how I imported this library file into my coding.Download the given library file and open the file in the terminal.Type
$ python setup.py install
to install the library file.Now you can call the functions by importing phonenumbers.
You can go through the code in my GitHub profile here.(Recently started committing my projects in GitHub)
Iain R. Learmonth joined my journey as a mentor.Helped in solving some issues in my coding through GitHub.
It was a wonderful journey till now.Will be working further to improve voice, video and chat communication with free software.Stay connected to know more about my further journey through GSoC.
Contribute constructively - no one likes to be told "You've got a REALLY ugly baby there" or equivalent.
Think through what you post: check references and check that it reads clearly and is spelled correctly
Add value
When contributing bug reports:
Provide as full details of hardware and software as you have
Answer questions carefully: Ask questions the smart way: http://www.catb.org/esr/faqs/smart-questions.html
Be prepared to follow up queries / provide sufficient evidence to reproduce behaviour or provide pathological test cases
Provide a patch if possible: even if it's only pseudocode
When adding to / modifying FLOSS software:
Keep pristine sources that you have downloaded
Maintain patch series against pristine source
Talk to the originators of the software / current maintainers elsewhere
Follow upstream style if feasible / a consistent house style if not
Be generous in what you accept: be precise in what you put out
Don't produce licence conflicts - check and check again that your software can be distributed.
Don't apply inconsistent copyrights
When writing new FLOSS software / "freeing" prior commercial/closed code under a FLOSS licence
Make permissions explicit and publish under a well established FLOSS licence
Be generous to potential contributors and collaborators: render them every assistance so that they can help you better
Be generous in what you accept: be precise in what you put out
Don't produce licence conflicts - check and check again that your software can be distributed.
Don't apply inconsistent copyrights: software you write is your copyright at the outset until you assign it elsewhere
Contribute documentation / examples
Maintain a bugtracker and mailing lists for your software
If you are required to sign a contributor license agreement [CLA]
Ensure that you have the rights you purport to assign
Assign the minimum of rights necessary - if you can continue to allow full and free use of your code, do so
Meet any required code of conduct [CoC] stipulations in addition to the CLA
Always remember in all of this: just because you understand your code and your working practices doesn't mean that anyone else will. There is no automatic right to contribution nor any necessary assumption or precondition that collaborators will come forward. Just because you love your own code doesn't mean that it merits anyone else's interest or that anyone else should value it thereby "Just because it scratches your itch doesn't mean that it scratches anyone else's - or that it's actually any good / any use to anyone else"
In a prior post,
I gave an overview of the OpenStack CI system and how jobs were
started. In that I said
(It is a gross oversimplification, but for the purposes of OpenStack
CI, Jenkins is pretty much used as a glorified ssh/scp wrapper. Zuul
Version 3, under development, is working to remove the need for
Jenkins to be involved at all).
Well some recent security issues with Jenkins and other changes has
led to a roll-out of what is being called Zuul 2.5, which has indeed
removed Jenkins and makes extensive use of Ansible as the basis for
running CI tests in OpenStack. Since I already had the diagram, it
seems worth updating it for the new reality.
OpenStack CI Overview
While previous post was really focused on the image-building
components of the OpenStack CI system, overview is the same but more
focused on the launchers that run the tests.
The process starts when a developer uploads their code to
gerrit via the git-review tool. There is no further action
required on their behalf and the developer simply waits for
results of their jobs.
Gerrit provides a JSON-encoded "fire-hose" output of everything
happening to it. New reviews, votes, updates and more all get sent
out over this pipe. Zuul is the overall scheduler
that subscribes itself to this information and is responsible for
managing the CI jobs appropriate for each change.
Zuul has a configuration
that tells it what jobs to run for what projects. Zuul can do lots
of interesting things, but for the purposes of this discussion we
just consider that it puts the jobs it wants run into gearman
for a launcher to consume. gearman is a
job-server; as they explain it "[gearman] provides a generic
application framework to farm out work to other machines or
processes that are better suited to do the work". Zuul puts into
gearman basically a tuple (job-name,node-type) for each
job it wants run, specifying the unique job name to run and what
type of node it should be run on.
A group of Zuul launchers
are subscribed to gearman as workers. It is these Zuul
launchers that will consume the job requests from the queue and
actually get the tests running. However, a launcher needs two
things to be able to run a job a job definition (what to actually
do) and a worker node (somewhere to do it).
The first part what to do is provided by job-definitions
stored in external YAML files. The Zuul launcher knows how to
process these files (with some help from Jenkins Job Builder, which
despite the name is not outputting XML files for Jenkins to
consume, but is being used to help parse templates and macros
within the generically defined job definitions). Each Zuul
launcher gets these definitions pushed to it constantly by Puppet,
thus each launcher knows about all the jobs it can run
automatically. Of course Zuul also knows about these same job
definitions; this is the job-name part of the tuple we said it
put into gearman.
The second part somewhere to run the test takes some more
explaining. To the next point...
Several cloud companies donate capacity in their clouds for
OpenStack to run CI tests. Overall, this capacity is managed by a
customized management tool called nodepool
(you can see the details of this capacity at any given time by
checking the nodepool configuration).
Nodepool watches the gearman queue and sees what requests are
coming out of Zuul. It looks at node-type of jobs in the queue
(i.e. what platform the job has requested to run on) and decides
what types of nodes need to start and which cloud providers have
capacity to satisfy demand.
Nodepool will start fresh virtual machines (from images built daily
as described in the prior post), monitor their start-up and, when
they're ready, put a new "assignment job" back into gearman with
the details of the fresh node. One of the active Zuul launchers
will pick up this assignment job and register the new node to
itself.
At this point, the Zuul launcher has what it needs to actually get
jobs started. With an fresh node registered to it and waiting for
something to do, the Zuul launcher can advertise its ability to
consume one of the waiting jobs from the gearman queue. For
example, if a ubuntu-trusty node is provided to the Zuul
launcher, the launcher can now consume from gearman any job it
knows about that is intended to run on an ubuntu-trusty node
type. If you're looking at the launcher code
this is driven by the NodeWorker class you can see this being
created in response to an assignment via
LaunchServer.assignNode.
To actually run the job where the "job hits the metal" as it were
the Zuul launcher will dynamically construct an Ansible playbook to run. This
playbook is a concatenation of common setup and teardown operations
along with the actual test scripts the jobs wants to run. Using
Ansible to run the job means all the flexibility an orchestration
tool provides is now available to the launcher. For example, there
is a custom console streamer
library that allows us to live-stream the console output for the
job over a plain TCP connection, and there is the possibility to
use projects like ARA
for visualisation of CI runs. In the future, Ansible will allow
for better coordination when running multiple-node testing jobs
after all, this is what orchestration tools such as Ansible are
made for! While the Ansible run can be fairly heavyweight
(especially when you're talking about launching thousands of jobs
an hour), the system scales horizontally with more launchers able
to consume more work easily.
When checking your job results on logs.openstack.org you will
see a _zuul_ansible directory now which contains copies of the
inventory, playbooks and other related files that the launcher used
to do the test run.
Eventually, the test will finish. The Zuul launcher will put the
result back into gearman, which Zuul will consume (log copying
is interesting but a topic for another day). The testing node will
be released back to nodepool, which destroys it and starts all over
again nodes are not reused and also have no sensitive details on
them, as they are essentially publicly accessible. Zuul will wait
for the results of all jobs for the change and post the result back
to Gerrit; it either gives a positive vote or the dreaded negative
vote if required jobs failed (it also handles merges to git, but
that is also a topic for another day).
Work will continue within OpenStack Infrastructure to further enhance
Zuul; including better support for multi-node jobs and "in-project"
job definitions (similar to the https://travis-ci.org/ model);
for full details see the spec.
I'm back from the GTK hackfest in Toronto, Canada and mostly recovered from
jetlag, so it's time to write up my notes on what we discussed there.
Despite the hackfest's title, I was mainly there to talk about non-GUI
parts of the stack, and technologies that fit more closely in what could
be seen as the freedesktop.org platform than they do in GNOME. In particular,
I'm interested in Flatpak as a way to deploy self-contained "apps" in a
freedesktop-based, sandboxed runtime environment layered over
the Universal Operating System and
its many derivatives,
with both binary and source compatibility with other GNU/Linux distributions.
I'm mainly only writing about discussions I was directly involved in:
lots of what sounded like good discussion about the actual graphics toolkit
went over my head completely :-)
More notes, mostly from Matthias
Clasen, are available on the GNOME wiki.
In no particular order:
Thinking with portals
We spent some time discussing Flatpak's portals, mostly on Tuesday.
These are the components that expose a subset of desktop functionality
as D-Bus services that can be used by contained applications: they are
part of the security boundary between a contained app and the rest of the
desktop session. Android's intents are a similar concept seen elsewhere.
While the portals are primarily designed for Flatpak, there's no real
reason why they couldn't be used by other app-containment solutions
such as Canonical's Snap.
One major topic of discussion was their overall design and layout. Most
portals will consist of a UX-independent part in Flatpak itself, together
with a UX-specific implementation of any user interaction the portal
needs. For example, the portal for file selection has a D-Bus service
in Flatpak, which interacts with some UX-specific service that will
pop up a standard UX-specific "Open" dialog for GNOME and probably
other GTK environments, that dialog is in (a branch of) GTK.
A design principle that was reiterated in this discussion is that
the UX-independent part should do as much as possible, with the
UX-specific part only carrying out the user interactions that need
to comply with a particular UX design (in the GTK case, GNOME's design).
This minimizes the amount of work that needs to be redone for other
desktop or embedded environments, while still ensuring that the other
environments can have their chosen UX design. In particular, it's
important that, as much as possible, the security- and performance-sensitive
work (such as data transport and authentication) is shared between all
environments.
The aim is for portals to get the user's permission to carry out actions,
while keeping it as implicit as possible, avoiding an "are you sure?" step
where feasible. For example, if an application asks to open a file,
the user's permission is implicitly given by them selecting the file
in the file-chooser dialog and pressing OK: if they do not want this
application to open a file at all, they can deny permission by cancelling.
Similarly, if an application asks to stream webcam data, the UX we expect
is for GNOME's Cheese app (or a similar non-GNOME app) to appear, open
the webcam to provide a preview window so they can see what they are about
to send, but not actually start sending the
stream to the requesting app until the user has pressed a "Start" button.
When defining the API "contracts" to be provided by applications in that
situation, we will need to be clear about whether the provider is expected
to obtain confirmation like this: in most cases I would anticipate that
it is.
One security trade-off here is that we have to have a small amount of
trust in the providing app. For example, continuing the example of Cheese
as a webcam provider, Cheese could (and perhaps should) be a contained
app itself, whether via something like Flatpak, an LSM like AppArmor
or both. If Cheese is compromised somehow, then whenever it is running, it
would be technically possible for it to open the webcam, stream video and
send it to a hostile third-party application. We concluded that this is an
acceptable trade-off: each application needs to be trusted with the privileges
that it needs to do its job, and we should not put up barriers that are easy
to circumvent or otherwise serve no purpose.
The main (only?) portal so far is the file chooser, in which the contained
application asks the wider system to show an "Open..." dialog, and if the user
selects a file, it is returned to the contained application through a FUSE
filesystem, the document portal. The reference implementation of the UX for
this is in GTK, and is basically a GtkFileChooserDialog. The intention is
that other environments such as KDE will substitute their own equivalent.
Other planned portals include:
image capture (scanner/camera)
opening a specified URI
this needs design feedback on how it should work for non-http(s)
sharing content, for example on social networks (like Android's Sharing menu)
proxying joystick/gamepad input (perhaps via Wayland or FUSE, or perhaps
by modifying libraries like SDL with a new input source)
network proxies (GProxyResolver) and availability (GNetworkMonitor)
contacts/address book, probably vCard-based
notifications, probably based on freedesktop.org Notifications
video streaming (perhaps using Pinot, analogous to PulseAudio but for video)
Environment variables
GNOME on Wayland currently has a problem with environment variables:
there are some traditional ways to set environment variables for X11
sessions or login shells using shell script fragments (/etc/X11/Xsession.d,
/etc/X11/xinit/xinitrc.d, /etc/profile.d), but these do not apply to
Wayland, or to noninteractive login environments like cron and
systemd --user. We are also keen to avoid requiring a Turing-complete shell
language during session startup, because it's difficult to reason about
and potentially rather inefficient.
Some uses of environment variables can be dismissed as unnecessary or even
unwanted, similar to the statement in Debian Policy 9.9: "A program must not
depend on environment variables to get reasonable defaults." However,
there are two common situations where environment variables can be necessary
for proper OS integration: search-paths like $PATH, $XDG_DATA_DIRS and
$PYTHONPATH (particularly necessary for things like Flatpak), and
optionally-loaded modules like $GTK_MODULES and $QT_ACCESSIBILITY
where a package influences the configuration of another package.
There is a stopgap solution in GNOME's gdm display manager,
/usr/share/gdm/env.d, but this is gdm-specific and
insufficiently expressive to provide the functionality needed by
Flatpak: "set XDG_DATA_DIRS to its specified default value if unset,
then add a couple of extra paths".
pam_env comes closer PAM is run at every transition from "no user logged
in" to "user can execute arbitrary code as themselves" but it doesn't
support .d fragments, which are required if we want distribution packages
to be able to extend search paths. pam_env also turns off per-user
configuration by default, citing security concerns.
I'll write more about this when I have a concrete proposal for how to solve it.
I think the best solution is probably a PAM module similar to pam_env but
supporting .d directories, either by modifying pam_env directly or
out-of-tree, combined with clarifying what the security concerns for
per-user configuration are and how they can be avoided.
Relocatable binary packages
On Windows and OS X, various GLib APIs automatically discover where the
application binary is located and use search paths relative to that;
for example, if C:\myprefix\bin\app.exe is running, GLib might put
C:\myprefix\share into the result of g_get_system_data_dirs(),
so that the application can ask to load app/data.xml from the data
directories and get C:\myprefix\share\app\data.xml. We would like
to be able to do the same on Linux, for example so that the apps in a
Flatpak or Snap package can be constructed from RPM or dpkg packages without
needing to be recompiled for a different --prefix, and so that other
third-party software packages like the games on Steam and gog.com can
easily locate their own resources.
Relatedly, there are currently no well-defined semantics for what happens
when a .desktop file or a D-Bus .service file has Exec=./bin/foo.
The meaning of Exec=foo is well-defined (it searches $PATH) and the
meaning of Exec=/opt/whatever/bin/foo is obvious. When this came up in
D-Bus previously, my assertion was that the meaning should be the same as
in .desktop files, whatever that is.
We agreed to propose that the meaning of a non-absolute path in a .desktop
or .service file should be interpreted relative to the directory
where the .desktop or .service file was found: for example, if
/opt/whatever/share/applications/foo.desktop says Exec=../../bin/foo,
then /opt/whatever/bin/foo would be the right thing to execute.
While preparing a mail to the freedesktop and D-Bus mailing lists proposing
this, I found that I had
proposed the same thingalmost 2 years ago...
this time I hope I can actually make it happen!
Flatpak and OSTree bug fixing
On the way to the hackfest, and while the discussion moved to topics that I
didn't have useful input on, I spent some time fixing up the Debian packaging
for Flatpak and its dependencies. In particular, I did my first upload
as a co-maintainer of bubblewrap,
uploaded ostree to unstable (with the known limitation that the grub, dracut
and systemd integration is missing for now
since I haven't been able to test it yet), got
most of the way through packaging Flatpak 0.6.5 (which I'll upload soon),
cherry-picked the right patches to make ostree compile on Debian 8 in an effort
to make backports trivial, and spent some time disentangling
a flatpak test failure
which was breaking the Debian package's installed-tests.
I'm still looking into
ostree test failures on little-endian MIPS,
which I was able to reproduce on a Debian porterbox just before the end of the
hackfest.
OSTree + Debian
I also had some useful conversations with developers from
Endless, who recently opened up a version of their
OSTree build scripts
for public access. Hopefully that information brings me a bit closer to
being able to publish a walkthrough for
how to deploy a simple Debian derivative using OSTree
(help with that is very welcome of course!).
GTK life-cycle and versioning
The life-cycle of GTK releases has already been
mentioned here and elsewhere, and there are some interesting responses
in the comments on my earlier blog post.
It's important to note that what we
discussed at the hackfest is only a proposal: a hackfest discussion between
a subset of the GTK maintainers and a small number of other GTK users
(I am in the latter category)
doesn't, and shouldn't, set policy for all of GTK or for all of GNOME. I
believe the intention is that the GTK maintainers will discuss the proposals
further at GUADEC, and make a decision after that.
As I said before, I hope that being more realistic about API and ABI
guarantees can avoid GTK going too far towards either of the possible
extremes: either becoming unable to advance because it's too constrained
by compatibility, or breaking applications because it isn't constrained
enough. The current situation, where it is meant to be compatible within
the GTK 3 branch but in practice applications still sometimes break,
doesn't seem ideal for anyone, and I hope we can do better in future.
Acknowledgements
Thanks to everyone involved, particularly:
Matthias Clasen, who organised the hackfest and took a lot of notes
Allison Lortie, who provided on-site cat-herding and led us to some
excellent restaurants
Red Hat Inc., who provided the venue (a conference room
in their Toronto office), snacks, a lot of coffee, and several participants
my employers Collabora Ltd., who sponsored my travel and accomodation
Git is a version control system which is very common among developers. I m not going to explain how git works, because there are plenty of great introductory tutorials on the internet for that. However, I would like to documment the commands I frequently use
1. First, we initialize a git repo. Take care to ensure that you initialise the repo in the folder where all the files you want to commit exists.
git init
2. To see all the branches in the current repo along with the current branch :
git branch
To create a new branch :
git branch <branch_name>
3. To change branches :
git checkout <branch_name>
If the branch doesn t exist, it can be created by using :
git checkout -b <branch_name>
4. To see the status of the files, ie. if there are uncommitted changes, files to save etc.. use :
git status
5. To stage the changes in the directory for the next commit, use :
git add <filename>
To stage all files in a directory
git add .
6. To commit the staged changes in the directory, use :
git commit -m "<commit_message>"
7. To create a new connection to a remote repo, especially to push existing code to a Github repo :
git remote add <connection_name> <connection_url>
8. To push the code into the remote repo
git push -u <connection_name> <branch_name>
9. To get the contents of a repo
git clone <path>
10. To merge another branch to the current (Example: a side branch to the master)
git merge <branch_name>
For a more detailed list of git commands for easy access check out this nifty cheat sheet. Happy coding!
As some of the world knows full well by now, I've been noodling with Go
for a few years, working through its pros, its cons, and thinking a lot
about how humans use code to express thoughts and ideas. Go's got a lot of
neat use cases, suited to particular problems, and used in the right place,
you can see some clear massive wins.
I've started writing Debian tooling in Go, because it's a pretty natural fit.
Go's fairly tight, and overhead shouldn't be taken up by your operating system.
After a while, I wound up hitting the usual blockers, and started to build up
abstractions. They became pretty darn useful, so, this blog post is announcing
(a still incomplete, year old and perhaps API changing) Debian package for Go.
The Go importable name is pault.ag/go/debian. This contains a lot of utilities
for dealing with Debian packages, and will become an edited down "toolbelt"
for working with or on Debian packages.
Module Overview
Currently, the package contains 4 major sub packages. They're a changelog
parser, a control file parser, deb file format parser, dependency parser
and a version parser. Together, these are a set of powerful building blocks
which can be used together to create higher order systems with reliable
understandings of the world.
changelog
The first (and perhaps most incomplete and least tested) is a changelog file
parser.. This provides the
programmer with the ability to pull out the suite being targeted in the
changelog, when each upload was, and the version for each. For example, let's
look at how we can pull when all the uploads of Docker to sid took place:
funcmain()resp,err:=http.Get("http://metadata.ftp-master.debian.org/changelogs/main/d/docker.io/unstable_changelog")iferr!=nilpanic(err)allEntries,err:=changelog.Parse(resp.Body)iferr!=nilpanic(err)for_,entry:=rangeallEntriesfmt.Printf("Version %s was uploaded on %s\n",entry.Version,entry.When)
The output of which looks like:
Version 1.8.3~ds1-2 was uploaded on 2015-11-04 00:09:02 -0800 -0800
Version 1.8.3~ds1-1 was uploaded on 2015-10-29 19:40:51 -0700 -0700
Version 1.8.2~ds1-2 was uploaded on 2015-10-29 07:23:10 -0700 -0700
Version 1.8.2~ds1-1 was uploaded on 2015-10-28 14:21:00 -0700 -0700
Version 1.7.1~dfsg1-1 was uploaded on 2015-08-26 10:13:48 -0700 -0700
Version 1.6.2~dfsg1-2 was uploaded on 2015-07-01 07:45:19 -0600 -0600
Version 1.6.2~dfsg1-1 was uploaded on 2015-05-21 00:47:43 -0600 -0600
Version 1.6.1+dfsg1-2 was uploaded on 2015-05-10 13:02:54 -0400 EDT
Version 1.6.1+dfsg1-1 was uploaded on 2015-05-08 17:57:10 -0600 -0600
Version 1.6.0+dfsg1-1 was uploaded on 2015-05-05 15:10:49 -0600 -0600
Version 1.6.0+dfsg1-1~exp1 was uploaded on 2015-04-16 18:00:21 -0600 -0600
Version 1.6.0~rc7~dfsg1-1~exp1 was uploaded on 2015-04-15 19:35:46 -0600 -0600
Version 1.6.0~rc4~dfsg1-1 was uploaded on 2015-04-06 17:11:33 -0600 -0600
Version 1.5.0~dfsg1-1 was uploaded on 2015-03-10 22:58:49 -0600 -0600
Version 1.3.3~dfsg1-2 was uploaded on 2015-01-03 00:11:47 -0700 -0700
Version 1.3.3~dfsg1-1 was uploaded on 2014-12-18 21:54:12 -0700 -0700
Version 1.3.2~dfsg1-1 was uploaded on 2014-11-24 19:14:28 -0500 EST
Version 1.3.1~dfsg1-2 was uploaded on 2014-11-07 13:11:34 -0700 -0700
Version 1.3.1~dfsg1-1 was uploaded on 2014-11-03 08:26:29 -0700 -0700
Version 1.3.0~dfsg1-1 was uploaded on 2014-10-17 00:56:07 -0600 -0600
Version 1.2.0~dfsg1-2 was uploaded on 2014-10-09 00:08:11 +0000 +0000
Version 1.2.0~dfsg1-1 was uploaded on 2014-09-13 11:43:17 -0600 -0600
Version 1.0.0~dfsg1-1 was uploaded on 2014-06-13 21:04:53 -0400 EDT
Version 0.11.1~dfsg1-1 was uploaded on 2014-05-09 17:30:45 -0400 EDT
Version 0.9.1~dfsg1-2 was uploaded on 2014-04-08 23:19:08 -0400 EDT
Version 0.9.1~dfsg1-1 was uploaded on 2014-04-03 21:38:30 -0400 EDT
Version 0.9.0+dfsg1-1 was uploaded on 2014-03-11 22:24:31 -0400 EDT
Version 0.8.1+dfsg1-1 was uploaded on 2014-02-25 20:56:31 -0500 EST
Version 0.8.0+dfsg1-2 was uploaded on 2014-02-15 17:51:58 -0500 EST
Version 0.8.0+dfsg1-1 was uploaded on 2014-02-10 20:41:10 -0500 EST
Version 0.7.6+dfsg1-1 was uploaded on 2014-01-22 22:50:47 -0500 EST
Version 0.7.1+dfsg1-1 was uploaded on 2014-01-15 20:22:34 -0500 EST
Version 0.6.7+dfsg1-3 was uploaded on 2014-01-09 20:10:20 -0500 EST
Version 0.6.7+dfsg1-2 was uploaded on 2014-01-08 19:14:02 -0500 EST
Version 0.6.7+dfsg1-1 was uploaded on 2014-01-07 21:06:10 -0500 EST
control
Next is one of the most complex, and one of the oldest parts of go-debian,
which is the control file parser
(otherwise sometimes known as deb822). This module was inspired by the way
that the json module works in Go, allowing for files to be defined in code
with a struct. This tends to be a bit more declarative, but also winds up
putting logic into struct tags, which can be a nasty anti-pattern if used too
much.
The first primitive in this module is the concept of a Paragraph, a struct
containing two values, the order of keys seen, and a map of string to string.
All higher order functions dealing with control files will go through this
type, which is a helpful interchange format to be aware of. All parsing of
meaning from the Control file happens when the Paragraph is unpacked into
a struct using reflection.
The idea behind this strategy that you define your struct, and let the Control
parser handle unpacking the data from the IO into your container, letting you
maintain type safety, since you never have to read and cast, the conversion
will handle this, and return an Unmarshaling error in the event of failure.
Additionally, Structs that define an anonymous member of control.Paragraph
will have the raw Paragraph struct of the underlying file, allowing the
programmer to handle dynamic tags (such as X-Foo), or at least, letting
them survive the round-trip through go.
The default decoder
contains an argument, the ability to verify the input control file using an
OpenPGP keyring, which is exposed to the programmer through the
(*Decoder).Signer() function. If the passed argument is nil, it will not
check the input file signature (at all!), and if it has been passed, any
signed data must be found or an error will fall out of the NewDecoder call.
On the way out, the opposite happens, where the struct is introspected,
turned into a control.Paragraph, and then written out to the io.Writer.
Here's a quick (and VERY dirty) example showing the basics of reading and
writing Debian Control files with go-debian.
packagemainimport("fmt""io""net/http""strings""pault.ag/go/debian/control")typeAllowedPackagestructPackagestringFingerprintstringfunc(a*AllowedPackage)UnmarshalControl(instring)errorin=strings.TrimSpace(in)chunks:=strings.SplitN(in," ",2)iflen(chunks)!=2returnfmt.Errorf("Syntax sucks: '%s'",in)a.Package=chunks[0]a.Fingerprint=chunks[1][1:len(chunks[1])-1]returnniltypeDMUAstructFingerprintstringUidstringAllowedPackages[]AllowedPackage control:"Allow" delim:"," funcmain()resp,err:=http.Get("http://metadata.ftp-master.debian.org/dm.txt")iferr!=nilpanic(err)decoder,err:=control.NewDecoder(resp.Body,nil)iferr!=nilpanic(err)fordmua:=DMUAiferr:=decoder.Decode(&dmua);err!=niliferr==io.EOFbreakpanic(err)fmt.Printf("The DM %s is allowed to upload:\n",dmua.Uid)for_,allowedPackage:=rangedmua.AllowedPackagesfmt.Printf(" %s [granted by %s]\n",allowedPackage.Package,allowedPackage.Fingerprint)
Output (truncated!) looks a bit like:
...
The DM Allison Randal <allison@lohutok.net> is allowed to upload:
parrot [granted by A4F455C3414B10563FCC9244AFA51BD6CDE573CB]
...
The DM Benjamin Barenblat <bbaren@mit.edu> is allowed to upload:
boogie [granted by 3224C4469D7DF8F3D6F41A02BBC756DDBE595F6B]
dafny [granted by 3224C4469D7DF8F3D6F41A02BBC756DDBE595F6B]
transmission-remote-gtk [granted by 3224C4469D7DF8F3D6F41A02BBC756DDBE595F6B]
urweb [granted by 3224C4469D7DF8F3D6F41A02BBC756DDBE595F6B]
...
The DM <aelmahmoudy@sabily.org> is allowed to upload:
covered [granted by 41352A3B4726ACC590940097F0A98A4C4CD6E3D2]
dico [granted by 6ADD5093AC6D1072C9129000B1CCD97290267086]
drawtiming [granted by 41352A3B4726ACC590940097F0A98A4C4CD6E3D2]
fonts-hosny-amiri [granted by BD838A2BAAF9E3408BD9646833BE1A0A8C2ED8FF]
...
...
deb
Next up, we've got the deb module. This contains code to handle reading
Debian 2.0 .deb files. It contains a wrapper that will parse the control
member, and provide the data member through the
archive/tar interface.
Here's an example of how to read a .deb file, access some metadata, and
iterate over the tar archive, and print the filenames of each of the
entries.
dependency
The dependency package provides an interface to parse and compute
dependencies. This package is a bit odd in that, well, there's no other
library that does this. The issue is that there are actually two different
parsers that compute our Dependency lines, one in Perl (as part of dpkg-dev)
and another in C (in dpkg).
To date, this has resulted in me filing
threedifferentbugs.
I also found a broken package in the
archive,
which actually resulted in another bug being (totally accidentally)
already fixed.
I hope to continue to run the archive through my parser in hopes of finding
more bugs! This package is a bit complex, but it basically just returns what
amounts to be an AST
for our Dependency lines. I'm positive there are bugs, so file them!
funcmain()dep,err:=dependency.Parse("foo bar, baz, foobar [amd64] bazfoo [!sparc], fnord:armhf [gnu-linux-sparc]")iferr!=nilpanic(err)anySparc,err:=dependency.ParseArch("sparc")iferr!=nilpanic(err)for_,possi:=rangedep.GetPossibilities(*anySparc)fmt.Printf("%s (%s)\n",possi.Name,possi.Arch)
Gives the output:
foo (<nil>)
baz (<nil>)
fnord (armhf)
version
Right off the bat, I'd like to thank
Michael Stapelberg for letting me graft this
out of dcs and into the go-debian package.
This was nearly entirely his work (with a one or two line function I added
later), and was amazingly helpful to have. Thank you!
This module implements Debian version comparisons and parsing, allowing for
sorting in lists, checking to see if it's native or not, and letting the
programmer to implement smart(er!) logic based on upstream (or Debian)
version numbers.
This module is extremely easy to use and very straightforward, and not worth
writing an example for.
Final thoughts
This is more of a "Yeah, OK, this has been useful enough to me at this point
that I'm going to support this" rather than a "It's stable!" or even
"It's alive!" post. Hopefully folks can report bugs and help iterate on
this module until we have some really clean building blocks to build
solid higher level systems on top of. Being able to have multiple libraries
interoperate by relying on go-debian will be a massive ease.
I'm in need of more documentation, and to finalize some parts of the older
sub package APIs, but I'm hoping to be at a "1.0" real soon now.
The last few months have been a bit of a crazy period of ups and downs, with a
tempest of events beneath the apparent and deceivingly calm surface waters of
being unemployed (still at it).
The daily grind
Chief activities are, of course, those related to the daily grind of
job-hunting, sending applications, and preparing and attending interviews.
It is demoralising when one searches for many days or weeks without seeing
anything suitable for one's skills or interests, or other more general life
expectations. And it takes a lot of time and effort to put one's best in the
applications for positions that one is really, really, interested in. And
even for the ones which are meh, for a variety of reasons (e.g. one is not
very suitable for what the offer demands).
After that, not being invited to interviews (or doing very badly at them) is
bad, of course, but quick and not very painful. A swift, merciful end to the
process.
But it's all the more draining when waiting for many weeks when not a few
months with the uncertainty of not knowing if one is going to be lucky enough
to be summoned for an interview; harbouring some hope one has to appear
enthusiastic in the interviews, after all , while trying to keep it contained
lest it grows too much ; then in the interview hearing good words and some
praises, and feeling the impression that one will fit in, that one did nicely
and that chances are good letting the hope grow again ; start to think about
life changes that the job will require to make a quick decision should the
offer finally arrives ; perhaps make some choices and compromises based on the
uncertain result; then wait for a week or two after the interview to know the
result...
... only to end up being unsuccessful.
All the effort and hopes finally get squashed with a cold, short email or
automatic response, or more often than not, complete radio silence from
prospective employers, as an end to a multi-month-long process. An emotional
roller coaster [1], which
happened to me several times in the last few months.
All in a day's work
The months of preparing and waiting for a new job often imply an impasse that
puts many other things that one cares about on hold, and one makes plans that
will never come to pass.
All in a day's (half-year's?) work of an unemployed poor soul.
But not all is bad.
This period was also a busy time doing some plans about life, mid- and
long-term; the usual and some really unusual! family events; visits to and
from friends, old and new; attending nice little local Debian gatherings or the
bigger gathering of Debian
SunCamp2016, and other
work for side projects or for other events that will happen soon...
And amidst all that, I managed to get some work done on aptitude.
Two pictures worth (less than) a thousand bugs
To be precise, worth 709 bugs 488 bugs in the first graph, plus 221 in the
second.
In 2015-11-15 (link to the post Work on aptitude):
In 2016-06-18:
Numbers
The BTS numbers for aptitude right now are:
221 (259 if counting all merged bugs independently)
1 Release Critical (but it is an artificial bug to keep it from migrating to
testing)
43 (55 unmerged) with severity Important or Normal
160 (182 unmerged) with severity Minor or Wishlist
17 (21 unmerged) marked as Forwarded or Pending
Highlights
Beyond graphs and stats, I am specially happy about two achievements in the last
year:
To have aptitude working today, first and foremost
Apart from the abandon that suffered in previous years, I mean
specifically the critical step of getting it through the troubles of the
last summer, with the GCC-5/C++11 transition in parallel with a
transition of the Boost library (explained in more detail in Work on
aptitude).
Without that, possibly aptitude would not have survived until today.
Improvements to the suggestions of the resolver
In the version 0.8, there were a lot of changes related with improving
the order of the suggestions from the resolver, when it finds conflicts
or other problems with the planned actions.
Historically, but specially in the last few years, there have been many
complaints about the nonsensical or dangerous suggestions from the
resolver. The first solution offered by the resolver was very often
regarded as highly undesirable (for example, removal of many packages),
and preferable solutions like upgrades of one or only a handful of
packages being offered only after many removals; and keeps only
offered as last resort.
Perhaps these changes don't get a lot of attention, given that in the first case
it's just to keep working (with few people realising that it could have
collapsed on the spot, if left unattended), and the second can probably go
unnoticed because it just works or it started to work more smoothly
doesn't get as much immediate attention as it suddenly broke! .
Still, I wanted to mention them, because I am quite proud of those.
Thanks
Even if I put a lot of work on aptitude in the last year, the results of the
graph and numbers have not been solely achieved by me.
Special thanks go to Axel Beckert (abe /
XTaran) and the apt team, David
Kalnischkies and Julian Andres Klode who, despite the claim in that page, does
not mostly work python-aptanymore... but also in the main tools.
They help with fixing some of the issues directly, or changing things in apt
that benefit aptitude, testing changes, triaging bugs or commenting on them,
patiently explaining to me why something in libapt doesn't do what I think it
does, and good company in general.
Not the least, for holding impromptu BTS group therapy / support meetings, for
those cases when prolonged exposure to BTS activity starts to induce very bad
feelings.
Thanks also to people who sent their translation updates, notified about
corrections, sent or tested patches, submitted bugs, or tried to help in other
ways. Change logs for details.
Notes
[1] ^ It's even an example in
the Cambridge Dictionaries Online website, for the entry of roller
coaster:
He was on an emotional roller coaster for a while when he lost his job.
Sursamen is an Arithmetic, Mottled, Disputed, Multiply Inhabited,
Multi-million Year Safe, and Godded Shellworld. It's a constructed world
with multiple inhabitable levels, each lit by thermonuclear "suns" on
tracks, each level supported above the last by giant pillars. Before the
recorded history of the current Involved Species, a culture called the
Veil created the shellworlds with still-obscure technology for some
unknown purpose, and then disappeared. Now, they're inhabited by various
transplants and watched over by a hierarchy of mentor and client species.
In the case of Sursamen, both the Aultridia and the Oct claim jurisdiction
(hence "Disputed"), and are forced into an uneasy truce by the Nariscene,
a more sophisticated species that oversees them both.
On Sursamen, on level eight to be precise, are the Sarl, a culture with an
early industrial level of technology in the middle of a war of conquest to
unite their level (and, they hope, the next level down). Their mentors
are the Oct, who claim descendance from the mysterious Veil. The Deldeyn,
the next level down, are mentored by the Aultridia, a species that evolved
from a parasite on Xinthian Tensile Aranothaurs. Since a Xinthian,
treated by the Sarl as a god, lives in the heart of Sursamen (hence
"Godded"), tensions between the Sarl and the Aultridians run
understandably high.
The ruler of the Sarl had three sons and a daughter. The oldest was
killed by the people he is conquering as Matter starts. The middle
son is a womanizer and a fop who, as the book opens, watches a betrayal
that he's entirely unprepared to deal with. The youngest is a thoughtful,
bookish youth pressed into a position that he also is not well-prepared
for.
His daughter left the Sarl, and Sursamen itself, fifteen years previously.
Now, she's a Special Circumstances agent for the Culture.
Matter is the eighth Culture novel, although (like most of the
series) there's little need to read the books in any particular order.
The introduction to the Culture here is a bit scanty, so you'll have more
background and understanding if you've read the previous novels, but it
doesn't matter a great deal for the story.
Sharp differences in technology levels have turned up in previous Culture
novels (although the most notable example is a minor spoiler), but this is
the first Culture novel I recall where those technological differences
were given a structure. Usually, Culture novels have Special
Circumstances meddling in, from their perspective, "inferior" cultures.
But Sursamen is not in Culture space or directly the Culture's business.
The Involved Species that governs Sursamen space is the Morthanveld: an
aquatic species roughly on a technology level with the Culture themselves.
The Nariscene are their client species; the Oct and Aultridia are, in
turn, client species (well, mostly) of the Nariscene, while meddling with
the Sarl and Deldeyn.
That part of this book reminded me of Brin's Uplift universe. Banks's
Involved Species aren't the obnoxious tyrants of Brin's universe, and
mentoring doesn't involve the slavery of the Uplift universe. But some of
the politics are a bit similar. And, as with Uplift, all the characters
are aware, at least vaguely, of the larger shape of galactic politics.
Even the Sarl, who themselves have no more than early industrial
technology. When Ferbin flees the betrayal to try to get help, he ascends
out of the shellworld to try to get assistance from an Involved species,
or perhaps his sister (which turns out to be the same thing). Banks
spends some time here, mostly through Ferbin and his servant (who is one
of the better characters in this book), trying to imagine what it would be
like to live in a society that just invented railroads while being aware
of interstellar powers that can do practically anything.
The plot, like the world on which it's set, proceeds on multiple levels.
There is court intrigue within the Sarl, war on their level and the level
below, and Ferbin's search for support and then justice. But the Sarl
live in an artifact with some very mysterious places, including the best
set piece in the book: an enormous waterfall that's gradually uncovering a
lost city on the level below the Sarl, and an archaeological dig that
proceeds under the Deldeyn and Sarl alike. Djan Seriy decides to return
home when she learns of events in Sarl, originally for reasons of family
loyalty and obligation, but she's a bit more in touch with the broader
affairs of the galaxy, including the fact that the Oct are acting very
strangely. There's something much greater at stake on Sursamen than
tedious infighting between non-Involved cultures.
As always with Banks, the set pieces and world building are amazing, the
scenery is jaw-dropping, and I have some trouble warming to the
characters. Dramatic flights across tower-studded landscapes seeking
access to forbidden world-spanning towers largely, but don't entirely,
make up for not caring about most of the characters for most of the book.
This did change, though: although I never particularly warmed to Ferbin, I
started to like his younger brother, and I really liked his sister and his
servant by the end of the book.
Unfortunately, the end of Matter is, if not awful, at least
exceedingly abrupt. As is typical of Banks, we get a lot of sense of
wonder but not much actual explanation, and the denouement is essentially
nonexistent. (There is a coy epilogue hiding after the appendices, but it
mostly annoyed me and provides only material for extrapolation about the
characters.) Another SF author would have written a book about the
Xinthian, the Veil, the purpose of the shellworlds, and the deep history
of the galaxy. I should have known going in that Banks isn't that sort of
SF author, but it was still frustrating.
Still, Banks is an excellent writer and this is a meaty, complex,
enjoyable story with some amazing moments of wonder and awe. If you like
Culture novels in general, you will like this. If you like
set-piece-heavy SF on a grand scale, such as Alastair Reynolds or Kim
Stanley Robinson, you probably like this. Recommended.
Rating: 8 out of 10
Allison Lortie has provoked a lot of comment with her blog post on
a new proposal for how GTK is versioned.
Here's some more context from the discussion at the GTK hackfest that
prompted that proposal: there's actually quite a close analogy in
how new Debian versions are developed.
The problem we're trying to address here is the two sides of a trade-off:
Without new development, a library (or an OS) can't go anywhere new
New development sometimes breaks existing applications
Historically, GTK has aimed to keep compatible within a major version,
where major versions are rather far apart (GTK 1 in 1998, GTK 2 in
2002, GTK 3 in 2011, GTK 4 somewhere in the future). Meanwhile, fixing
bugs, improving performance and introducing new features sometimes
results in major changes behind the scenes. In an ideal world, these
behind-the-scenes changes would never break applications; however, the
world isn't ideal. (The Debian analogy here is that as much as we
aspire to having the upgrade from one stable release to the next not break
anything at all, I don't think we've ever achieved that in practice -
we still ask users to read the release notes, even though ideally
that wouldn't be necessary.)
In particular, the perceived cost of doing a proper ABI break (a fully
parallel-installable GTK 4) means there's a strong temptation to make
changes that don't actually remove or change C symbols, but are clearly
an ABI break, in the sense that an application that previously worked
and was considered correct no longer works. A prominent recent example is
the theming changes in GTK 3.20: the ABI in terms of functions available
didn't change, but what happens when you call those functions changed in
an incompatible way. This makes GTK hard to rely on for applications
outside the GNOME release cycle, which is a problem that needs to
be fixed (without stopping development from continuing).
The goal of
the plan we discussed today
is to decouple the latest branch of development, which moves fast and
sometimes breaks API, from the API-stable branches, which only get bug
fixes. This model should look quite familiar to Debian contributors,
because it's a lot like the way we release Debian and Ubuntu.
In Debian, at any given time we have a development branch
(testing/unstable) - currently "stretch", the future Debian 9. We
also have some stable branches, of which the most recent are Debian
8 "jessie" and Debian 7 "wheezy". Different users of Debian have
different trade-offs that lead them to choose one or the other of
these. Users who value stability and want to avoid unexpected changes,
even at a cost in terms of features and fixes for non-critical bugs,
choose to use a stable release, preferably the most recent; they only
need to change what they run on top of Debian for OS API changes (for
instance webapps, local scripts, or the way they interact with the GUI)
approximately every 2 years, or perhaps less often than that with the
Debian-LTS project supporting non-current stable releases. Meanwhile,
users who value the latest versions and are willing to work with a
"moving target" as a result choose to use testing/unstable.
The GTK analogy here is really quite close. In the new versioning model,
library users who value stability over new things would prefer to use
a stable-branch, ideally the latest; library users who want the latest
features, the latest bug-fixes and the latest new bugs would use the
branch that's the current focus of development. In practice we expect
that the latter would be mostly GNOME projects. There's been some
discussion at the hackfest about how often we'd have a new
stable-branch: the fastest rate that's been considered is a stable-branch
every 2 years, similar to Ubuntu LTS and Debian, but there's no consensus
yet on whether they will be that frequent in practice.
How many stable versions of GTK would end up shipped in Debian depends
on how rapidly projects move from "old-stable" to "new-stable" upstream,
how much those projects' Debian maintainers are willing to patch them
to move between branches, and how many versions the release team will
tolerate. Once we reach a steady state, I'd hope that we might have
1 or 2 stable-branched versions active at a time, packaged as separate
parallel-installable source packages (a lot like how we handle Qt).
GTK 2 might well stay around as an additional active version just
from historical inertia. The stable versions are intended to be
fully parallel-installable, just like the situation with GTK 1.2,
GTK 2 and GTK 3 or with the major versions of Qt.
For the "current development" version, I'd anticipate that we'd probably
only ship one source package, and do ABI transitions for one version
active at a time, a lot like how we deal with libgnome-desktop and the
evolution-data-server family of libraries. Those versions would have
parallel-installable runtime libraries but non-parallel-installable
development files, again similar to libgnome-desktop.
At the risk of stretching the Debian/Ubuntu analogy too far, the
intermediate "current development" GTK releases that would accompany
a GNOME release are like Ubuntu's non-LTS suites: they're more up to
date than the fully stable releases (Ubuntu LTS, which has a release
schedule similar to Debian stable), but less stable and not supported
for as long.
Hopefully this plan can meet both of its goals: minimize breakage for
applications, while not holding back the development of new APIs.
This is report on my previous week activities with Debian Reproducible-Builds.
In last 10 days, I had build different Debain packages at my own using prebuilder to experience the reproducibility issues.
I am thankful to deki and Lunar for suggesting me to do that task. Based on this experience, I managed to find more use cases for hide=profiles specification.
I also researched differences of different unreproducible Debian packages on http://tests.reproducible-builds.org . There are many packages available for examination.
In brief I did following tasks:
Read documentation on argcomplete python module and had some hands on experience with module. Purpose of doing this was to add argument completion feature to Diffoscope. pabs had filed bug report for this #826711. I am implementing this feature and discussing issues with pabs as well as researching diffs side-by-side to generate more use cases. Here, Thanks to pabs for guidance and support :)
I went through different software to see how they are ignoring the stuff. Those are following:
Upcoming week will be an important as well as fun week because I will be implementing the use cases. Right now, I am currently looking at different softwares which ignores stuff and taking notes of it. So that, it will help me during implementing solution of use cases.
I am also looking forward to feedback from community on use cases and CLI interfaces.
Have a great week :)
After introducing ourselves to the community, we start contributing to the open and free source software. Since this is the first week, I have went through theories which would help me in coding. Before coding it is always safer to refer to theories so that we don t need to spare time in debugging.
The following were my week 1-4 plans:
Getting familiar with Python and coding for connecting to an email account (using IMAP) and examines every message in every folder.
Writing a basic Python script to look at the To , From and CC headers of every email message in the folder. Identifying all the names and email addresses and writing them in a CSV file.
Scanning the body of each message looking for phone numbers.(for messages in plain text format)
Cleaning up the phone numbers and write them in international format and putting those in the CSV file too.(Telify recognizes phone numbers on web pages or in email messages and converts them into clickable links. This works with many CTI applications, SIP clients, Skype, Netmeeting, snom phones, the AGFEO TK-Suite client, SerVonic IXI-PCS and others. In general, all telephony software, devices or interfaces which can be controlled by using a URL, will most likely enable you to call a phone number directly from your browser or email client.
These two weeks I have completed my first two tasks in the list.I have committed and pushed my works in GitHub.https://github.com/Jaminy/GSoC
Successfully logged into the email account using IMAP and examined each folders.Examined inbox to extract To , From and CC of the last message received.Trying to extract all message details to put in CSV file.
Historically, the adt-run command line has allowed multiple tests; as a consequence, arguments like --binary or --override-control were position dependent, which confused users a lot (#795274, #785068, #795274, LP #1453509). On the other hand I don t know anyone or any CI system which actually makes use of the multiple tests on a single command line feature.
The command line also was a bit confusing in other ways, like the explicit --built-tree vs. --unbuilt-tree and the magic / vs. // suffixes, or option vs. positional arguments to specify tests.
The other long-standing confusion is the pervasive adt acronym, which is still from the very early times when autopkgtest was called autodebtest (this was changed one month after autodebtest s inception, in 2006!).
Thus in some recent night/weekend hack sessions I ve worked on a new command line interface and consistent naming. This is now available in autopkgtest 4.0 in Debian unstable and Ubuntu Yakkety. You can download and use the deb package on Debian jessie and Ubuntu 14.04 LTS as well. (I will provide official backports after the first bug fix release after this got some field testing.)
New autopkgtest command
The adt-run program is now superseded by autopkgtest:
It accepts only exactly one tested source package, and gives a proper error if none or more than one (often unintend) is given. Binaries to be tested, --override-control, etc. can now be specified in any order, making the arguments position independent. So you now can do things like:
autopkgtest *.dsc *.deb [...]
Before, *.deb only applied to the following test.
The explicit --source, --click-source etc. options are gone, the type of tested source/binary packages, including built vs. unbuilt tree, is detected automatically. Tests are now only specified with positional arguments, without the need (or possibility) to explicitly specify their type. The one exception is --installed-click com.example.myapp as possible names are the same as for apt source package names.
The virtualization server is now separated with a double instead of a tripe dash, as the former is standard Unix syntax.
It defaults to the current directory if that is a Debian source package. This makes the command line particularly simple for the common case of wanting to run tests in the package you are just changing:
autopkgtest -- schroot sid
Assuming the current directory is an unbuilt Debian package, this will build the package, and run the tests in ./debian/tests against the built binaries.
The virtualization server must be specified with its short name only, e. g. ssh instead of adt-virt-ssh . They also don t get installed into $PATH any more, as it s hardly useful to call them directly.
README.running-tests got updated to the new CLI, as usual you can also read the HTML online.
The old adt-run CLI is still available with unchanged behaviour, so it is safe to upgrade existing CI systems to that version.
Image build tools
All adt-build* tools got renamed to autopkgtest-build*, and got changed to build images prefixed with autopkgtest instead of adt . For example, adt-build-lxc ubuntu xenial now produces an autopkgtest-xenial container instead of adt-xenial.
In order to not break existing CI systems, the new autopkgtest package contains symlinks to the old adt-build* commands, and when being called through them, also produce images with the old adt- prefix.
Environment variables in tests
Finally there is a set of environment variables that are exported by autopkgtest for using in tests and image customization tools, which now got renamed from ADT_* to AUTOPKGTEST_*:
AUTOPKGTEST_APT_PROXY
AUTOPKGTEST_ARTIFACTS
AUTOPKGTEST_AUTOPILOT_MODULE
AUTOPKGTEST_NORMAL_USER
AUTOPKGTEST_REBOOT_MARK
AUTOPKGTEST_TMP
As these are being used in existing tests and tools, autopkgtest also exports/checks those under their old ADT_* name. So tests can be converted gradually over time (this might take several years).
Feedback
As usual, if you find a bug or have a suggestion how to improve the CLI, please file a bug in Debian or in Launchpad. The new CLI is recent enough that we still have some liberty to change it.
Happy testing!
When using ansible to configure systems and services, templates can reach a significant complexity. Proper indenting can help to improve the readability of the templates, which is very important for further maintenance.
Unfortunately the default settings for the jinja2 template engine in ansible do enable trim_blocks only, while a combination with lstrip_blocks would be better. But here comes the good news:
It s possible to enable that setting on a per-template base. The secret is to add a special comment to the very first line of a template:
#jinja2: lstrip_blocks: True
This setting does the following: If enabled, leading spaces and tabs are stripped from the start of a line to a block .
So a resulting template could look like this:
global
% for setting in global_settings %
% if setting ... %
option setting
% endif %
% endfor %
Unfortunately (or fortunately, if you want to see it this way this does not strip leading spaces and tabs where the indentation is followed by pure text, e.g. the whitespaces in line 4 are preserved. So as a matter of fact, if you care for the indentation in the resulting target file, you need to indent those lines according to the indentation wanted in the target file instead, like it is done in the example.
In less simple cases, with more deep nesting, this may seem odd, but hey: it s the best compromise between a good, readable template and a consistently indented output file.
I'll tune in to the post-based conversation being held on Planet Debian: Russell Coker wonders about what's needed to get university graduates with enough skills for a sysadmin job, to which Lucas Nussbaum responds with his viewpoints. They present a very contrasting view of what's needed for students And for a good reason, I'd say: Lucas is an academician; I don't know for sure about Russell, but he seems to be a down-to-the-earth, dirty-handed, proficient sysadmin working on the field. They both contact newcomers to their fields, and will notice different shortcomings.
I tend to side with Lucas' view. That does not come as a surprise, as I've been working for over 15 years in an university, and in the last few years I started walking from a mostly-operative sysadmin in an academic setting towards becoming an academician that spends most of his time sysadmining. Subtle but important distinction.
I teach at the BSc level at UNAM, and am a Masters student at IPN (respectively, Mexico's largest and second-largest universities). And yes, the lack of sysadmin abilities in both is surprising. But so is a good understanding of programming. And I'm sure that, were I to dig into several different fields, I'd feel the same: Student formation is very basic at each of those fields.
But I see that as natural. Of course, if I were to judge people as geneticists as they graduate from Biology, or were I to judge them as topologists as they graduate from Mathematics, or any other discipline in which I'm not an expert, I'd surely not know where to start Given I have about 20 years of professional life on my shoulders, I'm quite skewed as to what is basic for a computing professional. And of course, there are severe holes in my formation, in areas I never used. I know next to nothing of electronics, my mathematical basis is quite flaky, and I'm a poor excuse when talking about artificial intelligence.
Where am I going with this? An university degree (BSc in English, would amount to "licenciatura" in Spanish) is not for specialization. It is to have a sufficiently broad panorama of the field, and all of the needed tools to start digging deeper and specializing either by yourself, working on a given field and learning its details as you go, or going through a postgraduate program (Specialization, Masters, Doctorate).
Even most of my colleagues at the Masters in Engineering in Security and Information Technology lack of a good formation in fields I consider essential. However, what does information security mean? Many among them are working on legal implications of several laws that touch our field. Many other are working on authenticity issues in images, audios and other such media. Many other are trying to come up with mathematical ways to cheapen the enormous burden of crypto operations (say, "shaving" CPU cycles off a very large exponentiation). Others are designing autonomous learning mechanisms to characterize malware. Were I as a computing professional to start talking about their research, I'd surely reveal I know nothing about it and get laughed at. That's because I haven't specialized in those fields.
University education should give a broad universal basis to enter a professional field. It should not focus on teaching tools or specific procedures (although some should surely be presented as examples or case studies). Although I'd surely be happy if my university's graduates were to know everything about administering a Debian system, that would be wrong for a university to aim at; I'd criticize it the same way I currently criticize programs that mix together university formation and industry certification as if they were related.
Welcome in my first and second report!
The community was really good, I talked with a lot of people from all around the world. All that projects are just awesome and I am happy to be part of this.
For this first week, I provided a list of all information I need to pull in my client (this list is subject to change a little bit):
-Call ID
-Resolution of the camera of all the people connect to the call
-Percentage of loosing frame
-Bandwidth (upload + download)
-Name of Codecs using on the conversation
-Time to contact the other person
-The security level
-Performance using by Ring (RAM + CPU)
I am trying to figure out how work the Ring project.
-Understand the external exchange by using Wireshark to catch some important packages.
-Understand the internal exchange between the daemon and clients on the D-Bus by using Bustle
I created my architecture program on the daemon and the D-Bus. [1] You can call the method launchSmartInfo(int x) from the D-Bus (by using D-Feet for example). That will call SmartInfo signal all x ms. This signal can only push an int for the moment, but he will push all the information we want on the clients.
I actually work on the Ring GNU Linux client. So I learn how work the QT and GTK+.
[1]github/Gasuleg/Smartlnfo-Ring: I will stop update this repository because I will push my code on the Gerrit draft of Savoir Faire Linux. It's more easy for my team to do some commentary on that platform and it's free software)
Welcome in my first and second report!
The community was really good, I talked with a lot of people from all around the world. All that projects are just awesome and I am happy to be part of this.
For this first week, I provided a list of all information I need to pull in my client (this list is subject to change a little bit):
-Call ID
-Resolution of the camera of all the people connect to the call
-Percentage of loosing frame
-Bandwidth (upload + download)
-Name of Codecs using on the conversation
-Time to contact the other person
-The security level
-Performance using by Ring (RAM + CPU)
I am trying to figure out how work the Ring project.
-Understand the external exchange by using Wireshark to catch some important packages.
-Understand the internal exchange between the daemon and clients on the D-Bus by using Bustle
I created my architecture program on the daemon and the D-Bus. [1] You can call the method launchSmartInfo(int x) from the D-Bus (by using D-Feet for example). That will call SmartInfo signal all x ms. This signal can only push an int for the moment, but he will push all the information we want on the clients.
I actually work on the Ring GNU Linux client. So I learn how work the QT and GTK+.
[1][https://github.com/Gasuleg/Smartlnfo-Ring](https://github.com/Gasuleg/Smartlnfo-Ring)(I will stop update this repository because I will push my code on the Gerrit draft of Savoir Faire Linux. It's more easy for my team to do some commentary on that platform and it's free software)
git-annex has been around for a long time, but I just recently stumbled across some of the work Joey has been doing to it. This post isn t about it s traditional roots in git or all the features it has for partial copies of large data sets, but rather for its live syncing capabilities like Dropbox. It takes a bit to wrap your head around, because git-annex is just a little different from everything else. It s sort of like a different-colored smell.
The git-annex wiki has a lot of great information both low-level reference and a high-level 10-minute screencast showing how easy it is to set up. I found I had to sort of piece together the architecture between those levels, so I m writing this all down hoping it will benefit others that are curious.
Ir you just want to use it, you don t need to know all this. But I like to understand how my tools work.
Overview
git-annex lets you set up a live syncing solution that requires no central provider at all, or can be used with a completely untrusted central provider. Depending on your usage pattern, this central provider could require only a few MBs of space even for repositories containing gigabytes or terabytes of data that is kept in sync.
Let s take a look at the high-level architecture of the tool. Then I ll illustrate how it works with some scenarios.
Three Layers
Fundamentally, git-annex takes layers that are all combined in Dropbox and separates them out. There is the storage layer, which stores the literal data bytes that you are interested in. git-annex indexes the data in storage by a hash. There is metadata, which is for things like a filename-to-hash mapping and revision history. And then there is an optional layer, which is live signaling used to drive the real-time syncing.
git-annex has several modes of operation, and the one that enables live syncing is called the git-annex assistant. It runs as a daemon, and is available for Linux/POSIX platforms, Windows, Mac, and Android. I ll be covering it here.
The storage layer
The storage layer simply is blobs of data. These blobs are indexed by a hash, and can be optionally encrypted at rest at remote backends. git-annex has a large number of storage backends; some examples include rsync, a remote machine with git-annex on it that has ssh installed, WebDAV, S3, Amazon Glacier, removable USB drive, etc. There s a huge list.
One of the git-annex features is that each client knows the state of each storage repository, as well as the capability set of each storage repository. So let s say you have a workstation at home and a laptop you take with you to work or the coffee shop. You d like changes on one to be instantly recognized on another. With something like Dropbox or OwnCloud, every file in the set you want synchronized has to reside on a server in the cloud. With git-annex, it can be configured such that the server in the cloud only contains a copy of a file until every client has synced it up, at which point it gets removed. Think about it that is often what you want anyhow, so why maintain an unnecessary copy after it s synced everywhere? (This behavior is, of course, configurable.) git-annex can also avoid storing in the cloud entirely if the machines are able to reach each other directly at least some of the time.
The metadata layer
Metadata about your files includes a mapping from the file names to the storage location (based on hashes), change history, and information about the status of each machine that participates in the syncing. On your clients, git-annex stores this using git. This detail is very useful to some, and irrelevant to others.
Some of the git-annex storage backends can support only storage (S3, for instance). Some can support both storage and metadata (rsync, ssh, local drives, etc.) You can even configure a backend to support only metadata (more on why that may be useful in a bit). When you are working with a git-backed repository for git-annex, it can hold data, metadata, or both.
So, to have a working sync system, you must have a way to transport both the data and the metadata. The transport for the metadata is generally rsync or git, but it can also be XMPP in which Git changesets are basically wrapped up in XMPP presence messages. Joey says, however, that there are some known issues with XMPP servers sometimes dropping or reordering some XMPP messages, so he doesn t encourage that method currently.
The live signaling layer
So once you have your data and metadata, you can already do syncs via git annex sync --contents. But the real killer feature here will be automatic detection of changes, both on the local and the remote. To do that, you need some way of live signaling. git-annex supports two methods.
The first requires ssh access to a remote machine where git-annex is installed. In this mode of operation, when the git-annex assistant fires up, it opens up a persistent ssh connection to the remote and runs the git-annex-shell over there, which notifies it of changes to the git metadata repository. When a change is detected, a sync is initiated. This is considered ideal.
A substitute can be XMPP, and git-annex actually converts git commits into a form that can be sent over XMPP. As I mentioned above, there are some known reliability issues with this and it is not the recommended option.
Encryption
When it comes to encryption, you generally are concerned about all three layers. In an ideal scenario, the encryption and decryption happens entirely on the client side, so no service provider ever has any details about your data.
The live signaling layer is encrypted pretty trivially; the ssh sessions are, of course, encrypted and TLS support in XMPP is pervasive these days. However, this is not end-to-end encryption; those messages are decrypted by the service provider, so a service provider could theoretically spy on metadata, which may include change times and filenames, though not the contents of files themselves.
The data layer also can be encrypted very trivially. In the case of the dumb backends like S3, git-annex can use symmetric encryption or a gpg keypair and all that ever shows up on the server are arbitrarily-named buckets.
You can also use a gcrypt-based git repository. This can cover both data and metadata and, if the target also has git-annex installed, the live signalling layer. Using a gcrypt-based git repository for the metadata and live signalling is the only way to accomplish live syncing with 100% client-side encryption.
All of these methods are implemented in terms of gpg, and can support symmetric of public-key encryption.
It should be noted here that the current release versions of git-annex need a one-character patch in order to fix live syncing with a remote using gcrypt. For those of you running jessie, I recommend the version in jessie-backports, which is presently 5.20151208. For your convenience, I have compiled an amd64 binary that can drop in over /usr/bin/git-annex if you have this version. You can download it and a gpg signature for it. Note that you only need this binary on the clients; the server can use the version from jessie-backports without issue.
Putting the pieces together: some scenarios
Now that I ve explained the layers, let s look at how they fit together.
Scenario 1: Central server
In this scenario, you might have a workstation and a laptop that sync up with each other by way of a central server that also has a full copy of the data. This is the scenario that most closely resembles Dropbox, box, or OwnCloud.
Here you would basically follow the steps in the git-assistant screencast: install git-annex on a server somewhere, and point your clients to it. If you want full end-to-end encryption, I would recommend letting git-annex generate a gpg keypair for you, which you would then need to copy to both your laptop and workstation (but not the server).
Every change you make locally will be synced to the server, and then from the server to your other PC. All three systems would be configured in the client transfer group.
Scenario 1a: Central server without a full copy of the data
In this scenario, everything is configured the same except the central server is configured with the transfer transfer group. This means that the actual data synced to it is deleted after it has been propagated to all clients. Since git-annex can verify which repository has received a copy of which data, it can easily enough delete the actual file content from the central server after it has been copied to all the clients. Many people use something like Dropbox or OwnCloud as a multi-PC syncing solution anyhow, so once the files have been synced everywhere, it makes sense to remove them from the central server.
This is often a good ideal for people. There are some obvious downsides that are sometimes relevant. For instance, to add a third sync client, it must be able to initially copy down from one of the existing clients. Or, if you intend to access the data from a device such as a cell phone where you don t intend for it to have a copy of all data all the time, you won t have as convenient way to download your data.
Scenario 1b: Split data/metadata central servers
Imagine that you have a shell or rsync account on some remote system where you can run git-annex, but don t have much storage space. Maybe you have a cheap VPS or shell account somewhere, but it s just not big enough to hold your data.
The answer to this would be to use this shell or rsync account for the metadata, but put the data elsewhere. You could, for instance, store the data in Amazon S3 or Amazon Glacier. These backends aren t capable of storing the git-annex metadata, so all you need is a shell or rsync account somewhere to sync up the metadata. (Or, as below, you might even combine a fully distributed approach with this.) Then you can have your encrypted data pushed up to S3 or some such service, which presumably will grow to whatever size you need.
Scenario 2: Fully distributed
Like git itself, git-annex does not actually need a central server at all. If your different clients can reach each other directly at least some of the time, that is good enough. Of course, a given client will not be able to do fully automatic live sync unless it can reach at least one other client, so changes may not propagate as quickly.
You can simply set this up by making ssh connections available between your clients. git-annex assistant can automatically generate appropriate ~/.ssh/authorized_keys entries for you.
Scenario 2a: Fully distributed with multiple disconnected branches
You can even have a graph of connections available. For instance, you might have a couple machines at home and a couple machines at work with no ability to have a direct connection between them (due to, say, firewalls). The two machines at home could sync with each other in real-time, as could the two machines at work. git-annex also supports things like USB drives as a transport mechanism, so you could throw a USB drive in your pocket each morning, pop it in to one client at work, and poof both clients are synced up over there. Repeat when you get home in the evening, and you re synced there. The USB drive s repository can, of course, be of the transport type so data is automatically deleted from it once it s been synced everywhere.
Scenario 3: Hybrid
git-annex can support LAN sync even if you have a central server. If your laptop, say, travels around but is sometimes on the same LAN as your PC, git-annex can easily sync directly between the two when they are reachable, saving a round-trip to the server. You can assign a cost to each remote, and git-annex will always try to sync first to the lowest-cost path that is available.
Drawbacks of git-annex
There are some scenarios where git-annex with the assistant won t be as useful as one of the more traditional instant-sync systems.
The first and most obvious one is if you want to access the files without the git-annex client. For instance, many of the other tools let you generate a URL that you can email to people, and then they can download files without any special client software. This is not directly possible with git-annex. You could, of course, make something like a public_html directory be managed with git-annex, but it wouldn t provide things like obfuscated URLs, password-protected sharing, time-limited sharing, etc. that you get with other systems. While you can share your repositories with others that have git-annex, you can t share individual subdirectories; for a given repository, it is all or nothing.
The Android client for git-annex is a pretty interesting thing: it is mostly a small POSIX environment, providing a terminal, git, gpg, and the same web interface that you get on a standalone machine. This means that the git-annex Android client is fully functional compared to a desktop one. It also has a quick setup process for syncing off your photos/videos. On the other hand, the integration with the Android ecosystem is poor compared to most other tools.
Other git-annex features
git-annex has a lot to offer besides the git-annex assistant. Besides the things I ve already mentioned, any given git-annex repository including your client repository can have a partial copy of the full content. Say, for instance, that you set up a git-annex repository for your music collection, which is quite large. You want some music on your netbook, but don t have room for it all. You can tell git-annex to get or drop files from the netbook s repository without deleting them remotely. git-annex has quite a few ways to automate and configure this, including making sure that at least a certain number of copies of a file exist in your git-annex ecosystem.
Conclusion
I initially started looking at git-annex due to the security issues with encfs, and the difficulty with setting up ecryptfs in this way. (I had been layering encfs atop OwnCloud). git-annex certainly ticks the box for me security-wise, and obviously anything encrypted with encfs wasn t going to be shared with others anyhow. I ll be using git-annex more in the future, I m sure.