[CI:DOCS] man-page checker: include --format (Go templates)
Very belated successor to #14046. I don't know why this is so important to me. Probably because we're doing a halfhearted sloppy job of documenting, and new options get added, and not documented, and that's just wrong. I've given up on documenting internal structs. This iteration has a $Format_Exceptions table defined at the top of the xref script, enumerating a hardcoded defined set of podman commands and fields that should remain undocumented. This iteration also forgives completely-undocumented formats. If podman-foo has a --format, but podman-foo.1.md does not list *any* valid fields, the script warns but does not fail. This at least is better than documenting a random mix of fields. This version of the xref script is much slower: 10s vs 4. I think we can live with that in a CI-only script. Signed-off-by: Ed Santiago <santiago@redhat.com>
This commit is contained in:
		
							parent
							
								
									d1fd399455
								
							
						
					
					
						commit
						4334135491
					
				| 
						 | 
				
			
			@ -61,12 +61,12 @@ Valid placeholders for the Go template are listed below:
 | 
			
		|||
 | 
			
		||||
| **Placeholder** | **Description**                        |
 | 
			
		||||
| --------------- | -------------------------------------- |
 | 
			
		||||
| .Unit           | Name of the systemd unit               |
 | 
			
		||||
| .ContainerName  | Name of the container                  |
 | 
			
		||||
| .ContainerID    | ID of the container                    |
 | 
			
		||||
| .Container      | ID and name of the container           |
 | 
			
		||||
| .ContainerID    | ID of the container                    |
 | 
			
		||||
| .ContainerName  | Name of the container                  |
 | 
			
		||||
| .Image          | Name of the image                      |
 | 
			
		||||
| .Policy         | Auto-update policy of the container    |
 | 
			
		||||
| .Unit           | Name of the systemd unit               |
 | 
			
		||||
| .Updated        | Update status: true,false,failed       |
 | 
			
		||||
 | 
			
		||||
#### **--rollback**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,6 +38,7 @@ Valid placeholders for the Go template are listed below:
 | 
			
		|||
| .HostsPath           | Path to container /etc/hosts file (string)         |
 | 
			
		||||
| .ID                  | Container ID (full 64-char hash)                   |
 | 
			
		||||
| .Image               | Container image ID (64-char hash)                  |
 | 
			
		||||
| .ImageDigest         | Container image digest (sha256:+64-char hash)      |
 | 
			
		||||
| .ImageName           | Container image name (string)                      |
 | 
			
		||||
| .IsInfra             | Is this an infra container? (string: true/false)   |
 | 
			
		||||
| .IsService           | Is this a service container? (string: true/false)  |
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -101,19 +101,20 @@ In the case where an ID is used, the ID may be in its full or shortened form.  T
 | 
			
		|||
 | 
			
		||||
Format the output to JSON Lines or using the given Go template.
 | 
			
		||||
 | 
			
		||||
| **Placeholder**    | **Description**                               |
 | 
			
		||||
|--------------------|-----------------------------------------------|
 | 
			
		||||
| .Attributes        | created_at, _by, labels, and more (map[])     |
 | 
			
		||||
| .ContainerExitCode | Exit code (int)                               |
 | 
			
		||||
| .Details ...       | Internal structure, not actually useful       |
 | 
			
		||||
| .HealthStatus      | Health Status (string)                        |
 | 
			
		||||
| .ID                | Container ID (full 64-bit SHA)                |
 | 
			
		||||
| .Image             | Name of image being run (string)              |
 | 
			
		||||
| .Name              | Container name (string)                       |
 | 
			
		||||
| .Network           | Name of network being used (string)           |
 | 
			
		||||
| .Status            | Event status (e.g., create, start, died, ...) |
 | 
			
		||||
| .Time              | Event timestamp (string)                      |
 | 
			
		||||
| .Type              | Event type (e.g., image, container, pod, ...) |
 | 
			
		||||
| **Placeholder**       | **Description**                               |
 | 
			
		||||
|-----------------------|-----------------------------------------------|
 | 
			
		||||
