@@ -95,22 +95,35 @@ def get_dep_tree(package_spec, verbose):
95
95
96
96
def find_deps (pkgs , dep_tree ):
97
97
"""Recursively resolve dependencies of the given package(s) and return them"""
98
+ MAX_PACKAGES = 1000
98
99
res = []
99
- for orig_pkg in pkgs :
100
- pkg = canonicalize_name (orig_pkg )
101
- matching_entries = [entry for entry in dep_tree
102
- if pkg in (entry ['package' ]['package_name' ], entry ['package' ]['key' ])]
103
- if not matching_entries :
100
+ next_pkgs = set (pkgs )
101
+ # Don't check any package multiple times to avoid infinite recursion
102
+ seen_pkgs = set ()
103
+ count = 0
104
+ while next_pkgs :
105
+ cur_pkgs = next_pkgs - seen_pkgs
106
+ seen_pkgs .update (cur_pkgs )
107
+ next_pkgs = set ()
108
+ for orig_pkg in cur_pkgs :
109
+ count += 1
110
+ if count > MAX_PACKAGES :
111
+ raise RuntimeError ("Aborting after checking %s packages. Possibly cycle detected!" % MAX_PACKAGES )
112
+ pkg = canonicalize_name (orig_pkg )
104
113
matching_entries = [entry for entry in dep_tree
105
- if orig_pkg in (entry ['package' ]['package_name' ], entry ['package' ]['key' ])]
106
- if not matching_entries :
107
- raise RuntimeError ("Found no installed package for '%s' in %s" % (pkg , dep_tree ))
108
- if len (matching_entries ) > 1 :
109
- raise RuntimeError ("Found multiple installed packages for '%s' in %s" % (pkg , dep_tree ))
110
- entry = matching_entries [0 ]
111
- res .append ((entry ['package' ]['package_name' ], entry ['package' ]['installed_version' ]))
112
- deps = (dep ['package_name' ] for dep in entry ['dependencies' ])
113
- res .extend (find_deps (deps , dep_tree ))
114
+ if pkg in (entry ['package' ]['package_name' ], entry ['package' ]['key' ])]
115
+ if not matching_entries :
116
+ matching_entries = [entry for entry in dep_tree
117
+ if orig_pkg in (entry ['package' ]['package_name' ], entry ['package' ]['key' ])]
118
+ if not matching_entries :
119
+ raise RuntimeError ("Found no installed package for '%s' in %s" % (pkg , dep_tree ))
120
+ if len (matching_entries ) > 1 :
121
+ raise RuntimeError ("Found multiple installed packages for '%s' in %s" % (pkg , dep_tree ))
122
+ entry = matching_entries [0 ]
123
+ res .append ((entry ['package' ]['package_name' ], entry ['package' ]['installed_version' ]))
124
+ # Add dependencies to list of packages to check next
125
+ # Could call this function recursively but that might exceed the max recursion depth
126
+ next_pkgs .update (dep ['package_name' ] for dep in entry ['dependencies' ])
114
127
return res
115
128
116
129
0 commit comments