-
Notifications
You must be signed in to change notification settings - Fork 13
/
down.go
181 lines (160 loc) · 5.46 KB
/
down.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
181
// Copyright (c) 2016, 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"
"os"
"github.com/cassava/repoctl/internal/term"
"github.com/cassava/repoctl/pacman/aur"
"github.com/cassava/repoctl/pacman/graph"
"github.com/cassava/repoctl/pacman/pkgutil"
"github.com/cassava/repoctl/repo"
"github.com/spf13/cobra"
)
var (
downDest string
downDryRun bool
downClobber bool
downExtract bool
downUpgrades bool
downAll bool
downRecurse bool
downOrder string
)
func init() {
MainCmd.AddCommand(downCmd)
downCmd.Flags().StringVarP(&downDest, "dest", "d", "", "output directory for tarballs")
downCmd.RegisterFlagCompletionFunc("dest", completeDirectory)
downCmd.Flags().BoolVarP(&downDryRun, "dry-run", "n", false, "don't download any packages")
downCmd.Flags().BoolVarP(&downClobber, "clobber", "l", false, "delete conflicting files and folders")
downCmd.Flags().BoolVarP(&downExtract, "extract", "e", true, "extract the downloaded tarballs")
downCmd.Flags().BoolVarP(&downUpgrades, "upgrades", "u", false, "download tarballs for all upgrades")
downCmd.Flags().BoolVarP(&downRecurse, "recursive", "r", false, "download any necessary dependencies")
downCmd.Flags().StringVarP(&downOrder, "order", "o", "", "write the order of compilation based on dependency tree into a file, implies -r")
downCmd.Flags().BoolVarP(&downAll, "all", "a", false, "download tarballs for all packages in database")
}
var downCmd = &cobra.Command{
Use: "down [PKGNAME ...]",
Aliases: []string{"download"},
Short: "Download and extract tarballs from AUR",
Long: `Download and extract tarballs from AUR for given packages.
Alternatively, all packages, or those with updates can be downloaded.
Options specified are additive, not exclusive.
By default, tarballs are deleted after being extracted, and are placed
in the current directory.
Packages can also be downloaded recursively, and the list that these
dependencies should be built can be saved. For example, to download
all updates to the repository and build them in approximately the
correct order:
repoctl down -o build-order.txt -u
for pkg in $(cat build-order.txt); do
(
cd $pkg
makepkg -si
ok=$?
if $ok; then
repoctl add -m *.pkg.tar*
cd ..
rm -rf $pkg
fi
)
done
You can just output the correct build order by adding the -n flag to
prevent downloading of tarballs.
Caveats:
1. Automatic dependency resolution does not currently handle version
resolution or library specifications, as noted in the Arch wiki at:
https://wiki.archlinux.org/index.php/PKGBUILD#Dependencies
2. Package dependencies are not resolved that are only "provided"
by other packages. Here, we currently print an "unknown package" warning.
For example, at the time of writing firefox56 requires mime-types.
This package does not exist, but is provided by other packages.
We can check this with:
repoctl query $(repoctl search -q mime-types)
Which leads us to see that mailcap-mime-types provides mime-types.
This caveat will be resolved in the future.
`,
Example: ` repoctl down -u
repoctl down -o build-order.txt -u`,
ValidArgsFunction: completeAURPackageNames,
PreRunE: func(cmd *cobra.Command, args []string) error {
if downAll || downUpgrades {
return ProfileInit(cmd, args)
}
return nil
},
PostRunE: func(cmd *cobra.Command, args []string) error {
if downAll || downUpgrades {
return ProfileTeardown(cmd, args)
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
// First, populate the initial list of packages to download.
var list []string
if downAll {
names, err := Repo.ReadAllNames(nil)
if err != nil {
return err
}
list = pkgutil.Map(names, pkgutil.PkgName)
} else if downUpgrades {
upgrades, err := Repo.FindUpgrades(nil, args...)
if err != nil {
return err
}
for _, u := range upgrades {
list = append(list, u.New.Name)
}
} else {
list = args
}
// If no dependencies are wanted, then get to it right away:
if !downRecurse && downOrder == "" {
// There's not much point to a try run here, but we should respect
// the option nevertheless.
if downDryRun {
return nil
}
return repo.Download(downDest, downExtract, downClobber, list)
}
// Otherwise, get the dependency list and download the packages:
aps, err := downDependencies(list)
if err != nil {
return err
}
// Don't download any packages if dry run is activated.
if downDryRun {
return nil
}
return repo.DownloadPackages(aps, downDest, downExtract, downClobber)
},
}
func downDependencies(packages []string) (aur.Packages, error) {
g, err := repo.DependencyGraph(packages)
if err != nil {
return nil, err
}
_, aps, ups := graph.Dependencies(g)
if downOrder != "" {
term.Debugf("Writing build-order to: %s\n", downOrder)
f, err := os.Create(downOrder)
if err != nil {
return nil, fmt.Errorf("cannot write build-order to %s: %w\n", downOrder, err)
}
for i := len(aps); i != 0; i-- {
fmt.Fprintln(f, aps[i-1].Name)
}
f.Close()
}
for _, u := range ups {
term.Warnf("Warning: unknown package %s\n", u)
iter := g.To(g.NodeWithName(u).ID())
for iter.Next() {
node := iter.Node().(*graph.Node)
term.Warnff(" Required by: %s\n", node.PkgName())
}
}
return aps, nil
}