@@ -127,17 +127,17 @@ def intersect(self, other: Term) -> Term | None:
127
127
negative = other if self .is_positive () else self
128
128
129
129
return self ._non_empty_term (
130
- positive .constraint .difference (negative .constraint ), True
130
+ positive .constraint .difference (negative .constraint ), True , other
131
131
)
132
132
elif self .is_positive ():
133
133
# foo ^1.0.0 ∩ foo >=1.5.0 <3.0.0 → foo ^1.5.0
134
134
return self ._non_empty_term (
135
- self .constraint .intersect (other .constraint ), True
135
+ self .constraint .intersect (other .constraint ), True , other
136
136
)
137
137
else :
138
138
# not foo ^1.0.0 ∩ not foo >=1.5.0 <3.0.0 → not foo >=1.0.0 <3.0.0
139
139
return self ._non_empty_term (
140
- self .constraint .union (other .constraint ), False
140
+ self .constraint .union (other .constraint ), False , other
141
141
)
142
142
elif self .is_positive () != other .is_positive ():
143
143
return self if self .is_positive () else other
@@ -151,21 +151,45 @@ def difference(self, other: Term) -> Term | None:
151
151
"""
152
152
return self .intersect (other .inverse )
153
153
154
+ @staticmethod
155
+ def _is_direct_reference (dependency : Dependency ) -> bool :
156
+ return dependency .source_type in ["directory" , "file" , "url" , "git" ]
157
+
154
158
def _compatible_dependency (self , other : Dependency ) -> bool :
155
159
compatible : bool = (
156
160
self .dependency .is_root
157
161
or other .is_root
158
162
or other .is_same_package_as (self .dependency )
159
163
)
164
+
165
+ if (
166
+ not compatible
167
+ and not self ._is_direct_reference (self .dependency )
168
+ and self ._is_direct_reference (other )
169
+ ):
170
+ # we do this here to indicate direct reference dependencies are compatible
171
+ # with NVR dependencies
172
+ return (
173
+ self .dependency .complete_name == other .complete_name
174
+ and self .dependency .constraint .allows_all (other .constraint )
175
+ )
176
+
160
177
return compatible
161
178
162
179
def _non_empty_term (
163
- self , constraint : VersionConstraint , is_positive : bool
180
+ self , constraint : VersionConstraint , is_positive : bool , other : Term
164
181
) -> Term | None :
165
182
if constraint .is_empty ():
166
183
return None
167
184
168
- return Term (self .dependency .with_constraint (constraint ), is_positive )
185
+ # when creating a new term prefer direct-reference dependencies
186
+ dependency = (
187
+ other .dependency
188
+ if not self ._is_direct_reference (self .dependency )
189
+ and self ._is_direct_reference (other .dependency )
190
+ else self .dependency
191
+ )
192
+ return Term (dependency .with_constraint (constraint ), is_positive )
169
193
170
194
def __str__ (self ) -> str :
171
195
prefix = "not " if not self .is_positive () else ""
0 commit comments