guix-patches
[Top][All Lists]
Advanced

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

[bug#57598] [PATCH] doc: Update contribution guidelines on patches, etc.


From: Maxime Devos
Subject: [bug#57598] [PATCH] doc: Update contribution guidelines on patches, etc.
Date: Fri, 9 Sep 2022 20:44:16 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.12.0



On 09-09-2022 15:32, Liliana Marie Prikler wrote:
Also, this is the package source field, not the description, I don't
see how the "helps software stand on its own merits" applies to
snippets of the package source.
Point taken, but imho it still makes sense to prefer keep lists over
remove lists.  The GNU project encourages people to read the sources
after all.

I do not see how the former follows from the latter, I would expect the opposite. GNU project encourages reading source code, we put useful information in the source code (e.g. records on what non-free parts
haven't been replaced yet).


There still is the difference that phases are clearly delimited
while snippets are a block of code that shouldn't get too
large.
Snippets are delimited clearly as well, though, with the
'snippet' field?
And the limitations of snippet length and phases length are the
same -- no limits, though conciseness is appreciate as always.
True, but phases can be made to do just one thing, whereas snippets
have to fix everything that's wrong in more or less one (begin
...).
This is a noticable distinction.>

You can do that in snippets too, with comments:

(snippet
    #~(begin
        ;; Do the foo thing
        (foo)
        (foo-2 [...])
        [...]
        ;; Do the bar thing
        (bar)
        (bar-2 [...])
        [...]))
You can, but it's still wiser to just keep the snippet short enough so
you don't have to.

That's also the case for phases, though? Conciseness is both good for phases and snippets.
   I would however very
much prefer a wording that points people toward this practice
existing,
even if they have to go look in the code for examples.
Alternatively,
a footnote for the most common case (search-input-file inputs
"bin/command") ought to suffice for the time being.

Aside from the typo's and a few rephrasings, I'm done with the
documentation.  If someone wants to extend the section with such
information, they can always do so later.
I haven't seen a v2 though.  Am I correct in assuming that none of the
points we discussed in the last few mails are going to be addressed?

I did sent a v2: <https://issues.guix.gnu.org/57598#8>.
And most were addressed, even if only as me not considering it an issue.


IMHO, I think a reader who remembers the guiding principles should
see that it applies.

Likely. But removing the explicit mention of the guiding principle
still makes the logical reasoning incomplete, remembering has nothing
to do with it.  As I've written previously: ‘This has nothing do do
with [...] and remembering, but rather with [...]’.
In that case, let me rephrase my criticism: "It passes the guidelines"
should not be part of the logical reasoning here.  Otherwise, why not
have a guideline checklist at the end of each subsection (which would
be silly, obviously, but that's the point).

Because, as you note, that's a silly structure, putting the premises (= guiding principles) after the conclusions (= worked-out cases) is an illogical structure, whereas putting the premises _before_ the conclusions is logical


Also, your guiding principles are (with one exception) really just
invariants that ought to hold for the source field of a package.

I don't know about the exceptions (I haven't counted them), but yes,
indeed.  I do not see the problem of this.
For the record, the exception is the "most convenient" bit you've
copied from my patch :)

That guideline actually predates your patch, it's part of the original proposal (of which the wording changed later):

> https://yhetil.org/guix/c4c0a071-2e03-d4d6-6718-05424d21d146@telenet.be/
Sometimes, there remains more than one acceptable way to accomplish the goal. In that case, choose whatever appears to be most convenient.




As such, I think it would be easier to state "A package's source
should
be the smallest corresponding source in terms of uncompressed file
size.  This corresponding source must consist only of free software
(note Free Software) and should build on all platforms supported by
upstream."  Note how smallest naturally implies unbundling bundled
sources.

This criterium on overly small sources.  Often, a package's source
contains things that is not used for the build or outputs and hence
is not part of the corresponding source.  Examples:
Note "should" rather than "shall" or "must", meaning that slightly
larger tarballs are still acceptable.
OK. The criterium remains overly tight though -- by that criterium, slightly larger tarballs are considered undesirable, even when they have useful (and hence, desired) things:


* the source contains documentation that could be built and
installed,
    but Guix doesn't do so yet.  --> should be kept (unless non-free)
* documentation that isn't meant to be built or installed
    (e.g. HACKING, PACKAGERS, ...) --> useful, shouldn't be removed.
