1
+ use std:: collections:: HashSet ;
2
+
1
3
use cargo:: core:: registry:: PackageRegistry ;
2
4
use cargo:: core:: QueryKind ;
3
5
use cargo:: core:: Registry ;
4
6
use cargo:: core:: SourceId ;
7
+ use cargo:: ops:: Packages ;
5
8
use cargo:: util:: command_prelude:: * ;
6
9
7
10
pub fn cli ( ) -> clap:: Command {
8
11
clap:: Command :: new ( "xtask-unpublished" )
12
+ . arg_package_spec_simple ( "Package to inspect the published status" )
9
13
. arg (
10
14
opt (
11
15
"verbose" ,
@@ -76,14 +80,24 @@ fn config_configure(config: &mut Config, args: &ArgMatches) -> CliResult {
76
80
77
81
fn unpublished ( args : & clap:: ArgMatches , config : & mut cargo:: util:: Config ) -> cargo:: CliResult {
78
82
let ws = args. workspace ( config) ?;
83
+
84
+ let members_to_inspect: HashSet < _ > = {
85
+ let pkgs = args. packages_from_flags ( ) ?;
86
+ if let Packages :: Packages ( _) = pkgs {
87
+ HashSet :: from_iter ( pkgs. get_packages ( & ws) ?)
88
+ } else {
89
+ HashSet :: from_iter ( ws. members ( ) )
90
+ }
91
+ } ;
92
+
79
93
let mut results = Vec :: new ( ) ;
80
94
{
81
95
let mut registry = PackageRegistry :: new ( config) ?;
82
96
let _lock = config. acquire_package_cache_lock ( ) ?;
83
97
registry. lock_patches ( ) ;
84
98
let source_id = SourceId :: crates_io ( config) ?;
85
99
86
- for member in ws . members ( ) {
100
+ for member in members_to_inspect {
87
101
let name = member. name ( ) ;
88
102
let current = member. version ( ) ;
89
103
if member. publish ( ) == & Some ( vec ! [ ] ) {
@@ -92,11 +106,8 @@ fn unpublished(args: &clap::ArgMatches, config: &mut cargo::util::Config) -> car
92
106
}
93
107
94
108
let version_req = format ! ( "<={current}" ) ;
95
- let query = cargo:: core:: dependency:: Dependency :: parse (
96
- name,
97
- Some ( & version_req) ,
98
- source_id. clone ( ) ,
99
- ) ?;
109
+ let query =
110
+ cargo:: core:: dependency:: Dependency :: parse ( name, Some ( & version_req) , source_id) ?;
100
111
let possibilities = loop {
101
112
// Exact to avoid returning all for path/git
102
113
match registry. query_vec ( & query, QueryKind :: Exact ) {
@@ -106,51 +117,77 @@ fn unpublished(args: &clap::ArgMatches, config: &mut cargo::util::Config) -> car
106
117
std:: task:: Poll :: Pending => registry. block_until_ready ( ) ?,
107
118
}
108
119
} ;
109
- if let Some ( last) = possibilities. iter ( ) . map ( |s| s . version ( ) ) . max ( ) {
110
- if last != current {
111
- results . push ( (
112
- name . to_string ( ) ,
113
- Some ( last. to_string ( ) ) ,
114
- current . to_string ( ) ,
115
- ) ) ;
116
- } else {
117
- log :: trace! ( "{ name} {current} is published" ) ;
118
- }
119
- } else {
120
- results . push ( ( name . to_string ( ) , None , current . to_string ( ) ) ) ;
121
- }
120
+ let ( last, published ) = possibilities
121
+ . iter ( )
122
+ . map ( |s| s . version ( ) )
123
+ . max ( )
124
+ . map ( |last| ( last. to_string ( ) , last == current ) )
125
+ . unwrap_or ( ( "-" . to_string ( ) , false ) ) ;
126
+
127
+ results . push ( vec ! [
128
+ name. to_string ( ) ,
129
+ last ,
130
+ current . to_string ( ) ,
131
+ if published { "yes" } else { "no" } . to_string( ) ,
132
+ ] ) ;
122
133
}
123
134
}
135
+ results. sort ( ) ;
124
136
125
- if !results. is_empty ( ) {
126
- results. insert (
127
- 0 ,
128
- (
129
- "name" . to_owned ( ) ,
130
- Some ( "published" . to_owned ( ) ) ,
131
- "current" . to_owned ( ) ,
132
- ) ,
133
- ) ;
134
- results. insert (
135
- 1 ,
136
- (
137
- "====" . to_owned ( ) ,
138
- Some ( "=========" . to_owned ( ) ) ,
139
- "=======" . to_owned ( ) ,
140
- ) ,
141
- ) ;
142
- }
143
- for ( name, last, current) in results {
144
- if let Some ( last) = last {
145
- println ! ( "{name} {last} {current}" ) ;
146
- } else {
147
- println ! ( "{name} - {current}" ) ;
148
- }
137
+ if results. is_empty ( ) {
138
+ return Ok ( ( ) ) ;
149
139
}
150
140
141
+ results. insert (
142
+ 0 ,
143
+ vec ! [
144
+ "name" . to_owned( ) ,
145
+ "crates.io" . to_owned( ) ,
146
+ "local" . to_owned( ) ,
147
+ "published?" . to_owned( ) ,
148
+ ] ,
149
+ ) ;
150
+
151
+ output_table ( results) ;
152
+
151
153
Ok ( ( ) )
152
154
}
153
155
156
+ /// Outputs a markdown table like this.
157
+ ///
158
+ /// ```text
159
+ /// | name | crates.io | local | published? |
160
+ /// |------------------|-----------|--------|------------|
161
+ /// | cargo | 0.70.1 | 0.72.0 | no |
162
+ /// | cargo-platform | 0.1.2 | 0.1.2 | yes |
163
+ /// | cargo-util | - | 0.2.4 | no |
164
+ /// | crates-io | 0.36.0 | 0.36.0 | yes |
165
+ /// | home | - | 0.5.6 | no |
166
+ /// ```
167
+ fn output_table ( table : Vec < Vec < String > > ) {
168
+ let header = table. first ( ) . unwrap ( ) ;
169
+ let paddings = table. iter ( ) . fold ( vec ! [ 0 ; header. len( ) ] , |mut widths, row| {
170
+ for ( width, field) in widths. iter_mut ( ) . zip ( row) {
171
+ * width = usize:: max ( * width, field. len ( ) ) ;
172
+ }
173
+ widths
174
+ } ) ;
175
+
176
+ let print = |row : & [ _ ] | {
177
+ for ( field, pad) in row. iter ( ) . zip ( & paddings) {
178
+ print ! ( "| {field:pad$} " ) ;
179
+ }
180
+ println ! ( "|" ) ;
181
+ } ;
182
+
183
+ print ( header) ;
184
+
185
+ paddings. iter ( ) . for_each ( |fill| print ! ( "|-{:-<fill$}-" , "" ) ) ;
186
+ println ! ( "|" ) ;
187
+
188
+ table. iter ( ) . skip ( 1 ) . for_each ( |r| print ( r) ) ;
189
+ }
190
+
154
191
#[ test]
155
192
fn verify_cli ( ) {
156
193
cli ( ) . debug_assert ( ) ;
0 commit comments