Skip to content

Commit 6f5f1b3

Browse files
gitphillgemaxim
andauthored
feat: record pkg id provenance (#252)
Co-authored-by: Georgiana-Elena Maxim <[email protected]>
1 parent d5b4b4e commit 6f5f1b3

File tree

9 files changed

+371
-32
lines changed

9 files changed

+371
-32
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"@snyk/cli-interface": "^2.11.2",
2828
"@snyk/dep-graph": "^1.28.1",
2929
"shescape": "1.6.1",
30-
"snyk-poetry-lockfile-parser": "^1.4.2",
30+
"snyk-poetry-lockfile-parser": "^1.6.1",
3131
"tmp": "0.2.1"
3232
},
3333
"devDependencies": {

pysrc/pip_resolve.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
PACKAGE_FORMAT_VERSION = 'packageFormatVersion'
2525
LABELS = 'labels'
2626
PROVENANCE = 'provenance'
27+
PKG_ID_PROVENANCE = 'pkgIdProvenance'
2728
NUMBER_OF_BYTES = 4
2829

2930
# Declaring deps manager as global variable
@@ -44,7 +45,8 @@ def create_tree_of_packages_dependencies(
4445
optional_dependencies,
4546
req_file_path,
4647
allow_missing=False,
47-
only_provenance=False
48+
only_provenance=False,
49+
top_level_provenance_map={},
4850
):
4951
"""Creates the dependency tree for the project.
5052
@@ -67,6 +69,11 @@ def create_tree_of_packages_dependencies(
6769
key_tree = dict(
6870
(canonicalize_package_name(k.key), v) for k, v in tree.items()
6971
)
72+
73+
tree_provenance_map = dict(
74+
(canonicalize_package_name(k.key), k.key) for k, _ in tree.items()
75+
)
76+
tree_provenance_map.update(top_level_provenance_map)
7077

7178
lowercase_pkgs_names = [p.name.lower() for p in top_level_requirements]
7279
tlr_by_key = dict((tlr.name.lower(), tlr) for tlr in top_level_requirements)
@@ -84,7 +91,8 @@ def create_children_recursive(
8491
root_package,
8592
key_tree,
8693
ancestors,
87-
all_packages_map
94+
all_packages_map,
95+
provenance_map,
8896
):
8997
root_name = canonicalize_package_name(root_package[NAME])
9098

@@ -101,6 +109,14 @@ def create_children_recursive(
101109
else:
102110
sys.exit(msg)
103111

112+
if provenance_map[root_name] != root_package[NAME]:
113+
if LABELS in root_package:
114+
root_package[LABELS][PKG_ID_PROVENANCE] = "{}@{}".format(provenance_map[root_name],root_package[VERSION])
115+
else:
116+
root_package[LABELS] = {
117+
PKG_ID_PROVENANCE: "{}@{}".format(provenance_map[root_name],root_package[VERSION])
118+
}
119+
104120
ancestors = ancestors.copy()
105121
ancestors.add(root_name)
106122
children_packages_as_dist = key_tree[root_name]
@@ -123,10 +139,10 @@ def create_children_recursive(
123139

124140
child_package = {
125141
NAME: child_project_name,
126-
VERSION: child_dist.installed_version,
142+
VERSION: child_dist.installed_version
127143
}
128144

129-
create_children_recursive(child_package, key_tree, ancestors, all_packages_map)
145+
create_children_recursive(child_package, key_tree, ancestors, all_packages_map, provenance_map)
130146
root_package[DEPENDENCIES][child_project_name] = child_package
131147
all_packages_map[child_project_name] = 'true'
132148
return root_package
@@ -165,7 +181,7 @@ def create_package_as_root(package):
165181
dir_as_root[DEPENDENCIES][package_as_root[NAME]] = package_as_root
166182
else:
167183
package_tree = create_children_recursive(package_as_root, key_tree,
168-
set([]), all_packages_map)
184+
set([]), all_packages_map, tree_provenance_map)
169185
dir_as_root[DEPENDENCIES][package_as_root[NAME]] = package_tree
170186

171187
return dir_as_root
@@ -457,6 +473,8 @@ def create_dependencies_tree_by_req_file_path(
457473
deps_manager
458474
)
459475

476+
top_level_provenance_map = {}
477+
460478
if not required and not allow_empty:
461479
msg = 'No dependencies detected in manifest.'
462480
sys.exit(msg)
@@ -469,6 +487,7 @@ def create_dependencies_tree_by_req_file_path(
469487
missing_package_names.append(r.name)
470488
else:
471489
top_level_requirements.append(r)
490+
top_level_provenance_map[canonicalize_package_name(r.name)] = r.original_name
472491
if missing_package_names:
473492
msg = 'Required packages missing: ' + (', '.join(missing_package_names))
474493
if allow_missing:
@@ -483,7 +502,8 @@ def create_dependencies_tree_by_req_file_path(
483502
optional_dependencies,
484503
requirements_file_path,
485504
allow_missing,
486-
only_provenance
505+
only_provenance,
506+
top_level_provenance_map,
487507
)
488508

489509
print(json.dumps(package_tree))

pysrc/pipfile.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def __init__(self, name):
1818
self.version = None
1919
self.markers = None
2020
self.provenance = None # a tuple of (file name, line)
21+
self.original_name = None
2122

2223
def __repr__(self):
2324
return str(self.__dict__())
@@ -42,6 +43,7 @@ def __eq__(self, other):
4243
def from_dict(cls, name, requirement_dict, pos_in_toml):
4344
req = cls(name)
4445

46+
req.original_name = req.name
4547
req.version = parse_req(requirement_dict.get('version'))
4648
req.editable = parse_req(requirement_dict.get('editable', False))
4749
for vcs in ['git', 'hg', 'svn', 'bzr']:

pysrc/requirements/requirement.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ def __init__(self, line):
8282
self.extras = []
8383
self.specs = []
8484
self.provenance = None
85+
self.original_name = None
8586

8687
def __repr__(self):
8788
return '<Requirement: "{0}">'.format(self.line)
@@ -217,8 +218,11 @@ def parse_line(cls, line):
217218

218219
pkg_req = Req.parse(line)
219220
req.name = pkg_req.unsafe_name
221+
req.original_name = pkg_req.name
220222
req.extras = list(pkg_req.extras)
221223
req.specs = pkg_req.specs
224+
if not req.original_name:
225+
req.original_name = req.name
222226
return req
223227

224228
@classmethod

0 commit comments

Comments
 (0)