* .gitignore, .github, ... --> nothing wrong with removing those,
    but pointless, let's not waste our time with looking for those
    and removing them, even though doing so would make it smaller.
* source files for platforms the upstream does not support
yet/anymore
    (but with some volunteer effort (e.g. bugfixes), it might become
    a supported system again)
    --> removing them (e.g. as part of an overly-broad
(delete-file-recursively
"this-dir-has-bundling-albeit-not-all-of-it-is-bundling"))
        can be OK-ish, but removing them for 'minimality' is
pointless.

I see you're nitpicking for the sake of the argument,

I'm not.  It's nitpicking for the sake of the four * examples above.

but none of the
examples you provide (safe for the bundling one) add much cost to
either packing or unpacking.

Not the point, the point is that having to treat those examples seriously is a waste of time and even somewhat harmful (removing useful stuff).

Thus, I'm pretty sure we can ignore them
for practical purposes.

As I've explained, this guideline is inconsistent with what is actually recommended. Here are some practical purposes:

* minimal dissonance between 'appreciated by policy' and 'appreciated by
  reviewers, packagers, users'.
* not having to review and accept pointless patches to Guix for deleting
  .github, .gitignore, uninstalled documentation that were written
  for the sake of minimality
* not having to (in the sense of: it would be appreciated if you'd do
  that) write such patches

  That being said, if you have a better
formulation, please do tell.

The four guiding principles.



I still find this wording very confusing. Perhaps "To add new
functionality, a patch is almost always the best choice. For
one,
it is likely that the new functionality requires changing
multiple
lines of source code, which is more convenient to do with a
patch
than with a snippet. Further, patches can be taken from and
submitted to upstreams more easily. If your patch has not been
submitted to upstream, consider doing so."
It loses some information (that patches are preferred) and
(after re-adding the conclusion) is more verbose, which appears
to be considered very important.
Which conclusion is there to re-add?

"patches are preferred"

    The conclusion is already stated
in the beginning: patches are almost always the best choice.  Then
two
reasons as for why.  The part w.r.t. upstreaming changes has also
been
addressed.

While I consider that policies should have "best choices" coinciding
with "preferred" and that not doing so would be illogical, people,
projects, decisions ... are far from always logical.

Because of this, people cannot assume that the 'best choices' are
'preferred', so it needs to be mentioned explicitly that these 'best
choices' are actually 'preferred'.
In that case, simply write preferred choice?

It is already mentioned that they are preferred:

‘As such, patches are preferred’

By removing the information that 'patches are the most convenient choice' (by replacing it with ‘patches are the preferred choice’), the logical structure becomes weaker; a part of the explanation on the ‘why’ becomes missing.


I'm using enumeration as a super term here, which can be
((sub)sub)sections, chapters, list elements, whatever, and my claim
is that we barely have enough principles to allow the use of a
plural.

In English, things are either plural or singular.  Everything >= 2 is
plural.  There number of principles, however we count them, is, at
least, 2.  Consequently, the principles are plural, not singular.
Treating the principles as singular is simply grammatically
incorrect.
Correction: Everything that isn't exactly 1 is plural in English,
including 0, with perhaps the exception of -1 also using singular.

Maybe it is barely allowed to be plural, but English grammar doesn't
care about that -- it is definitively disallowed to be singular, only
plural remains.
Note that my argument isn't about English grammar, it uses English
grammar.

Your argument is that ‘there aren't a sufficient amount of principles to allow the use of a plural’. 'Plural' is a concept of English grammar.
As such, you have written an argument about English grammar.

You appear to have meant some different argument, but all the arguments on ‘are they guiding principles or not’ I've read are based on the number of principles or on what 'guiding principle' means, which are issues of grammar and vocabulary respectively.

I'm still not seeing how they aren't guiding principles. Maybe you have a different meaning of ‘guiding principles’ in mind? Or maybe you would
like to name them 'guidelines' or 'general recommendations' instead.

Adding to that, now that I think of it, I also doubt their
usefulness in guiding.  "Use whatever feels convenient, but note
that that might be subjective" is more useful at the end of the
section when a user didn't find what they were looking for than at
the start.

The introduction has a set of guiding principles, from with concrete
cases are built.  By adding another principle at the end, the cases
cannot make use of the "use [...] convenient" principle.

Additionally, now the user has to look at _two_ places to find the
guiding principles -- at the beginning, and at the end.  Worse,
the beginning does not have a cross-reference to the end, so since
the set at the beginning is presented as exhaustive, the user might
not know there is another guiding principle.

And even if they did read through the whole section (even though they
should only have to read the introduction and the relevant worked-out
case), assuming they read through it in a linear fashion, due to the
new guiding principle that wasn't alluded to at the beginning, they
have to redo their mental model of "Modifying Sources" as this
principle could invalidate things.
This shows both a problem with your structure,

I'm not seeing the problem.  How does this show a problem?

but more importantly, a
failure to understand what I meant when I wrote "use whatever is
convenient" in my own patch.  This principle *can* only work for cases
in which there is *no clearly established practice*, thus putting it at
the end *after having enumerated all practices* is the logical choice.
With your structure, you have to bend it sideways to shoehorn it in
with the other principles.

You appear to have meant it as a kind of ‘fallback principle’, in which case putting it at the end does indeed make sense.

In my patch, the principle works differently, it is also used for explaining already established practices, for the cases where there are multiple technically allowed principles but still often a single _recommended_ principle. E.g.:

Usually, a bug fix comes in the form of a patch copied from upstream or
another distribution.  In that case, simply adding the patch to the
@code{patches} field is the most convenient and usually does not cause
any problems; there is no need to rewrite it as a snippet or a phase.

If no ready-made patch already exists, then ...]

and

To add new functionality, a patch is almost always the most convenient
choice of the three

.

To go from the principle as used in your patch to the principle as used in my patch, perhaps in the process it is bent sideways and shoehorned. But after all the bending and shoehorning, it seems to fit well now in the beginning (and not well at all the end), so I'm not seeing any problems here.


At the risk of responding jokingly to what was meant serious: I
didn't know we suddenly gained 20 guiding principles.

25 lines are for the guiding principles (sometimes referring to a
principle of elsewhere in Guix, sometimes a new principle for
"Modifying Sources").  You proposed to 'cache' them somehow.  In
Guile, to cache something, you can use 'delay/force'.  But this
increases the amount of code (due to the additional use of 'delay'),
instead of decreasing.

The documentation equivalent (whatever that might be, I am not seeing
one myself) would then also be at least as long, maybe even a little
longer due to the use of 'delay'.
Okay, so I did misunderstand those 25 lines as 25 lines within the text
calling back to those guiding principles rather than 25 lines for the
guiding principles themselves.  Still, 25 lines are a little much,
especially given that the bulk of it explains the semantics of the
packages' source field.

I think we'll have to agree to disagree on that.


I suppose table items might take two less line or so less than
subsubsections, but I don't think that's sufficient reason to
step away from a nice section structure.
Another reason is that you can end a table in the middle of a
section, which you can't do with subsections.  Hence why I'm able
to put a remark at the bottom, which you have to clumsily fit into
the top.

I can, indeed, not put the 'convenience principle' at the bottom,
except perhaps by adding a new subsubsection, and for tables adding
such a remark at the bottom is indeed more convenient.

However, I don't see the 'have to clumsily' here -- as explained
elsewhere, I believe that the 'convenience principle' shouldn't be
separated from the other principles and that it fits nicely next to
the the principles --- there is no 'have to', because I choose for
this, and I am not seeing any 'clumsiness' here.
I think we'd have to debate choice vs. force here which would be a
rather long aside, but to make my argument short, your choice of how to
structure this section (table vs subsections) directly influences your
"choice" where to place particular information

Sure.

in a way that might
inhibit natural information flow.

I'm not seeing it. As I've explained previously, putting the premises (= guiding principles) before the conclusions (= worked out cases / solutions) is a logical (hence, natural) information flow, and introducing them on-the-way or implicitly is ad-hoc (unnatural).
The patch does this, currently.  It already proposes a number of
hammers (patches, snippets and phases) and purposes (adding new
functionality, fixing technical issues, unbundling, ...).
Also, the scenario "oh no, however will I put this nail into a
wall"
actually happened -- see the Shepherd discussion, where there was
a lot of disagreement on how nails (= small work-around in the
Makefile) should be put in walls (= patches, snippet, phase?).
It
was the whole reason to start writing a documentation patch.
You might want to add a link here if it supports your argument, but
without looking at the discussion this rather sounds like "oh no, I
have three hammers, which one do I pick?" – which, fair enough, is
still a problem, but one that neither of our patches would cause
imho.