| .Attributes           | created_at, _by, labels, and more (map[])     |
 | 
			
		||||
| .ContainerExitCode    | Exit code (int)                               |
 | 
			
		||||
| .ContainerInspectData | Payload of the container's inspect            |
 | 
			
		||||
| .HealthStatus         | Health Status (string)                        |
 | 
			
		||||
| .ID                   | Container ID (full 64-bit SHA)                |
 | 
			
		||||
| .Image                | Name of image being run (string)              |
 | 
			
		||||
| .Name                 | Container name (string)                       |
 | 
			
		||||
| .Network              | Name of network being used (string)           |
 | 
			
		||||
| .PodID                | ID of pod associated with container, if any   |
 | 
			
		||||
| .Status               | Event status (e.g., create, start, died, ...) |
 | 
			
		||||
| .Time                 | Event timestamp (string)                      |
 | 
			
		||||
| .Type                 | Event type (e.g., image, container, pod, ...) |
 | 
			
		||||
 | 
			
		||||
#### **--help**
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,16 +25,16 @@ Alter the output for a format like 'json' or a Go template.
 | 
			
		|||
 | 
			
		||||
Valid placeholders for the Go template are listed below:
 | 
			
		||||
 | 
			
		||||
| **Placeholder** | **Description**                                                               |
 | 
			
		||||
| --------------- | ----------------------------------------------------------------------------- |
 | 
			
		||||
| .ID             | Image ID                                                                      |
 | 
			
		||||
| .Created        | if --human, time elapsed since creation, otherwise time stamp of creation     |
 | 
			
		||||
| .CreatedAt      | Time when the image layer was created                |
 | 
			
		||||
| .CreatedBy      | Command used to create the layer                     |
 | 
			
		||||
| .CreatedSince   | Elapsed time since the image layer was created       |
 | 
			
		||||
| .Size           | Size of layer on disk                                |
 | 
			
		||||
| .Comment        | Comment for the layer                                |
 | 
			
		||||
| .Tags           | Image tags |
 | 
			
		||||
| **Placeholder**        | **Description**                                                           |
 | 
			
		||||
|------------------------|---------------------------------------------------------------------------|
 | 
			
		||||
| .ID                    | Image ID                                                                  |
 | 
			
		||||
| .Created               | if --human, time elapsed since creation, otherwise time stamp of creation |
 | 
			
		||||
| .CreatedAt             | Time when the image layer was created                                     |
 | 
			
		||||
| .CreatedBy             | Command used to create the layer                                          |
 | 
			
		||||
| .CreatedSince          | Elapsed time since the image layer was created                            |
 | 
			
		||||
| .Size                  | Size of layer on disk                                                     |
 | 
			
		||||
| .Comment               | Comment for the layer                                                     |
 | 
			
		||||
| .Tags                  | Image tags                                                                |
 | 
			
		||||
 | 
			
		||||
#### **--help**, **-h**
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,7 +88,6 @@ Valid placeholders for the Go template are listed below:
 | 
			
		|||
| .History        | History of the image layer                                 |
 | 
			
		||||
| .ID             | Image ID (truncated)                                       |
 | 
			
		||||
| .Id             | Image ID (full SHA)                                        |
 | 
			
		||||
| .ImageSummary   | Internal data structure, not actually useful               |
 | 
			
		||||
| .IsDangling     | Is image dangling? (true/false)                            |
 | 
			
		||||
| .IsReadOnly     | Is unage read-only? (true/false)                           |
 | 
			
		||||
| .Labels         | map[] of labels                                            |
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,20 +14,21 @@ Display the (JSON format) network configuration.
 | 
			
		|||
 | 
			
		||||
Pretty-print networks to JSON or using a Go template.
 | 
			
		||||
 | 
			
		||||
| **Placeholder**   | **Description**                           |
 | 
			
		||||
| ----------------- | ----------------------------------------- |
 | 
			
		||||
| .ID               | Network ID                                |
 | 
			
		||||
| .Name             | Network name                              |
 | 
			
		||||
