guix-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: 01/01: services: Add ‘/usr/bin/env’ special file.


From: Bengt Richter
Subject: Re: 01/01: services: Add ‘/usr/bin/env’ special file.
Date: Mon, 9 Sep 2019 00:01:44 -0700
User-agent: Mutt/1.12.1 (2019-06-15)

On +2019-09-09 00:07:10 +0200, Ludovic Courtès wrote:
> Hi,
> 
> Ricardo Wurmus <address@hidden> skribis:
> 
> > Using a custom script with a /usr/bin/env shebang is pretty common.  You
> > don’t need to be a power user for that, and certainly not a *Guix* power
> > user.
> 
> Like I wrote in <https://issues.guix.gnu.org/issue/35910#2> and in the
> message it refers to, although I was initially mildly reluctant to
> having /usr/bin/env by default, I’ve come to think that lack of
> /usr/bin/env is a gratuitous annoyance—not to me of course, but to
> newcomers as we’ve seen repeatedly, be they seasoned GNU/Linux users or
> not.
>
> With that in mind, adding /usr/bin/env by default is probably a good move.
>

Hi Ludo,

I may be one of those (over-) seasoned (past best-before) users you mention :)
-- but with all due respect, is this not a compromise of the fundamental
idea of guix _transactional_ package management? Or did I misunderstand?

I thought the idea was that each mod to the system drew one unique
transaction-arc from current to next state (whether the mod was by
guix install, guix pull, or guix whatever) -- with the ideal goal
of being able to walk the graph transactionally back to any other
state, with no loose ends.

ISTM that the current state defining the behaviour of my system includes
the various config files such as ~/.bash_profile and ~/.guix-profile and
~/.emacs.d/* and all the rest, that programs read to condition their behaviour.

Not only that, but the whole deep tree of references used -- including
scripts and programs called in the body of scripts, not just in the
hash-bang line.

Does that not mean that, ideally :) the particular state of such
referenced entities ought to be captured in a closure belonging
to a particular generation, for that generation's sovereign use?

Implementation optimization is another matter. Things that in practice
don't change much could be shared COW entities, I guess?

I certainly agree with the goal of being able to share scripts without
manual changes, such as what a friend might attach to or include in an email,
or what one might copy/paste from a browser view of gitlab contents, etc.

But not at the price of fundamental compromises :)

Could emacs grow an "M-x pack-region-as" command to produce something
that could be installed with guix install, automatically taking care
of name collisions with existing foo to install foo-from-origin-mnemonic?

Then modding your system would produce a proper generation and could
be controlled.

If there are no tools to do things safely with pure transactions the
result will IME (doing it to myself :) be an unholy mess of unpredictable
future error messages with no easy way to figure out what happened, and
lots of rewrite work to make everything play nicely together for real.

IMO "works" "most of the time" is not a good rationale for compromising
fundamental principles.

I see this as a version of the pythonic (see python -c 'import this') argument
that "pacticality beats purity". Yes it does, but IMO _only_ in emergencies --
because if left to persist, each emergency hack adds to an eventual rats-nest of
tangled dependencies for which there is no "revert" but painful manual analysis
and re-implemention.

BTW, is there a guixian version of "python -c import this" ? "guix describe 
this"? ;-)

> Now, we can add a snippet in the manual with the ‘modify-services’ trick
> to remove /usr/bin/env.  :-)
> 
> > The argument that /usr/bin/env could make software work by accident when
> > testing on a Guix System is not very convincing to me.  We don’t have
> > /bin/sh or /usr/bin/env in the build environment.  Software behaviour is
> > also affected by the presence of /usr, /lib, /bin, etc, and these can
> > all exist at runtime.  We assume that building in an isolated
> > environment is usually sufficient; and yet we sometimes find that
> > applications behave differently when run inside of containers
> > (e.g. applications that call out to coreutils that are usually available
> > in a normal system).
> 
> Yeah.
> 
> Well anyway, if we take a step back, we’re talking about a really tiny
> issue in the grand scheme of things, and it’s certainly not worth losing
> our hair over it.  :-)
> 
> Thanks,
> Ludo’.
>

Here follows an example of a script one might receive in an email from a friend 
;-)

What automation could be brought to bear to include this safely and 
transactionally
into your system to try? As a tool that could be used by a sender or by the 
receiver.

It shows unicode information about characters in its command line arguments
or piped in split by whitespace, e.g., (with control char for good measure :)

Invoked like:
unicode-info Ludovic Courtès $(echo -e "\x07")

"Ludovic":
    glyph  codepoint .....int  name...
    _L_     +U00004c       76  LATIN CAPITAL LETTER L  
    _u_     +U000075      117  LATIN SMALL LETTER U  
    _d_     +U000064      100  LATIN SMALL LETTER D  
    _o_     +U00006f      111  LATIN SMALL LETTER O  
    _v_     +U000076      118  LATIN SMALL LETTER V  
    _i_     +U000069      105  LATIN SMALL LETTER I  
    _c_     +U000063       99  LATIN SMALL LETTER C  

"Courtès":
    glyph  codepoint .....int  name...
    _C_     +U000043       67  LATIN CAPITAL LETTER C  
    _o_     +U00006f      111  LATIN SMALL LETTER O  
    _u_     +U000075      117  LATIN SMALL LETTER U  
    _r_     +U000072      114  LATIN SMALL LETTER R  
    _t_     +U000074      116  LATIN SMALL LETTER T  
    _è_     +U0000e8      232  LATIN SMALL LETTER E WITH GRAVE  
    _s_     +U000073      115  LATIN SMALL LETTER S  

"\a":
    glyph  codepoint .....int  name...
    _^G_    +U000007        7  ASCII bel, aka #\alarm

I used /usr/bin/env in the hash-bang which let me use the -S option
(which I wonder if guile couldn't be taught to emulate if called
directly instead of via env, BTW)

Sorry if this is an inappropriate way to pass on a jelly-bean...
Regards,
Bengt Richter
Oh, gpl3+ on the following, forgot to edit it in ;-/
------------------------------------------------
#!/usr/bin/env -S guile -e unicode-info -s
!#

(use-modules (ice-9 unicode))
(use-modules (ice-9 format))
(use-modules (ice-9 regex))
(use-modules (ice-9 rdelim))
;;(use-modules (ice-9 textual-ports))

;; <ESC> 1 <ESC> ! printf -v cc "\\\x%02x" {0..32};echo -ne "$cc"|od -a|cut -d 
' ' -f2-
;; nul soh stx etx eot enq ack bel  bs  ht  nl  vt  ff  cr  so  si
;; dle dc1 dc2 dc3 dc4 nak syn etb can  em sub esc  fs  gs  rs  us
;;  sp
;; 0000041

;;;; ctl-names from od -a -- see above <ESC>... emacs shell command to capture 
names
(define ctl-names (map cons
                       (iota 33)
                       (map match:substring (list-matches "[a-z]+" 
(string-append  
        "nul soh stx etx eot enq ack bel  bs  ht  nl  vt  ff  cr  so  si "
        "dle dc1 dc2 dc3 dc4 nak syn etb can  em sub esc  fs  gs  rs  us  sp " 
)))))

(define (show-char c)
  (begin
    (let*((c_int (char->integer c))
          (glyph_c (format #f "~:c" c)))
      (cond
       ((char<? c #\040) ;;(char=? c #\177));; ascii control
        (begin
          (let*((c_name (cdr (assv c_int ctl-names))))
            (format #t
               ;    glyph  codepoint .....int  name...     
               "    _~:c_    +U~6,'0X ~8,d  ASCII ~a, aka ~:s\n"
               c c_int c_int c_name c ))))
       (else
        (begin
          (let*((glyph_a (format #f "_~c_" c))
                (c_formal (char->formal-name c))
                (glyph_a (if (not c_formal) "n/a" glyph_a))
                (big_glyph (>= (string-length glyph_a) 4))
                (glyph_out (if big_glyph "see->" glyph_a)))
            (begin
              (format #t
                 ;    glyph  codepoint .....int  name...           
                 "    ~4,a    +U~6,'0X ~8,d  ~a  \n" glyph_out c_int c_int  
c_formal)))))))))

(define (show-str s)
  (begin
    (format #t "\n~s:\n    glyph  codepoint .....int  name...\n" s)
    (map show-char (string->list s))))

(define (strings-from-readlines p)
  (let lp ((line (read-delimited "\n" p 'concat)) (slist '()))
    (if (eof-object? line)
        slist
        (lp (read-delimited "\n" p 'concat)
            (append slist (map match:substring (list-matches "([ \t\f\n]*|[^ 
\t\f\n]+)[\n]?" line)))))))

(define (unicode-info args)
  (let*((as (cdr args))
        (ss (if (pair? as)
                as
                (strings-from-readlines (current-input-port)))))
    (map show-str ss)))
------------------------------------------------



reply via email to

[Prev in Thread] Current Thread [Next in Thread]