As I think I've written previously, the whole point was to solve that
problem. For the discussion, see:

* https://issues.guix.gnu.org/54216
*
https://yhetil.org/guix/c4c0a071-2e03-d4d6-6718-05424d21d146@telenet.be/
*
https://yhetil.org/guix-devel/84e13ef7d437062df5cca51a12e6da54929e0176.camel@telenet.be/

Not solving the problem defeats the whole point, as the purpose is to
solve that problem.
I think we might be disagreeing about what constitutes "solving the
problem" here.  Correct me if I'm wrong, but to me it seems any
scenario that is not covered by whatever patch is applied counts as
"not having solved the problem".

It doesn't -- I consider the Shepherd problem to be solved by my patch (albeit rather weakly, see later), and the wider problem of unclear guidelines and policy on snippet/phase/patch to be, perhaps not really solved, but still much improved (this time not weakly).

I personally find this line of
reasoning questionable, as there are perfectly valid reasons why
multiple tools could apply.

See previous paragraph.

Take the problem of embedding a store path.  You could for instance
replace all occurences of "sh" with /gnu/store/.../bin/sh, or you could
first replace them in a patch with "@sh@" and then replace that with
/gnu/store/.../bin/sh.  Of course, you rarely have to do the latter and
the former is simpler, hence why you will often see the former, but
that doesn't mean the latter is invalid.

It's contrary to 'It preferably should also work on non-Guix systems’ -- not invalid, but still usually (*) against (proposed) policy because a direct substitute* is at the same time more convenient and follows all the the principles.

(*) sometimes, in case of shell scripts, a substitute* is fragile (substituting too much), in which case a "sh" -> "@sh@" becomes more convenient and hence the violation of the 'non-Guix system' rules becomes acceptable.

And if they don't find anything, they see the handy little line
at the bottom saying "use whatever you think is convenient".
Nowhere did the patch imply that the listed cases were all cases.
In fact, in two places in the introduction it is implied that the
examples are not exhaustive, and that they can choose according
to convenience  [...]
Emphasis on handy little line rather than needing to be told twice
(particularly if people have no idea what to expect due to not
having looked at the worked-out cases yet).

They don't need to be told twice.  Also, my patch also has that handy
little line (albeit differently worded), see the 'guiding
principles'.

Also, on the 'no idea what to expect' -- this is exactly the same for
your patch too?  In both patches, if the user only reads the
introduction and conclusion (if any) and doesn't read the actual
(relevant examples)/(explanation of patches, snippets, phases), then
that's their problem.
I do think a table in the middle of the section is hard to ignore,

I think so too, hence my previous response.

but suppose for the sake of argument that they do, [...]

Given this response, I assume I've misinterpreted what you meant with ‘not having looked at the worked-out cases yet’.


I also expand a little on the benefits and drawbacks of
these approaches as you would when describing design patterns.
This is also done in my patch. [...]
This is not about the contained information, but the structure of
the contained information.

My solution->problem style follows roughly this style:
1. solution
2. problems it is known to solve
3. how to use
4. properties, caveats, etc.

Your problem->solution style roughly has the following:
1. problem
2. (set of) solution(s)
3. if more than one solution, maybe a help to select

Also, in no particular order

    4.: how to use
    5.: explanation why it is preferred (properties, caveats?)
No particular order is problematic,

I'm not seeing why.

 but more importantly if a
technology appears more than once (guaranteed by the pigeonhole
principle), then either its properties get repeated (not good for
length) or scattered (not good for the flow you want).  Again, a
structural problem.

That's equally applies to your patch too, though? (Switching "technology" with "problem".)

Also, I've re-read my patch, and I didn't find any repeated properties or scattering, except for a single property (patches are upstreamable):

> First, when the fix is not Guix-specific, upstreaming the fix is
> strongly desired to avoid the additional maintenance cost to Guix.
> [...]
As such, patches are preferred.  However, as with bug
fixes, upstreaming the new functionality is desired.

As such, I'm not following your point here.

This makes it so that people might have to go to a different
subsection than the one they read for their solution to find out
about potential caveats, e.g. not embedding store paths in a
snippet.

