Hacker News new | comments | show | ask | jobs | submit login
Apt: please make the moo reproducible (debian.org)
236 points by teddyh on Dec 31, 2016 | hide | past | web | favorite | 59 comments



Took me a while (after reading through the reply, to no avail) to figure out what this refers to. Here's the feature this is referring to:

     $ apt-get moo
                     (__) 
                     (oo) 
               /------\/ 
              / |    ||   
             *  /\---/\ 
                ~~   ~~   
    ..."Have you mooed today?"...
Edit: maybe not actually! Just found this too:

    $ aptitude moo
    There are no Easter Eggs in this program.
    $ aptitude -v moo
    There really are no Easter Eggs in this program.


This is “documented” as well. apt-get has got Super Cow Powers and aptitude has not.

    $ apt-get
    apt 1.0.9.8.4 for amd64 compiled on Dec 11 2016 09:48:19
    Usage: apt-get [options] command
           apt-get [options] install|remove pkg1 [pkg2 ...]
           apt-get [options] source pkg1 [pkg2 ...]
    …
                                            This APT has Super Cow Powers.

    $ aptitude --help
    aptitude 0.6.11
    Usage: aptitude [-S fname] [-u|-i]
           aptitude [options] <action> ...

    …

                      This aptitude does not have Super Cow Powers.


I don't really understand what in this feature makes the build non-reproducible. Judging by the patch it's the call to time(NULL) that seems to be problematic, but I don't understand why.


The output of "apt-get moo" changes on special days (4/1, 12/25, 8/16, 11/7, 2/18). So if another program was using "apt-get moo" in its build script, the build would not be reproducible. With the patch, the SOURCE_DATE_EPOCH environment variable can be set to make "apt-get moo" deterministic.

I don't think anything actually uses "apt-get moo" in its build script.

This kind of patch makes more sense for build tools like "ar" (static library creator). By default, "ar" injects a timestamp into the output file, so the binary is different each build. But, use the "D" flag and "ar" becomes deterministic.


The time-dependent part can be seen here: https://github.com/Debian/apt/blob/master/apt-private/privat...



Yeh I only skimmed the patch but I presumed "reproducable build" referred to the actual binary, and the patch addresses runtime behaviour. Guess I'm missing something.


It doesn't; it makes anyone using the output...


From what I can read in patch file, it seems to be doing something different on April fools day.


Keep adding more v.


Yep it gets good - wasn't sure whether to spoil the fun or not :)


> I got a fever! And the only prescription.. is more -v!


try

  $ apt-get moo moo
  $ apt-get moo moo moo


Try `aptitude -vv moo` :)


Thanks. A nice New Year's gift, to learn Super Cow Powers. Though talking about more -v's, I don't think Aptitude is written in Python, is it?


I recall that aptitude has more messages for more v's.


This is a patch for apt, it does not have anything to do with aptitude.


Hilarious, yes. Except this: "The followers advice is dropping the curly brackets for these one-line ifs to make them all happy."

Did I just read a code review advocating for #gotofail, just to avoid a minor formatting nitpick?


Python has #gotofail built-in, and it's considered by fans to be an awesome feature of the language!


That's not a bug, that's a feature! :D


I thought it was a (pretty funny) joke.


It's also the Linux kernel style.


Popularity doesn't make a bad idea any better.


Sure, but you know what does make this idea better?

The fact that it's pretty much the most sane way to consistently handle errors in a complicated C program. In particular if you have multiple paths out of your function and it also makes memory allocations, that's an overcomplicated amount of free() calls you need to take care of, remember are there, and maintain as you add/remove allocations and failure paths. goto lets you keep it simple by only maintaining a single block of free()s at your function's single exit path.

Granted it seems this file is C++ and therefore the "going full RAII" option exists and could avoid goto in favor of exceptions or early returns... But if your code is C style that is a tough conversion to make, and not everybody buys into it equally.


True, insightful, but completely beside the point - which was "bracketless conditionals open up an avenue for coding errors."

The fail in #gotofail wasn't in using GOTO - it was a coding error, where a misindented line after a bracketless condition was always executed, when it should have been only executed inside the condition.


But you could also do all of that without omitting curly brackets.


When it shows up in the kernel it is likely to be deep in a hairy if cluster inside some driver code. Thus if you get a failure of some sort it is quite likely that it is best to just drop everything and get out, as the whole edifice is about to come down anyways.


if (something) { blah(); goto fail; }

^^^ that part works

if (something) blah(); goto fail;

^^^ that part is written in a misleading way and doesn't do what it seems to do on first glance.

