-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathquery.go
180 lines (158 loc) · 5.2 KB
/
query.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Copyright (c) 2020, Ben Morgan. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
package main
import (
"fmt"
"strings"
"time"
"github.com/cassava/repoctl/internal/term"
"github.com/cassava/repoctl/pacman/aur"
"github.com/goulash/pr"
"github.com/spf13/cobra"
)
func init() {
MainCmd.AddCommand(queryCmd)
}
var queryCmd = &cobra.Command{
Use: "query [PKGNAME ...]",
Short: "Query package information from AUR",
Long: `Query package information from AUR.
This command queries AUR for the specified packages and returns as much
information on these packages as AUR gives us. The results are combined and
sorted alphabetically.
Note that this command is very similar to the results given from "search -i"
command, but it uses a different AUR request. This command shows the
following additional metadata:
- Groups
- Dependencies
- Make Dependencies
- Optional Dependencies
- Conflicts
- Provides
- Replaces
- Keywords
Metadata properties that are empty are not shown.
Running this command without any arguments is not an error. (This means you
can use another command to generate a list of packages to query and if the
list has no elements, that's ok.)
`,
Example: ` repoctl query firefox56 flirc-bin
repoctl query $(repoctl search -q firefox)
`,
DisableFlagsInUseLine: true,
ValidArgsFunction: completeAURPackageNames,
RunE: func(cmd *cobra.Command, args []string) error {
exceptQuiet()
pkgs, err := aur.ReadAll(args)
if err != nil {
nfe, ok := err.(*aur.NotFoundError)
if !ok {
return err
}
for _, n := range nfe.Names {
term.Warnf("Warning: unknown package %s\n", n)
}
}
// Get the terminal width and fallback to a massive value if it's not
// available. This prevents wrapping and lets us for example grep the
// output better.
terminalWidth := pr.StdoutTerminalWidth()
if terminalWidth <= 0 {
// FIXME: This is a hack
terminalWidth = 1024
}
// Print the list
pkgset := make(map[string]bool)
for _, p := range pkgs {
// Only add unique names to the list of packages
if pkgset[p.Name] {
continue
}
pkgset[p.Name] = true
term.Printf("@{!m}aur/@{!w}%s @{!g}%s @{r}(%d)\n@|", p.Name, p.Version, p.NumVotes)
term.Printf("@.%s\n", formatAURPackageInfo(p, terminalWidth))
}
return nil
},
}
func formatAURPackageInfo(p *aur.Package, hspace int) string {
// We want formatList to give us something like this:
// Depends: package package package package package
// package package package package
wrap := func(xs []string, prefixLen int) string {
var buf strings.Builder
n := prefixLen
for i := 0; i < len(xs); i++ {
x := xs[i]
k := len(x)
if n+k+1 > hspace && n != prefixLen {
// If n == prefixLen, then that means we are at the beginning of the line,
// and we still don't have enough space. We'll just have to deal with it.
// A possible optimization here would be to try to reduce prefixLen and
// see if it would fit then. But that can be done some other day.
// Add a newline and the prefix
buf.WriteRune('\n')
buf.WriteString(strings.Repeat(" ", prefixLen))
n = prefixLen
}
if n != prefixLen {
buf.WriteRune(' ')
}
buf.WriteString(x)
n += k + 1
}
return buf.String()
}
var buf strings.Builder
fmt.Fprintf(&buf, " Name: %s\n", p.Name)
if p.PackageBase != p.Name {
fmt.Fprintf(&buf, " Base Name: %s\n", p.PackageBase)
}
fmt.Fprintf(&buf, " Version: %s\n", p.Version)
fmt.Fprintf(&buf, " Description: %s\n", wrap(strings.Split(p.Description, " "), 17))
if len(p.URL) != 0 {
fmt.Fprintf(&buf, " URL: %s\n", p.URL)
}
// The following is not available from the information we get when using the
// search API, but might be useful in the future.
//
if len(p.License) > 0 {
fmt.Fprintf(&buf, " Licenses: %s\n", wrap(p.License, 14))
}
if len(p.Groups) > 0 {
fmt.Fprintf(&buf, " Groups: %s\n", wrap(p.Groups, 14))
}
if len(p.Provides) > 0 {
fmt.Fprintf(&buf, " Provides: %s\n", wrap(p.Provides, 14))
}
if len(p.Conflicts) > 0 {
fmt.Fprintf(&buf, " Conflicts: %s\n", wrap(p.Conflicts, 15))
}
if len(p.Replaces) > 0 {
fmt.Fprintf(&buf, " Replaces: %s\n", wrap(p.Replaces, 14))
}
if len(p.Depends) > 0 {
fmt.Fprintf(&buf, " Dependencies: %s\n", wrap(p.Depends, 16))
}
if len(p.OptDepends) > 0 {
fmt.Fprintf(&buf, " Optional Dependencies:\n")
for _, d := range p.OptDepends {
fmt.Fprintf(&buf, " %s\n", d)
}
}
if len(p.MakeDepends) > 0 {
fmt.Fprintf(&buf, " Build Dependencies: %s\n", wrap(p.MakeDepends, 15))
}
if len(p.Keywords) > 0 {
fmt.Fprintf(&buf, " Keywords: %s\n", wrap(p.Keywords, 14))
}
fmt.Fprintf(&buf, " Snapshot URL: %s%s\n", "https://aur.archlinux.org", p.URLPath)
fmt.Fprintf(&buf, " Maintainer: %s\n", p.Maintainer)
fmt.Fprintf(&buf, " Votes: %d\n", p.NumVotes)
fmt.Fprintf(&buf, " Popularity: %f\n", p.Popularity)
fmt.Fprintf(&buf, " First Submitted: %s\n", time.Unix(int64(p.FirstSubmitted), 0))
fmt.Fprintf(&buf, " Last Updated: %s\n", time.Unix(int64(p.LastModified), 0))
fmt.Fprintf(&buf, " Out-Of-Date: %v", p.OutOfDate != 0)
return buf.String()
}