I assume their problem was "X doesn't find Y".  This being a
technical issue, they go to "Fixing technical issues".  In that
subsubsection,  there are the words:

Secondly, if the fix of a technical issue embeds a store file name,
then it has to be a phase.  Otherwise, if the store file name were
embedded in the source, the result of @command{guix build --source}
would be unusable on non-Guix systems and also likely unusable on
Guix systems of another architecture.

so they actually do know of the caveat 'don't embed store paths in a
snippet, do it in a phase instead', and they did not need to go to a
different subsubsection.
Typical happy path.

Indeed, it's a happy path!


Your problem->solution approach instead leaves people wondering
when their particular use case has not been described.
See my reply to ‘And if they don't find anything, they see the
handy little line at the bottom saying "use whatever you think is
convenient’.
It gives them a solution rather than the tools to build
solutions with.
It does give the tools: snippets, patches and phases.
As far as I read, it describes none of those.  It puts out guiding
principles and some already worked-out cases.
Here are the descriptions:

Guix has tree main ways of modifying the source code of a package,
that you as a packager may use.  These are patches, snippets and
phases

Once the user knows _which_ of the three they should use (by
consulting the following subsubsections), they can then search for
'patch', 'snippet' and 'phases' in the manual for more information,
no need to duplicate that information.
Point taken, but imho cross-references are nice for those who just
learned "okay, I now know I need to solve my technical problem with a
phase, how do I do that?"

They are indeed.  But I'm not following what you mean with "But" here.
I didn't claim anything about cross-references there?

Do you want me to add a few cross-references (for 'patch', 'snippet' and 'phases')?

Also, "giving the tools to build solutions with" does not help
with the problem that I aimed to solve -- there was disagreement
on what the appropriate tools are (see: Shepherd), so it not just
needs to give the tools, but also the solutions.
I don't see how my patch lacks this information however.

IIUC, the raw information should usually be indeed all there, but the
user has to consult _all_ of the sections to determine which option
(patch, snippet, phase) is appropriate, having to assemble all the
information is (a) a waste of time and (b) can lead to different
interpretations and conclusions (see: Shepherd).

More concretely, I cannot use your patch to decide between phases,
snippets and patches for the Shepherd issue:

* none of three appear to be forbidden by your documentation
* there is no recommendation for 'patches' (IIRC it wasn't accepted
upstream and there was no intent to submit it upstream, it being
really a Guile bug, not a Shepherd bug)
* there is no recommendation for snippets (it's all free, no
bundling)
* build phases are 'to be avoided' (but not forbidden), as it
resulted
    in observably different runtime behaviour (being a bug fix)

-- three (or at best, two, if build phases are discounted) options
remain.  Myself, I would then consider 'snippets' to be the most
convenient, but some others (see: Shepherd, IIRC) would really want a
patch instead, because 'patches can be reverted' or something like
that.

As such, you are giving the tools (snippets / patches / phases, some
downsides and upsides), but different people can construct different
solutions from those tools even in the same situation, leading to
conflicts.

If I use my patch instead, I go to "fixing technical issues". This
section tells me to use a patch or a snippet.  As the fix is not
Guix-specific, it recommends a patch to save time when upstreaming.
Conclusion: write a patch.  It was a Guile bug, so the fix was a
patch to Guile.  But that would take time and upstream took the
responsibility for a fix, so the 'efficient time thing' doesn't
really apply and a small work-around (setting optimisation flags)
suffices.

In this situation, the subsubsection doesn't care at all if you go
for a snippet, so apply the last guiding principle: go for the
simplest thing: a snippet. (Unless you already have a patch, then a
patch is simplest.)
Does someone else have a different idea on what's simplest?  Doesn't
really matter, ‘Sometimes this is subjective, which is also fine’.
I do get the impression that this patch simply codifies what you feel
is right based on the shepherd situation

True, except for the 'simply', as I also considered several other situations (Removing bundled libraries, Removing non-free software, Adding new functionality). I do not see the problem with this -- the proposed policy was considered workable even if some would like it to be a little bit different, and if others feel strongly about they could, I don't, maybe set up a vote system or such.

rather than thinking about the general case,

See: several other cases that should cover most situations encountered in practice, and for the parts of the general case that aren't worked-out yet, there are the guiding principles.