| .Driver           | Network driver                            |
 | 
			
		||||
| .Labels           | Network labels                            |
 | 
			
		||||
| .Options          | Network options                           |
 | 
			
		||||
| .IPAMOptions      | Network ipam options                      |
 | 
			
		||||
| .Created          | Timestamp when the network was created    |
 | 
			
		||||
| .Internal         | Network is internal (boolean)             |
 | 
			
		||||
| .IPv6Enabled      | Network has ipv6 subnet (boolean)         |
 | 
			
		||||
| .DNSEnabled       | Network has dns enabled (boolean)         |
 | 
			
		||||
| .NetworkInterface | Name of the network interface on the host |
 | 
			
		||||
| .Subnets          | List of subnets on this network           |
 | 
			
		||||
| **Placeholder**    | **Description**                           |
 | 
			
		||||
|--------------------|-------------------------------------------|
 | 
			
		||||
| .ID                | Network ID                                |
 | 
			
		||||
| .Name              | Network name                              |
 | 
			
		||||
| .Driver            | Network driver                            |
 | 
			
		||||
| .Labels            | Network labels                            |
 | 
			
		||||
| .Options           | Network options                           |
 | 
			
		||||
| .IPAMOptions       | Network ipam options                      |
 | 
			
		||||
| .Created           | Timestamp when the network was created    |
 | 
			
		||||
| .Internal          | Network is internal (boolean)             |
 | 
			
		||||
| .IPv6Enabled       | Network has ipv6 subnet (boolean)         |
 | 
			
		||||
| .DNSEnabled        | Network has dns enabled (boolean)         |
 | 
			
		||||
| .NetworkDNSServers | Array of DNS servers used in this network |
 | 
			
		||||
| .NetworkInterface  | Name of the network interface on the host |
 | 
			
		||||
| .Subnets           | List of subnets on this network           |
 | 
			
		||||
 | 
			
		||||
## EXAMPLE
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,20 +42,21 @@ Change the default output format.  This can be of a supported type like 'json'
 | 
			
		|||
or a Go template.
 | 
			
		||||
Valid placeholders for the Go template are listed below:
 | 
			
		||||
 | 
			
		||||
| **Placeholder**   | **Description**                           |
 | 
			
		||||
| ----------------- | ----------------------------------------- |
 | 
			
		||||
| .ID               | Network ID                                |
 | 
			
		||||
| .Name             | Network name                              |
 | 
			
		||||
| .Driver           | Network driver                            |
 | 
			
		||||
| .Labels           | Network labels                            |
 | 
			
		||||
| .Options          | Network options                           |
 | 
			
		||||
| .IPAMOptions      | Network ipam options                      |
 | 
			
		||||
| .Created          | Timestamp when the network was created    |
 | 
			
		||||
| .Internal         | Network is internal (boolean)             |
 | 
			
		||||
| .IPv6Enabled      | Network has ipv6 subnet (boolean)         |
 | 
			
		||||
| .DNSEnabled       | Network has dns enabled (boolean)         |
 | 
			
		||||
| .NetworkInterface | Name of the network interface on the host |
 | 
			
		||||
| .Subnets          | List of subnets on this network           |
 | 
			
		||||
| **Placeholder**    | **Description**                           |
 | 
			
		||||
|--------------------|-------------------------------------------|
 | 
			
		||||
| .ID                | Network ID                                |
 | 
			
		||||
| .Name              | Network name                              |
 | 
			
		||||
| .Driver            | Network driver                            |
 | 
			
		||||
| .Labels            | Network labels                            |
 | 
			
		||||
| .Options           | Network options                           |
 | 
			
		||||
| .IPAMOptions       | Network ipam options                      |
 | 
			
		||||
| .Created           | Timestamp when the network was created    |
 | 
			
		||||
| .Internal          | Network is internal (boolean)             |
 | 
			
		||||
| .IPv6Enabled       | Network has ipv6 subnet (boolean)         |
 | 
			
		||||
| .DNSEnabled        | Network has dns enabled (boolean)         |
 | 
			
		||||
| .NetworkDNSServers | Array of DNS servers used in this network |
 | 
			
		||||
| .NetworkInterface  | Name of the network interface on the host |
 | 
			
		||||
| .Subnets           | List of subnets on this network           |
 | 
			
		||||
 | 
			
		||||
#### **--no-trunc**
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -77,17 +77,20 @@ Pretty-print containers to JSON or using a Go template
 | 
			
		|||
 | 
			
		||||
Valid placeholders for the Go template are listed below:
 | 
			
		||||
 | 
			
		||||
|   **Placeholder**   | **Description**                                                                                 |
 | 
			
		||||
| ------------------- | ----------------------------------------------------------------------------------------------- |
 | 
			
		||||
| .ID                 | Container ID                                                                                    |
 | 
			
		||||
| .Name               | Name of pod                                                                                     |
 | 
			
		||||
| .Status             | Status of pod                                                                                   |
 | 
			
		||||
| .Labels             | All the labels assigned to the pod                                                              |
 | 
			
		||||
| .NumberOfContainers | Show the number of containers attached to pod                                                   |
 | 
			
		||||
| .Cgroup             | Cgroup path of pod                                                                              |
 | 
			
		||||
| .Created            | Creation time of pod                                                                            |
 | 
			
		||||
| .InfraID            | Pod infra container ID                                                                          |
 | 
			
		||||
| .Networks           | Show all networks connected to the infra container                                              |
 | 
			
		||||
| **Placeholder**     | **Description**                                    |
 | 
			
		||||
|---------------------|----------------------------------------------------|
 | 
			
		||||
| .Cgroup             | Cgroup path of pod                                 |
 | 
			
		||||
| .ContainerIds       | Comma-separated list of container IDs in the pod   |
 | 
			
		||||
| .ContainerNames     | Comma-separated list of container names in the pod |
 | 
			
		||||
| .ContainerStatuses  | Comma-separated list of container statuses         |
 | 
			
		||||
| .Created            | Creation time of pod                               |
 | 
			
		||||
| .ID                 | Container ID                                       |
 | 
			
		||||
| .InfraID            | Pod infra container ID                             |
 | 
			
		||||
| .Labels             | All the labels assigned to the pod                 |
 | 
			
		||||
| .Name               | Name of pod                                        |
 | 
			
		||||
| .Networks           | Show all networks connected to the infra container |
 | 
			
		||||
| .NumberOfContainers | Show the number of containers attached to pod      |
 | 
			
		||||
| .Status             | Status of pod                                      |
 | 
			
		||||
 | 
			
		||||
#### **--help**, **-h**
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,22 +67,33 @@ Pretty-print containers to JSON or using a Go template
 | 
			
		|||
 | 
			
		||||
Valid placeholders for the Go template are listed below:
 | 
			
		||||
 | 
			
		||||
| **Placeholder** | **Description**                                  |
 | 
			
		||||
| --------------- | ------------------------------------------------ |
 | 
			
		||||
| .ID             | Container ID                                     |
 | 
			
		||||
| .Image          | Image Name/ID                                    |
 | 
			
		||||
| .ImageID        | Image ID                                         |
 | 
			
		||||
| .Command        | Quoted command used                              |
 | 
			
		||||
| .CreatedAt      | Creation time for container                      |
 | 
			
		||||
| .RunningFor     | Time elapsed since container was started         |
 | 
			
		||||
| .Status         | Status of container                              |
 | 
			
		||||
| .Pod            | Pod the container is associated with             |
 | 
			
		||||
| .Ports          | Exposed ports                                    |
 | 
			
		||||
| .Size           | Size of container                                |
 | 
			
		||||
| .Names          | Name of container                                |
 | 
			
		||||
| .Networks       | Show all networks connected to the container     |
 | 
			
		||||
| .Labels         | All the labels assigned to the container         |
 | 
			
		||||
| .Mounts         | Volumes mounted in the container                 |
 | 
			
		||||
| **Placeholder**    | **Description**                              |
 | 
			
		||||
