1
1
use std:: {
2
2
cmp:: Ordering ,
3
+ collections:: HashSet ,
3
4
fmt:: Display ,
4
5
io:: { Write , stdout} ,
5
6
path:: PathBuf ,
@@ -12,10 +13,10 @@ use dialoguer::console::style;
12
13
use oma_pm:: {
13
14
apt:: { AptConfig , OmaApt , OmaAptArgs } ,
14
15
matches:: { GetArchMethod , PackagesMatcher } ,
15
- oma_apt:: { Package , Version } ,
16
+ oma_apt:: { BaseDep , Package , Version } ,
16
17
pkginfo:: OmaDepType ,
17
18
} ;
18
- use tracing:: debug;
19
+ use tracing:: { debug, trace } ;
19
20
20
21
use crate :: {
21
22
CliExecuter , config:: Config , error:: OutputError , fl, table:: oma_display_with_normal_output,
@@ -138,8 +139,14 @@ impl CliExecuter for Tree {
138
139
139
140
let matcher = PackagesMatcher :: builder ( )
140
141
. cache ( & apt. cache )
141
- . native_arch ( GetArchMethod :: SpecifySysroot ( & sysroot) )
142
- . build ( ) ;
142
+ . native_arch ( GetArchMethod :: SpecifySysroot ( & sysroot) ) ;
143
+
144
+ let matcher = if invert {
145
+ let matcher = matcher. filter_candidate ( false ) ;
146
+ matcher. build ( )
147
+ } else {
148
+ matcher. build ( )
149
+ } ;
143
150
144
151
let ( pkgs, no_result) =
145
152
matcher. match_pkgs_and_versions ( packages. iter ( ) . map ( |x| x. as_str ( ) ) ) ?;
@@ -164,6 +171,9 @@ impl CliExecuter for Tree {
164
171
limit,
165
172
)
166
173
} else {
174
+ if !p. version_raw . is_installed ( ) {
175
+ continue ;
176
+ }
167
177
reverse_dep_tree (
168
178
PkgWrapper {
169
179
package : Package :: new ( & apt. cache , p. raw_pkg ) ,
@@ -267,6 +277,7 @@ fn reverse_dep_tree<'a>(
267
277
limit : u8 ,
268
278
) -> TermTree < PkgWrapper < ' a > > {
269
279
let pkg_clone = pkg. package . clone ( ) ;
280
+ let pkg_installed = pkg_clone. installed ( ) . unwrap ( ) ;
270
281
let rdep = pkg_clone. rdepends ( ) ;
271
282
272
283
let mut res = TermTree :: new ( pkg) ;
@@ -279,68 +290,54 @@ fn reverse_dep_tree<'a>(
279
290
let t = t. into ( ) ;
280
291
match t {
281
292
OmaDepType :: Depends | OmaDepType :: PreDepends | OmaDepType :: Recommends => {
293
+ let mut added = HashSet :: new ( ) ;
282
294
for deps in deps_group {
283
295
for dep in deps. iter ( ) {
284
- let Some ( pkg ) = apt. cache . get ( dep. name ( ) ) else {
285
- debug ! (
296
+ let Some ( dep_pkg ) = apt. cache . get ( dep. name ( ) ) else {
297
+ trace ! (
286
298
"dep {} does not exist on apt cache, will continue" ,
287
299
dep. name( )
288
300
) ;
289
301
continue ;
290
302
} ;
291
303
292
- let Some ( installed_version ) = pkg . installed ( ) else {
293
- debug ! ( "pkg {} is not installed, will continue" , pkg . name( ) ) ;
304
+ let Some ( dep_installed ) = dep_pkg . installed ( ) else {
305
+ trace ! ( "pkg {} is not installed, will continue" , dep_pkg . name( ) ) ;
294
306
continue ;
295
307
} ;
296
308
297
- let require_ver = Version :: new ( unsafe { dep. parent_ver ( ) } , & apt. cache ) ;
298
-
299
- let push = if let Some ( t) = dep. comp_type ( ) {
300
- let mut push = None ;
301
- let t = match t {
302
- ">" | ">>" => vec ! [ Ordering :: Greater ] ,
303
- "<" | "<<" => vec ! [ Ordering :: Less ] ,
304
- ">=" => vec ! [ Ordering :: Greater , Ordering :: Equal ] ,
305
- "<=" => vec ! [ Ordering :: Less , Ordering :: Equal ] ,
306
- "=" | "==" => vec ! [ Ordering :: Equal ] ,
307
- "!=" => {
308
- push = Some ( require_ver != installed_version) ;
309
- vec ! [ ]
310
- }
311
- "" => {
312
- push = Some ( true ) ;
313
- vec ! [ ]
314
- }
315
- x => unreachable ! ( "unsupported comp type {x}" ) ,
316
- } ;
317
-
318
- debug ! ( "{} {:?} {}" , dep. name( ) , t, require_ver) ;
319
-
320
- let cmp = & installed_version. cmp ( & require_ver) ;
321
-
322
- debug ! ( "{} {installed_version} {cmp:?} {require_ver}" , pkg. name( ) ) ;
323
-
324
- if push. is_none ( ) && t. contains ( cmp) {
325
- push = Some ( true )
326
- }
327
-
328
- debug ! ( "push = {push:?}" ) ;
329
-
330
- push. unwrap_or ( false )
331
- } else {
332
- true
333
- } ;
309
+ let key = format ! ( "{dep_pkg}-{}" , dep_installed. version( ) ) ;
310
+
311
+ if added. contains ( & key) {
312
+ continue ;
313
+ }
314
+
315
+ let pkg_rev_dep = dep_installed
316
+ . depends_map ( )
317
+ . values ( )
318
+ . flatten ( )
319
+ . flat_map ( |x| x. iter ( ) )
320
+ . find ( |dep| dep. name ( ) == pkg_clone. name ( ) ) ;
321
+
322
+ if pkg_rev_dep
323
+ . is_none_or ( |pkg_rev_dep| !is_result ( & pkg_installed, pkg_rev_dep) )
324
+ {
325
+ continue ;
326
+ }
327
+
328
+ let push = is_result ( & dep_installed, dep) ;
334
329
335
330
if !push {
336
331
continue ;
337
332
}
338
333
334
+ added. insert ( key) ;
335
+
339
336
res. push ( reverse_dep_tree (
340
337
PkgWrapper {
341
- package : pkg ,
338
+ package : dep_pkg ,
342
339
is_recommend : t == OmaDepType :: Recommends ,
343
- comp_and_version : Some ( installed_version . version ( ) . to_string ( ) ) ,
340
+ comp_and_version : Some ( dep_installed . version ( ) . to_string ( ) ) ,
344
341
} ,
345
342
apt,
346
343
depth + 1 ,
@@ -355,3 +352,45 @@ fn reverse_dep_tree<'a>(
355
352
356
353
res
357
354
}
355
+
356
+ fn is_result < ' a > ( pkg_installed : & Version < ' a > , dep : & BaseDep < ' _ > ) -> bool {
357
+ debug ! ( "{dep:#?}" ) ;
358
+
359
+ let Some ( required_ver) = dep. version ( ) else {
360
+ // 没有版本要求,说明要求总是符合
361
+ return true ;
362
+ } ;
363
+
364
+ let Ok ( required_ver) = required_ver. parse :: < debversion:: Version > ( ) else {
365
+ return false ;
366
+ } ;
367
+
368
+ let Ok ( installed) = pkg_installed. version ( ) . parse :: < debversion:: Version > ( ) else {
369
+ return false ;
370
+ } ;
371
+
372
+ if let Some ( t) = dep. comp_type ( ) {
373
+ let confirm = match t {
374
+ ">" | ">>" => |cmp| cmp == Ordering :: Greater ,
375
+ "<" | "<<" => |cmp| cmp == Ordering :: Less ,
376
+ ">=" => |cmp| [ Ordering :: Greater , Ordering :: Equal ] . contains ( & cmp) ,
377
+ "<=" => |cmp| [ Ordering :: Less , Ordering :: Equal ] . contains ( & cmp) ,
378
+ "=" | "==" => |cmp| Ordering :: Equal == cmp,
379
+ "!=" => |cmp| Ordering :: Equal != cmp,
380
+ "" => |_cmp| true ,
381
+ x => unreachable ! ( "unsupported comp type {x}" ) ,
382
+ } ;
383
+
384
+ debug ! ( "{} {t} {required_ver}" , dep. name( ) ) ;
385
+
386
+ let cmp = installed. cmp ( & required_ver) ;
387
+
388
+ debug ! ( "{} {pkg_installed} {cmp:?} {required_ver}" , dep. name( ) ) ;
389
+
390
+ if !confirm ( cmp) {
391
+ return false ;
392
+ }
393
+ }
394
+
395
+ true
396
+ }
0 commit comments