which is why my patch makes weaker statements here.  If
this issue could have been avoided with a #:make-flag, we would have
used that.

More importantly, I fail to see the superiority of your patch here > IIUC 
neither patch offers a unique solution to the shepherd thing, so
the room for debate remains

In my patch, multiple options remain, but there is no real room for debate. More concretely:

When there is more than one way to do something, choose whichever method
is the simplest.  Sometimes this is subjective, which is also fine.
What matters is that you use techniques that are common within the
community (i.e., patterns that appear throughout @code{gnu/packages/...})
and are thus clearly legible for reviewers.

it is considered subjective, having multiple options if fine! To correct a packaging following the other option (to help with following the policies), you don't have to debate on what's the proper option to get a fix in, as both are considered acceptable. In many cases, no need for debate, just pick one and move on. (Also the case for your patch IIUC.)

Things are also phrased reconciliatory, e;g.:

To make things more concrete and to resolve conflicts between the
principles, a few cases have been worked out:

However, in your patch, there is more opportunity for conflicts. E.g.:

Each one has its strengths and drawbacks, along with intended andhistorically 
derived use cases.

By this line, arguments like 'X was historically the intended purpose of Y, using Y for Z is incorrect' become reasonable, which makes disagreements more difficult to resolve (as you know need to consult history and because history is fixed, so no improvements would be possible anymore in areas where there is a historically intended use case).

You could claim that my patch offers more
room, which fair enough, it does, but on the same token it allows
people to see that the guidelines have been followed and the patch can
be applied.

In particular, for review purposes, mine should be easier to work
with.  For instance, the reviewer sees a hash embedded in a
snippet, sees in the snippet entry that you shouldn't do that, and
can thus say "nope, don't do a snippet here".

That is also the case for problem->solution? A "sh" -> #$(file-append bash-minimal "/bin/sh") substitution can be recognised on sight as not possibly being anything else than a technical fix, and then the subsubsection on technical fixes mentions that those must be done in phases.

Or, another explanation: reviewers usually have seen a lot of more packages than a new packager. Because of that, and because they have familiarised theirselves with policy, they have over time automatically built a mental 'reverse index' of solutions->problems.
I think we should optimise for packagers before reviewers
Code is more often read than written, so optimising for the reader is
optimizing for the packager as well.

While all reviewers are readers, not all readers are reviewers, and reviewing usually happens only once, maybe twice per patch.

Regardless of which patch we pick, it should not mandate a
particular solution in potentially contentious cases,

Actually the whole point was to mandate a particular solution for the
contentious cases, see Shepherd.
But I disagree.

Memes aside, please refrain from the "I'm right, do this" style (which
is another problem with the "problem-centric" approach),

Is this referring to the style of the documentation patch? If so: it does explain why the "do this" is right, so I don't see the problem. Do you have a particular point of the documentation in mind you consider wrong (*)?

(*) points I know of:
* keep lists / remove lists (for the footnote about not-yet-policy on removing things in patches)
* the guiding principles aren't guiding principles

but rather
focus on writing a patch that makes reviewers not discard a patch due
to formalities.

I think the patch (v1 and v2) satisfies that.

If the shepherd thing had needed an upstream patch,
even with a snippet that patch could have easily been created by
converting that snippet to a sed, so more time was wasted debating than
overworking.

I do not see your point here -- #57598 is about documentating/making policy, not 'should we spent time on correcting the shepherd package to match policy / convincing the other party that the status quo matches policy'.

and also point towards the right solution.  See our discussions on
the individual solutions on points in which I believe you've
errored.

These are:

* the typo's
* including "skipping tests indicating failure under ‘Fixing
technical issues’"
* "don't mention file names of non-free things in patches"

Did I miss any?
I'm pretty sure there's also a discussion on store path embeddings at
the very least.  Forgive me if I too missed something.
There was a discussion on store file name embeddings. There was no mention of any errors in the documentation of store file names. IIRC, we agree on how store file name embeddings must be done. There were, however, proposals to extend the documentation to cover ‘how to embed’ in more detail (substitute* + search-input-file ...), but no errors.

Greetings,
Maxime.

Attachment: OpenPGP_0x49E3EE22191725EE.asc
Description: OpenPGP public key

Attachment: OpenPGP_signature
Description: OpenPGP digital signature


reply via email to

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