|--------------------|----------------------------------------------|
 | 
			
		||||
| .AutoRemove        | If true, container will be removed on exit   |
 | 
			
		||||
| .Command           | Quoted command used                          |
 | 
			
		||||
| .Created           | Creation time for container, Y-M-D H:M:S     |
 | 
			
		||||
| .CreatedAt         | Creation time for container (same as above)  |
 | 
			
		||||
| .CreatedHuman      | Creation time, relative                      |
 | 
			
		||||
| .ExitCode          | Container exit code                          |
 | 
			
		||||
| .Exited            | "true" if container has exited               |
 | 
			
		||||
| .ExitedAt          | Time (epoch seconds) that container exited   |
 | 
			
		||||
| .ID                | Container ID                                 |
 | 
			
		||||
| .Image             | Image Name/ID                                |
 | 
			
		||||
| .ImageID           | Image ID                                     |
 | 
			
		||||
| .IsInfra           | "true" if infra container                    |
 | 
			
		||||
| .Labels            | All the labels assigned to the container     |
 | 
			
		||||
| .Mounts            | Volumes mounted in the container             |
 | 
			
		||||
| .Names             | Name of container                            |
 | 
			
		||||
| .Networks          | Show all networks connected to the container |
 | 
			
		||||
| .Pid               | Process ID on host system                    |
 | 
			
		||||
| .Pod               | Pod the container is associated with (SHA)   |
 | 
			
		||||
| .PodName           | Seems to be empty no matter what             |
 | 
			
		||||
| .Ports             | Exposed ports                                |
 | 
			
		||||
| .RunningFor        | Time elapsed since container was started     |
 | 
			
		||||
| .Size              | Size of container                            |
 | 
			
		||||
| .StartedAt         | Time (epoch seconds) the container started   |
 | 
			
		||||
| .State             | Human-friendly description of ctr state      |
 | 
			
		||||
| .Status            | Status of container                          |
 | 
			
		||||
 | 
			
		||||
#### **--help**, **-h**
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,13 +20,14 @@ Secrets can be queried individually by providing their full name or a unique par
 | 
			
		|||
Format secret output using Go template.
 | 
			
		||||
 | 
			
		||||
| **Placeholder**          | **Description**                                                   |
 | 
			
		||||
| ------------------------ | ----------------------------------------------------------------- |
 | 
			
		||||
|--------------------------|-------------------------------------------------------------------|
 | 
			
		||||
| .CreatedAt               | When secret was created (relative timestamp, human-readable)      |
 | 
			
		||||
| .ID                      | ID of secret                                                      |
 | 
			
		||||
| .Spec                    | Details of secret                                                 |
 | 
			
		||||
| .Spec.Driver             | Driver info                                                       |
 | 
			
		||||
| .Spec.Driver.Name        | Driver name (string)                                              |
 | 
			
		||||
| .Spec.Driver.Options ... | Driver options (map of driver-specific options)                   |
 | 
			
		||||
| .Spec.Labels             | Labels for this secret                                            |
 | 
			
		||||
| .Spec.Name               | Name of secret                                                    |
 | 
			
		||||
| .UpdatedAt               | When secret was last updated (relative timestamp, human-readable) |
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,43 @@ my $Markdown_Path = "$Docs_Path/markdown";
 | 
			
		|||
# Global error count
 | 
			
		||||
my $Errs = 0;
 | 
			
		||||
 | 
			
		||||
# Table of exceptions for documenting fields in '--format {{.Foo}}'
 | 
			
		||||
#
 | 
			
		||||
# Autocomplete is wonderful, and it's even better when we document the
 | 
			
		||||
# existing options. Unfortunately, sometimes internal structures get
 | 
			
		||||
# exposed that are of no use to anyone and cannot be guaranteed. Avoid
 | 
			
		||||
# documenting those. This table lists those exceptions. Format is:
 | 
			
		||||
#
 | 
			
		||||
#      foo       .Bar
 | 
			
		||||
#
 | 
			
		||||
# ...such that "podman foo --format '{{.Bar}}'" will not be documented.
 | 
			
		||||
#
 | 
			
		||||
my $Format_Exceptions = <<'END_EXCEPTIONS';
 | 
			
		||||
# Deep internal structs; pretty sure these are permanent exceptions
 | 
			
		||||
events       .Details
 | 
			
		||||
history      .ImageHistoryLayer
 | 
			
		||||
images       .ImageSummary
 | 
			
		||||
network-ls   .Network
 | 
			
		||||
 | 
			
		||||
# FIXME: this one, maybe? But someone needs to write the text
 | 
			
		||||
machine-list    .Starting
 | 
			
		||||
 | 
			
		||||
# No clue what these are. Some are just different-case dups of others.
 | 
			
		||||
pod-ps  .Containers .Id .InfraId .ListPodsReport .Namespace
 | 
			
		||||
ps      .Cgroup .CGROUPNS .IPC .ListContainer .MNT .Namespaces .NET .PIDNS .User .USERNS .UTS
 | 
			
		||||
 | 
			
		||||
# I think .Destination is an internal struct, but .IsMachine maybe needs doc?
 | 
			
		||||
system-connection-list .Destination .IsMachine
 | 
			
		||||
END_EXCEPTIONS
 | 
			
		||||
 | 
			
		||||
my %Format_Exceptions;
 | 
			
		||||
for my $line (split "\n", $Format_Exceptions) {
 | 
			
		||||
    $line =~ s/#.*$//;                  # strip comments
 | 
			
		||||
    next unless $line;                  # skip empty lines
 | 
			
		||||
    my ($subcommand, @fields) = split(' ', $line);
 | 
			
		||||
    $Format_Exceptions{"podman-$subcommand"} = \@fields;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# END   user-customizable section
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -126,14 +163,38 @@ sub main {
 | 
			
		|||
sub xref_by_help {
 | 
			
		||||
    my ($help, $man, @subcommand) = @_;
 | 
			
		||||
 | 
			
		||||
  OPTION:
 | 
			
		||||
    for my $k (sort keys %$help) {
 | 
			
		||||
        if (exists $man->{$k}) {
 | 
			
		||||
            if (ref $help->{$k}) {
 | 
			
		||||
                # This happens when 'podman foo --format' offers
 | 
			
		||||
                # autocompletion that looks like a Go template, but those
 | 
			
		||||
                # template options aren't documented in the man pages.
 | 
			
		||||
                if ($k eq '--format' && ! ref($man->{$k})) {
 | 
			
		||||
                    warn "$ME: 'podman @subcommand': --format options are available through autocomplete, but are not documented in $man->{_path}\n";
 | 
			
		||||
 | 
			
		||||
                    # FIXME: don't make this an error... yet.
 | 
			
		||||
                    # ++$Errs;
 | 
			
		||||
                    next OPTION;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                xref_by_help($help->{$k}, $man->{$k}, @subcommand, $k);
 | 
			
		||||
            }
 | 
			
		||||
            # Otherwise, non-ref is leaf node such as a --option
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            # Not documented in man. However, handle '...' as a special case
 | 
			
		||||
            # in formatting strings. E.g., 'podman info .Host' is documented
 | 
			
		||||
            # in the man page as '.Host ...' to indicate that the subfields
 | 
			
		||||
            # are way too many to list individually.
 | 
			
		||||
            my $k_copy = $k;
 | 
			
		||||
            while ($k_copy =~ s/\.[^.]+$//) {
 | 
			
		||||
                if (($man->{$k_copy}||'') eq '...') {
 | 
			
		||||
                    next OPTION;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            # Nope, it's not that case.
 | 
			
		||||
            my $man = $man->{_path} || 'man';
 | 
			
		||||
            warn "$ME: 'podman @subcommand --help' lists '$k', which is not in $man\n";
 | 
			
		||||
            ++$Errs;
 | 
			
		||||
| 
						 | 
				
			
			@ -152,11 +213,23 @@ sub xref_by_man {
 | 
			
		|||
    my ($help, $man, @subcommand) = @_;
 | 
			
		||||
 | 
			
		||||
    # FIXME: this generates way too much output
 | 
			
		||||
  KEYWORD:
 | 
			
		||||
    for my $k (grep { $_ ne '_path' } sort keys %$man) {
 | 
			
		||||
        if ($k eq '--format' && ref($man->{$k}) && ! ref($help->{$k})) {
 | 
			
		||||
            warn "$ME: 'podman @subcommand': --format options documented in man page, but not available via autocomplete\n";
 | 
			
		||||
            next KEYWORD;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (exists $help->{$k}) {
 | 
			
		||||
            if (ref $man->{$k}) {
 | 
			
		||||
                xref_by_man($help->{$k}, $man->{$k}, @subcommand, $k);
 | 
			
		||||
            }
 | 
			
		||||
            elsif ($k =~ /^-/) {
 | 
			
		||||
                # This is OK: we don't recurse into options
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                # FIXME: should never get here, but we do. Figure it out later.
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        elsif ($k ne '--help' && $k ne '-h') {
 | 
			
		||||
            my $man = $man->{_path} || 'man';
 | 
			
		||||
| 
						 | 
				
			
			@ -254,15 +327,39 @@ sub podman_help {
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
        elsif ($section eq 'options') {
 | 
			
		||||
            my $opt = '';
 | 
			
		||||
 | 
			
		||||
            # Handle '--foo' or '-f, --foo'
 | 
			
		||||
            if ($line =~ /^\s{1,10}(--\S+)\s/) {
 | 
			
		||||
                print "> podman @_ $1\n"                        if $debug;
 | 
			
		||||
                $help{$1} = 1;
 | 
			
		||||
                $opt = $1;
 | 
			
		||||
                $help{$opt} = 1;
 | 
			
		||||
            }
 | 
			
		||||
            elsif ($line =~ /^\s{1,10}(-\S),\s+(--\S+)\s/) {
 | 
			
		||||
                print "> podman @_ $1, $2\n"                    if $debug;
 | 
			
		||||
                $help{$1} = $help{$2} = 1;
 | 
			
		||||
                $opt = $2;
 | 
			
		||||
                $help{$1} = $help{$opt} = 1;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            # Special case for --format: run podman with autocomplete.
 | 
			
		||||
            # If that lists one or more '{{.Foo}}' or '{{.Foo.' entries
 | 
			
		||||
            # (indicating terminal or nonterminal nodes respectively)
 | 
			
		||||
            # convert our option data structure from scalar (indicating
 | 
			
		||||
            # that we just cross-check for existence in the man page)
 | 
			
		||||
            # to hashref (indicating that we recurse down and cross-check
 | 
			
		||||
            # each individual param).
 | 
			
		||||
            if ($opt eq '--format') {
 | 
			
		||||
                my @completions = _completions(@_, '--format', '{{.');
 | 
			
		||||
                for my $c (@completions) {
 | 
			
		||||
                    if ($c =~ /^\{\{(\.\S+)(\.|\}\})$/) {
 | 
			
		||||
                        # First time through: convert to a hashref
 | 
			
		||||
                        $help{$opt} = {}   if ! ref($help{$opt});
 | 
			
		||||
 | 
			
		||||
                        # Remember this param
 | 
			
		||||
                        $help{$opt}{$1} = 1;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
           }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    close $fh
 | 
			
		||||
| 
						 | 
				
			
			@ -420,6 +517,31 @@ sub podman_man {
 | 
			
		|||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            # --format does not always mean a Go format! E.g., push --format=oci
 | 
			
		||||
            if ($previous_flag eq '--format') {
 | 
			
		||||
                # ...but if there's a table like '| .Foo | blah blah |'
 | 
			
		||||
                # then it's definitely a Go template. '.Foo ...' (three dots)
 | 
			
		||||
                # indicates that .Foo includes a number of subfields .Foo.Xxx,
 | 
			
		||||
                # .Foo.Yyy too numerous to list individually in man pages.
 | 
			
		||||
                #                   1     12   3      32
 | 
			
		||||
                if ($line =~ /^\|\s+(\.\S+)(\s+(\.\.\.))?\s+\|/) {
 | 
			
		||||
                    my ($format, $etc) = ($1, $3);
 | 
			
		||||
 | 
			
		||||
                    # Confirmed: we have a table with '.Foo' strings, so
 | 
			
		||||
                    # this is a Go template. Override previous (scalar)
 | 
			
		||||
                    # setting of the --format flag with a hash, indicating
 | 
			
		||||
                    # that we will recursively cross-check each param.
 | 
			
		||||
                    if (! ref($man{$previous_flag})) {
 | 
			
		||||
                        $man{$previous_flag} = { _path => $subpath };
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    # ...and document this format option. $etc, if set,
 | 
			
		||||
                    # will be '...' which indicates that $format has
 | 
			
		||||
                    # too many subformats to document individually.
 | 
			
		||||
                    $man{$previous_flag}{$format} = $etc || 1;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        # It's easy to make mistakes in the SEE ALSO elements.
 | 
			
		||||
| 
						 | 
				
			
			@ -429,6 +551,13 @@ sub podman_man {
 | 
			
		|||
    }
 | 
			
		||||
    close $fh;
 | 
			
		||||
 | 
			
		||||
    # Done reading man page. If there are any '--format' exceptions defined
 | 
			
		||||
    # for this command, flag them as seen, and as '...' so we don't
 | 
			
		||||
    # complain about any sub-fields.
 | 
			
		||||
    if (my $fields = $Format_Exceptions{$command}) {
 | 
			
		||||
        $man{"--format"}{$_} = '...' for @$fields;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Special case: the 'image trust' man page tries hard to cover both set
 | 
			
		||||
    # and show, which means it ends up not being machine-readable.
 | 
			
		||||
    if ($command eq 'podman-image-trust') {
 | 
			
		||||
| 
						 | 
				
			
			@ -511,6 +640,45 @@ sub podman_rst {
 | 
			
		|||
    return \%rst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
##################
 | 
			
		||||
#  _completions  #  run podman __completeNoDesc, return list of completions
 | 
			
		||||
##################
 | 
			
		||||
sub _completions {
 | 
			
		||||
    my $kidpid = open my $podman_fh, '-|';
 | 
			
		||||
    if (! defined $kidpid) {
 | 
			
		||||
        die "$ME: Could not fork: $!\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ($kidpid == 0) {
 | 
			
		||||
        # We are the child
 | 
			
		||||
        close STDERR;
 | 
			
		||||
        exec $PODMAN, '__completeNoDesc', @_;
 | 
			
		||||
        die "$ME: Could not exec: $!\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # We are the parent
 | 
			
		||||
    my @completions;
 | 
			
		||||
    while (my $line = <$podman_fh>) {
 | 
			
		||||
        chomp $line;
 | 
			
		||||
        push @completions, $line;
 | 
			
		||||
 | 
			
		||||
        # Recursively expand Go templates, like '{{.Server.Os}}'
 | 
			
		||||
        if ($line =~ /^\{\{\..*\.$/) {
 | 
			
		||||
            my @cmd_copy = @_;          # clone of podman subcommands...
 | 
			
		||||
            pop @cmd_copy;              # ...so we can recurse with new format
 | 
			
		||||
            my @subcompletions = _completions(@cmd_copy, $line);
 | 
			
		||||
 | 
			
		||||
            # A huge number of deep fields are time-related. Don't document them.
 | 
			
		||||
            my @is_time = grep { /Nanosecond|UnixNano|YearDay/ } @subcompletions;
 | 
			
		||||
            push @completions, @subcompletions
 | 
			
		||||
                unless @is_time >= 3;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    close $podman_fh
 | 
			
		||||
        or warn "$ME: Error running podman __completeNoDesc @_\n";
 | 
			
		||||
    return @completions;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# END   data gathering
 | 
			
		||||
###############################################################################
 | 
			
		||||
# BEGIN sanity checking of SEE ALSO links
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue