mirror of
https://github.com/containers/podman.git
synced 2025-08-06 11:32:07 +08:00
[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:
@ -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
|
||||
|
Reference in New Issue
Block a user