It is unfortunate that the problematic line contained a jump, because "#gotofail" seems to convey "GOTO considered harmful", while it's something completely unrelated. Ironic, really, given the actual meaning of "human looks at a block of text and misparses it."


You're conveniently not mentioning that this would cause very similar issues:

    if (some_cond) {
        goto fail;
    }
        goto fail;
    if (some_cond) {
        goto fail;
    }
    if (some_cond) {
        goto fail;
    }
    if (some_cond) {
        goto fail;
    }
Is it more obvious? Sure. But the real issue is that they weren't testing all of the important failure cases, not that they weren't using one code style over another. Coding style is not going to help you if one of those some_cond values is incorrectly written...


"More obvious" is precisely my point: the misindentation in your example jumps out at anyone familiar with the syntax. This is not an universal cure, and won't help you with other types of semantic errors: nothing is going to help you if you try to avoid thinking and rely solely on your tools; that is the essence of cargo-cult programming.

OTOH, this tool will help you avoid a common pitfall with potentially disastrous consequences. A high-visibility vest for coding, if you will: won't save you from slipping or your head from falling objects, but neither is its purpose.

(Iterative bootstrapping is how we got from sharpened rocks to virtual machines, not by "meh, this minor improvement won't fix everything, so why bother.")


Popularity may suggest that it is not a bad idea.


May or may not. Given that popularity breeds more popularity, all it actually says is that it was popular enough, sometime in the past, to start a runaway process (I don't really want to start a flame war of "look at those popular yet fairly horrible things/languages/whatevers")


What exactly is the risk here?


Here? Not much but as a style choice it is what lead to an SSL bug in iOS.

https://www.imperialviolet.org/2014/02/22/applebug.html


Reduced mooing.


Compilers warn against misleading indentation these days, so I don't think that line of argument is all that strong these days.


David Kalnischkies response is the most hilarious code review I've ever read.


It's quite funny, but..

" The followers advice is dropping the curly brackets for these one-line ifs to make them all happy. "

I have never understood why anyone would do this. It's a bug waiting to happen (as goto fail showed), for truly marginal benefit

    if (foo)
      bar();

    if (foo) { 
      bar();
    }


I agree, but to be fair, goto fail was not really caused by the lack of curly braces around an if statement body. It was caused by inadequate code review and lack of testing coverage. The latter especially is inexcusable in security-critical code.


"The building's collapse was not caused by poor choices in materials, but by inadequate inspection procedures."

Any number of things could have prevented the bug. So lets do all of them.


That logic clearly fails, though. You will never do everything to prevent a failure. (As an example, there are almost always stronger materials. Cost is a requirement,)

Though, your point here is interesting. Using curlies probably could have stopped that bug. Using static analysis that saw dead code definitely would have stopped it.

In this case, mechanisms (automatic checking for dead code) are vastly superior to good intentions (always using curlies).


You're right.

I didn't mean literally everything. I mean everything that has more benefits than costs. I consider consistent curly brace style to fit in that category.


Consistent is nice. There are place where it is consistent to not use them, though.

And to be clear, I find that just as weird as you probably do. :)


Out of millions of CVEs, one is plausibly related to this coding style. I don't think that's a strong argument for using the more verbose style. If we saw this all the time it might be a different matter.

I think it is a strong argument for compilers' -Wall to detect misindented statements directly following unbracketed conditional expressions, though.


Does this make it a moo-t point?


Also a strong argument for Python's syntax :)


Except in Python both the incorrect and correct code are syntactically valid and the error cannot be detected by auto-formatter.


Because one takes an extra line. For something that's effectively an error condition. There's so reason errors should take up so much vertical code space (which is at a premium even today, given how wide monitors are). This is one of my primary quibbles with golang, and why I will never give in to the community's slavish devotion to "go fmt @


Yikes. Do you realize how useful it is to have a single consistent formatting for source code? It eliminates an entire class of arguments. Or do you enjoy arguing about tabs and spaces, and when to make newlines?


Try rotating your screen 90 degrees.


Do you know how weird that makes me look when I'm coding on my laptop at the airport?


No doubt it's quite weird, but I am of the opinion that hardware should serve the code and coder, not the other way around. Maybe use a portrait orientation tablet with a bt keyboard for travel. I think there could be a small market for laptops with a portrait mode, too.



I am sad that my contribution to this bug has been dropped from Debian:

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=413725


apt-get install cowsay - for all your mooing desires.


fortune | cowsay | lolcat


There is also:

  ip moo


PETA approved.


Can I just say.. Holy cow!




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: