guix-devel
[Top][All Lists]
Advanced

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

RFC: new syntax for inline patches


From: Ricardo Wurmus
Subject: RFC: new syntax for inline patches
Date: Tue, 04 Jan 2022 17:50:31 +0100
User-agent: mu4e 1.6.10; emacs 27.2

Hi Guix,

does this pattern look familiar to you?

  (arguments
    (list
    #:phases
    '(modify-phases %standard-phases
      (add-after 'unpack 'i-dont-care
        (lambda _
          (substitute* "this-file"
            (("^# some unique string, oh, careful! gotta \\(escape\\) this\\." 
m)
             (string-append m "\nI ONLY WANTED TO ADD THIS LINE!\n"))))))))

This is a lot of boilerplate just to add a line to a file.  I’m using
“substitute*” but actually I don’t want to substitute anything.  I just
know that I need to add a line somewhere in “this-file”.

Or maybe it’s a CMakeLists.txt file that inexplicably wants to download
stuff?  I should patch that file but it’s a multi-line change.  So I’m
trying to do the same as above with several different anchor strings to
comment out lines.

We have a lot of packages like that.  And while this boilerplate pattern
looks familiar to most of us now, it is really unclear.  It is
imperative and abuses regular expression matching when really it should
have been a patch.

There are a few reasons why we don’t use patches as often:

1. the source code is precious and we prefer to modify the original
sources as little as necessary, so that users can get the source code as
upstream intended with “guix build -S foo”.  We patch the sources
primarily to get rid of bundled source code, pre-built binaries, or
code that encroaches on users’ freedom.

2. the (patches …) field uses patch files.  These are annoying and
inflexible.  They have to be added to dist_patch_DATA in gnu/local.mk,
and they cannot contain computed store locations.  They are separate
from the package definition, which is inconvenient.

3. snippets feel like less convenient build phases.  Snippets are not
thunked, so we can’t do some things that we would do in a build phase
substitution.  We also can’t access %build-inputs or %outputs.  (I don’t
know if we can use Gexps there.)

I feel that the first point is perhaps a little overvalued.  I have
often felt annoyed that I had to manually apply all this build phase
patching to source code obtained with “guix build -S”, but I never felt
that source code I got from “guix build -S” was too far removed from
upstream.

It may not be possible to apply patches with computed store locations —
because when we compute the source derivation (which is an input to the
package derivation) we don’t yet know the outputs of the package
derivation.  But perhaps we can still agree on a more declarative way to
express patches that are to be applied before the build starts; syntax
that would be more declarative than a serious of brittle substitute*
expressions that latch onto hopefully unique strings in the target
files.

(We have something remotely related in etc/committer.scm.in, where we
define a record describing a diff hunk.)

Here’s a colour sample for the new bikeshed:

  (arguments
    (list
      #:patches
      #~(patch "the-file"
         ((line 10)
          (+ "I ONLY WANTED TO ADD THIS LINE"))
         ((line 3010)
          (- "maybe that’s better")
          (+ (string-append #$guix " is better"))
          (+ "but what do you think?")))))

-- 
Ricardo



reply via email to

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