-
Notifications
You must be signed in to change notification settings - Fork 0
/
rust.go
125 lines (104 loc) · 3.47 KB
/
rust.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
// Copyright 2022 The Firefly Authors.
//
// Use of this source code is governed by a BSD 3-clause
// license that can be found in the LICENSE file.
package vendeps
import (
"context"
"fmt"
"log"
"golang.org/x/mod/semver"
"firefly-os.dev/tools/cratesio"
)
// FetchRustCrate downloads a Rust crate using the
// crates.io API.
func FetchRustCrate(ctx context.Context, crate *RustCrate, dir string) error {
data, err := cratesio.Lookup(ctx, crate.Name)
if err != nil {
return err
}
for _, version := range data.Versions {
if version.Number == crate.Version {
_, ok := AcceptableLicense(version.License)
if !ok {
return fmt.Errorf("cannot use Rust crate %s %s: license %q is unacceptable", crate.Name, crate.Version, version.License)
}
return cratesio.Download(ctx, version, dir)
}
}
return fmt.Errorf("failed to find download path for Rust crate %s %s", crate.Name, crate.Version)
}
// UpdateRustCrate checks a Rust crate for updates,
// using the crates.io API.
func UpdateRustCrate(ctx context.Context, crate *UpdateDep) (updated bool, err error) {
data, err := cratesio.Lookup(ctx, crate.Name)
if err != nil {
return false, err
}
current := semver.Canonical("v" + *crate.Version)
if current == "" {
return false, fmt.Errorf("Rust crate %s has an invalid version %q", crate.Name, *crate.Version)
}
yanked := false
ignoredMajor := false
for _, version := range data.Versions {
// Check that the version is canonical.
// If not, we log it and continue. We
// could return an error, but that feels
// likely to be more annoying than helpful.
next := semver.Canonical("v" + version.Number)
if next == "" {
log.Printf("WARN: Rust crate %s returned invalid version %q", crate.Name, version.Number)
continue
}
cmp := semver.Compare(current, next)
if cmp == 0 {
if version.Yanked {
// We keep going to find which version
// we should downgrade to.
yanked = true
continue
}
// We're already up to date.
return false, nil
}
// Ignore yanked versions, other than the
// current version. If that is yanked, we
// need to downgrade (see above).
if version.Yanked {
continue
}
// We often won't want to update to a
// higher major version if we're already
// on a stable version (one with a major
// version larger than zero). However,
// in case we do, we log the largest
// version we see with a larger major
// version.
if MajorUpdate(current, next) {
if !ignoredMajor {
ignoredMajor = true
fmt.Printf("Ignored Rust crate %s major update from %s to %s.\n", crate.Name, *crate.Version, version.Number)
}
continue
}
// If we see an older version and the
// current version has been yanked, we
// need to downgrade.
if cmp == +1 {
if yanked {
fmt.Printf("Downgraded Rust crate %s from %s (which has been yanked) to %s.\n", crate.Name, *crate.Version, version.Number)
*crate.Version = version.Number
return true, nil
}
return false, fmt.Errorf("Rust crate %s returned no data for the current version %s", crate.Name, *crate.Version)
}
fmt.Printf("Upgraded Rust crate %s from %s to %s.\n", crate.Name, *crate.Version, version.Number)
*crate.Version = version.Number
return true, nil
}
if yanked {
return false, fmt.Errorf("Rust crate %s returned no viable versions (current version %s is yanked)", crate.Name, *crate.Version)
}
return false, fmt.Errorf("Rust crate %s returned no viable versions (current version %s missing)", crate.Name, *crate.Version)
}