Skip to content

Conversation

@ndim
Copy link
Contributor

@ndim ndim commented Aug 8, 2024

Install doc files:

  • README.md and CHANGELOG.md
  • LICENSE.txt

Install README files into all directories where the user can place files describing the respective directories:

  • cowpathdir (default: /usr/local/etc/cowsay/cowpath.d)
  • cowsdir (default: /usr/local/share/cowsay/cows)
  • sitecowsdir (default: /usr/local/share/cowsay/site-cows)

This PR is based on #26 - merge that one first.

@apjanke
Copy link
Collaborator

apjanke commented Aug 20, 2024

#26 is merged. We can talk about this one now.

Hmm. I like installing the documentation files into $docdir. But I don't know about dropping READMEs in to the various data directories, though. That doesn't seem to be very conventional for Unix programs. I don't have a reference for that; just not something I've seen much.

The other thing is that, while this isn't correctly documented, cowsay supports no-extension cow files. You can use them with cowsay -f <cow>, even though they don't show up under cowsay -l.

The man page says this under "COWFILE FORMAT":

The name of a cowfile must end with *.cow*, otherwise it is not recognized as a cowfile.  

But the code allows no-extension files (or extensions in the -f option argument).

sub resolve_cow {
    my ($name) = @_;
    my $full = "";
    for my $d (@cowpath) {
        if (-f "$d/$name") {
            $full = "$d/$name";
            last;
        } elsif (-f "$d/$name.cow") {
            $full = "$d/$name.cow";
            last;
        } elsif (-f "$d/$name.pm") {
            $full = "$d/$name.pm";
        }

So under this PR, you get an odd error if you use "README" as the name of a cow.

[cowsay] $ cowsay -f README blah
do "README" failed, '.' is no longer in @INC; did you mean do "./README"? at /usr/local/bin/cowsay line 348.
 ______
< blah >
 ------
[cowsay] $ cowsay -f nosuchcow blah
cowsay: Could not find cowfile for 'nosuchcow'!
[cowsay] $

I think we should make the behavior uniform here. I think that undocumented no-extension cowfile behavior has been here for a while. The 3.04 code does it:

	for my $d (split(/:/, $cowpath)) {
	    if (-f "$d/$f") {
		$full = "$d/$f";
		last;
	    } elsif (-f "$d/$f.cow") {
		$full = "$d/$f.cow";
		last;
	    }

So for back-compatibility, should probably keep it around. But I'd like to make cowsay -l recognize them too, so it's consistent. In that case, adding README files to the cows and site-cows directory would make "README" cows show up in the list, too.

Not much impact here, but it doesn't feel "clean" to me.

Either way, IMHO the man page should be updated to note the *.pm and extensionless cow files. Or we should just remove the *.pm cows, since support for that format is broken. I'm leaning toward the latter.

@ndim
Copy link
Contributor Author

ndim commented Aug 20, 2024

I have seen README type files in places where other programs are intended to drop their config files or where other information about the directory makes sense. Having a README file around might not be a Unix tradition specifically, but has certainly been a standard in IT systems for many decades.

I think the idea to place a README where a bit of information is needed makes sense. That is a nice gesture towards the people who are not cowsay developers.

Case in point: On my system, I have 182 README type files in /usr/lib (README, README.md, README.txt, README.rst, README.xz, README.<some-thing>).

$ locate -b README | grep ^/usr/lib/ | wc -l
182

such as

$ cat /usr/lib/firewalld/ipsets/README.md
Location for built-in ipsets
$ cat /usr/lib/sysctl.d/README 
Files in this directory contain configuration for systemd-sysctl.service, a
service to configure sysctl kernel parameters.

See man:sysctl.d(5) for explanation of the configuration file format, and
man:sysctl(8) and man:systemd-sysctl.service(8) for a description of when and
how this configuration is applied.

Use 'systemd-analyze cat-config sysctl.d' to display the effective config.
$ cat /usr/lib/sysusers.d/README 
Files in this directory contain configuration for systemd-sysusers, a program
to allocate system users and groups.

See man:sysusers.d(5) for explanation of the configuration file format, and
man:systemd-sysusers(8) for a description of when and how this configuration is
applied.

Use 'systemd-analyze cat-config sysusers.d' to display the effective config.
$ cat /usr/lib/tmpfiles.d/README 
Files in this directory contain configuration for systemd-tmpfiles, a program
to create, delete, and clean up volatile and temporary files and directories.

See man:tmpfiles.d(5) for explanation of the configuration file format, and
man:systemd-tmpfiles(8) for a description of when and how this configuration is
applied.

Use 'systemd-analyze cat-config tmpfiles.d' to display the effective config.
$ cat /usr/lib/udev/hwdb.d/README
Files in this directory specify a description of hardware devices, in the form
of mappings from modalias-like keys (which identify specific hardware devices)
to udev properties.

Files in this directory are not read by udev directly. Instead,
man:systemd-hwdb(8) compiles them into a binary database.

See man:hwdb(7) for an overview of the configuration file format, and
man:systemd-udevd.service(8) for a description of the udev daemon.

Use 'systemd-analyze cat-config udev/hwdb.d' to display the effective config.
$ cat /usr/lib/udev/rules.d/README 
Files in this directory contain configuration for systemd-udevd.service, a
daemon that manages symlinks to device nodes, permissions of devices nodes,
emits device events for userspace, and renames network interfaces.

See man:udev(7) for an overview of the configuration file format, and
man:systemd-udevd.service(8) for a description of service itself.

Use 'systemd-analyze cat-config udev/rules.d' to display the effective config.
$ _

Regarding the problem with no-extension cow files (NECF)... we could also call these doc files README.md. They are markdown files, after all, and there is precedence for having README.md files documenting directories in /usr/lib.

So... the man page says "*.cow or *.pm", and the code behind cowsay -l only lists the documented *.cow and *.pm files. That is consistent. The code considering legacy NECFs when explicitly given a cow with cowsay -f is inconsistent, but might be a legacy behaviour.

That undocumented legacy behaviour might exist because it allowed testing cowsay -f tux.cow vs cowsay -f tux.pm with actual NECF not really having been intended use. The former NECF mech-and-cow certainly was not intended use, because NECF cow files must be the same file format as *.cow files and the NECF mech-and-cow was just a plain text file and therefore did not even work.

IMHO extending cowsay -l to include any type of file would not be a good idea. There are always editor backup files and similar things, called foo~ or foo.bak or .foo.something. Listing all of those files not make sense, and filtering them out with a block list of file name patterns is a neverending story. Using a positive list of allowed filename patterns such as the documented *.cow and *.pm is a much more robust way to go forward.

Keeping the existing cowsay behaviour for cowsay -l and cowsay -f and cowsay -r makes the most sense to me, while renaming the README files to README.md.

@apjanke
Copy link
Collaborator

apjanke commented Aug 20, 2024

Yeah, I think I agree. The "make them README.md, and only treat *.cow extension files as cowfiles" seems like a good approach. And then tighten up the behavior for -f to limit the number of cases where NECFs or other-extension files are viewed as cowfiles. "positive list of allowed filename patterns" seems like the better approach here, even if it's not fully back-compatible. I doubt many users are actually (intentionally) using the any-file-extension-or-none behavior. And having README.md docs out in the actual config/data dirs would be friendlier to non-developers.

Want to rebase this on main again? I rearranged the repo a bit to deal with the "not correctly detecting installation location" problem, and moved some of the doco files into a man subdirectory.

3.9.0 seems like a reasonable tentative release target for this.

@apjanke apjanke added the enhancement Make stuff better! label Aug 20, 2024
@apjanke apjanke self-assigned this Aug 20, 2024
@apjanke apjanke added this to the 3.9.0 milestone Aug 20, 2024
@ndim ndim force-pushed the install-docs branch 2 times, most recently from 92491a8 to f0f25b2 Compare August 21, 2024 01:20
@ndim
Copy link
Contributor Author

ndim commented Aug 21, 2024

Uhmm... I rebased, added a CI workflow, and fixed a few things.

Until you have enabled Actions for PRs on cowsay-org/cowsay, see https://github.com/ndim/cowsay/actions for the CI jobs and their results.

@apjanke
Copy link
Collaborator

apjanke commented Aug 21, 2024

Uhmm... I rebased, added a CI workflow, and fixed a few things.

Ah, cool!

I've got permissions set to allow PR-related GH Actions runs, I think - in the repo-level Actions permissions, I have it set to "Allow all actions and reusable workflows", "Require approval for first-time contributors" (only), Workflow permissions = read repo contents and packages, and unchecked "Allow GH Actions to create and approve PRs". I think I also need to configure an Actions Runner, and actually merge a commit like this with some .github/workflows content before we'll see any Actions runs in the main cowsay-org/cowsay repo instead of just on your PR. But I can see the linked Actions runs you have here no problem.

Could you rebase again? Sorry for the hassle; I did some more dir rearrangement and a squash/force-push around the 3.8.3 release. That's the last force-push you'll have to deal with; I protected the main branch so nobody's allowed to do that any more.

This mostly all looks good to me, aside from a couple aesthetic/philosophical quibbles around the handling of symlinks and deletes in the install/uninstall targets.

image

Instead of README-<blah>.mds in the root of the repo, could you put these at share/cowsay/cows/README.md, share/cowsay/site-cows/README.md, and etc/cowsay/cowpath.d/README.md? The dir layout of the repo now mostly mirrors the installation prefix dir layout, to make it easier to test stuff in-place. E.g. when running directly from the repo, this should make it more clear whether the cowpath.d reading code is correctly handling the presence of a README.md in that directory.

image

I'd like to think about and discuss this removal of cowthink.1 as a make man target dep, and the changes to symlink deletion & creation in make install in a bit more detail. But I think I'm good to merge the rest of the changes here now, once rebased. Want to split the cowthink.1 dep and symlink changes out to a separate PR, if you want to get the rest merged quickly?

@apjanke apjanke mentioned this pull request Aug 21, 2024
@ndim
Copy link
Contributor Author

ndim commented Aug 26, 2024

image

I'd like to think about and discuss this removal of cowthink.1 as a make man target dep, and the changes to symlink deletion & creation in make install in a bit more detail. But I think I'm good to merge the rest of the changes here now, once rebased. Want to split the cowthink.1 dep and symlink changes out to a separate PR, if you want to get the rest merged quickly?

.PHONY: man
man: cowsay-man.stamp

cowsay-man.stamp: cowsay.adoc
    asciidoctor cowsay.adoc  # generates both cowsay.1 and cowthink.1
    date > cowsay-man.stamp  # if successful, generate and update the stamp file

The basic idea is:

  • You do not tell make anything about cowthink.1.
  • make knows it is supposed to generate cowsay.1.
  • The recipe generating cowsay.1 also happens to generate cowthink.1.
  • make runs the recipe generating cowsay.1 and (unknowingly) cowthink.1.
  • Everything is working as intended.

This is the same principle which the automatic dependency file generation uses as described in https://make.mad-scientist.net/papers/advanced-auto-dependency-generation/.

.PHONY: man
man: cowsay.1 cowthink.1

cowsay.1 cowthink.1: cowsay.adoc
    asciidoctor cowsay.adoc  # generates both cowsay.1 and cowthink.1

If you have a make recipe with two targets, make will run that recipe once for each target. That is ok if that recipe only generates the one target which make is running it for. However, the asciidoctor recipe creates both targets at the same time, so running that recipe twice is a waste of resources in the best case or a way to race conditions with two asciidoctor processes simultaneously writing to the same two files.

To make that recipe run only once, the third alternative is to write the make recipe to generate a stamp file and use that stamp file for dependencies:

.PHONY: man
man: cowsay-man.stamp

cowsay-man.stamp: cowsay.adoc
    asciidoctor cowsay.adoc  # generates both cowsay.1 and cowthink.1
    date > cowsay-man.stamp  # if successful, generate and update the stamp file

However, why deal with a separate stamp file when you can just use the generated cowsay.1 file? And now we are back at the basic idea from above: Generate one target explicitly, and have all other files generated as a side effect.

@ndim ndim force-pushed the install-docs branch 3 times, most recently from 01fcfd9 to 01fb22d Compare August 26, 2024 14:55
@ndim
Copy link
Contributor Author

ndim commented Aug 26, 2024

I have just rebased this onto main.

I have worked around the cowsay.1/cowthink.1 parallel build issue by only updating man/man1/cowsay.1 from any make recipe, and leaving man/man1/cowthink.1 completely untouched.

The green checkmarks on https://github.com/ndim/cowsay/commits/install-docs/ say the CI runs successfully.

@ndim
Copy link
Contributor Author

ndim commented Aug 27, 2024

Sorry I forgot to push cleaning up of the XXX temporary commits. 12 to 24 hours.

@ndim
Copy link
Contributor Author

ndim commented Aug 27, 2024

Finished.

@ndim
Copy link
Contributor Author

ndim commented Aug 29, 2024

Uhm... @apjanke with "rebase", did you mean "rebase onto main" or "rebase onto dev/free-mime" (whatever "free-mime" means)?

I have rebased onto main. Please tell me if I should rebase onto dev/free-mime.

ndim added 5 commits August 29, 2024 19:55
Do a basic "make install" and "make uninstall", showing the list of
installed files.

Additionally, a check is performed to ensure "make uninstall" uninstalls
all files, and the man pages are being rebuilt.
As you cannot rely on "ln -s foo bar" to do the right thing if
the something of the same name already exists, it is prudent to
remove the name before creating it as a symlink.

And "ln -sf" has its own issues. So... "rm -f ... && ln -s" it is.
Clean up the make recipe which updates the man page:

  * There is no need for an additional dependency of
    .PHONY target "man" to depend on the adoc file which
    the "cowsay.1" target already depends on.

  * We do not touch the man/man1/cowthink.1 symlink in any
    make recipe any more.

  * We have asciidoctor put its results into a temporary
    directory, and then move only the cowsay.1 file from
    there to the make target. So the make recipe only updates
    one file, and we avoid the need to think about generating
    files as side effects.

    Also, we only need to update the man page if it has actually
    changed. A change to the Asciidoctor version or to the current
    date does not count as an actual change, so we normalize those
    away before deciding whether to update cowsay.1 or not.
Install cowsay documentation files into docdir, such as
CHANGELOG.md LICENSE.txt README.md
@apjanke
Copy link
Collaborator

apjanke commented Aug 30, 2024

with "rebase", did you mean "rebase onto main" or "rebase onto dev/free-mime" (whatever "free-mime" means)?

I just meant "rebase onto main". I'm not going to make you deal with my alternate work branches. :)

"free-mime" is a silly phrase that sounds like "three nine", and is where I'm putting my work for the upcoming 3.9.x minor release series. Similarly, for the "dev/fro-yo" branch, "fro-yo" sounds like "four oh", and is where I'm putting my longer-term changes for the 4.0 major release.

This rebase looks good. I should be able to review it, and read through your longer comment about the make man targhet, by this weekend. Thanks!

@ndim
Copy link
Contributor Author

ndim commented Aug 30, 2024

The long comment recently became shorter, as it was easier to just implement the thing than to describe it in the comment.

@ndim
Copy link
Contributor Author

ndim commented Aug 30, 2024

BTW, regarding the three-nine branch consequences for install-docs:

  • Installing CONTRIBUTORS.md is as easy as adding one doc_DATA += CONTRIBUTORS.md line.

  • Installing some of the new doc files from the doc-project/ subdirectory is non-trivial, but I have already written the code for that (not in this PR's install-docs branch, though).

@apjanke
Copy link
Collaborator

apjanke commented Dec 1, 2024

I pulled the CI setup on to main in ee5c050 (with a cherry-pick, preserving your author credit). I think that will enable CI for new PRs based off main, since they will now include the CI *.yml files in their source branches. Will give it a try with some test PRs tomorrow; I'm about out of gas for tonight.

@apjanke
Copy link
Collaborator

apjanke commented Dec 1, 2024

Pulled the reliable symlink creation code in 9eba758.

@apjanke
Copy link
Collaborator

apjanke commented Dec 1, 2024

Working on the make man cleanup over in #72 and branch cleaner-make-man.

@apjanke
Copy link
Collaborator

apjanke commented Dec 1, 2024

Pulled the make man cleanup in 29ae85c, with followup in a337a30.

I think that's everything except for the actual "install doc files" changes, which I'm going to leave targeted for 3.9.0, since that's a larger user-visible change.

@apjanke
Copy link
Collaborator

apjanke commented Dec 1, 2024

The CI runs are working, at least on branches on the main repo, and already catching some bugs and sending me notifications. That's useful. Thanks for putting this together!

Example email notification:

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Make stuff better!

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants