Skip to content

Commit 669bc18

Browse files
committed
Add step to tag resources based on content and name #688
Signed-off-by: Thomas Druez <tdruez@nexb.com>
1 parent f427d6f commit 669bc18

10 files changed

Lines changed: 143 additions & 26 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Generated by Django 4.2 on 2023-04-21 13:01
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
dependencies = [
8+
("scanpipe", "0030_codebaserelation_scanpipe_co_relatio_40d26d_idx_and_more"),
9+
]
10+
11+
operations = [
12+
migrations.AddIndex(
13+
model_name="codebaseresource",
14+
index=models.Index(fields=["status"], name="scanpipe_co_status_20d02b_idx"),
15+
),
16+
]

scanpipe/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1639,6 +1639,7 @@ class Meta:
16391639
models.Index(fields=["path"]),
16401640
models.Index(fields=["name"]),
16411641
models.Index(fields=["extension"]),
1642+
models.Index(fields=["status"]),
16421643
models.Index(fields=["programming_language"]),
16431644
models.Index(fields=["sha1"]),
16441645
]

scanpipe/pipelines/develop_to_deploy.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from scanpipe.pipes import d2d
2626
from scanpipe.pipes import purldb
2727
from scanpipe.pipes import scancode
28+
from scanpipe.pipes import tag
2829
from scanpipe.pipes.scancode import extract_archives
2930

3031

@@ -38,6 +39,7 @@ def steps(cls):
3839
cls.extract_inputs_to_codebase_directory,
3940
cls.extract_archives_in_place,
4041
cls.collect_and_create_codebase_resources,
42+
cls.tag_empty_and_ignored_files,
4143
cls.checksum_match,
4244
cls.purldb_match,
4345
cls.java_to_class_match,
@@ -74,6 +76,12 @@ def collect_and_create_codebase_resources(self):
7476
for resource_path in self.project.walk_codebase_path():
7577
pipes.make_codebase_resource(project=self.project, location=resource_path)
7678

79+
def tag_empty_and_ignored_files(self):
80+
"""Tag empty and ignored files using names and extensions."""
81+
tag.tag_empty_codebase_resources(self.project)
82+
tag.tag_ignored_filenames(self.project, filenames=d2d.IGNORE_FILENAMES)
83+
tag.tag_ignored_extensions(self.project, extensions=d2d.IGNORE_EXTENSIONS)
84+
7785
def checksum_match(self):
7886
"""Match using SHA1 checksum."""
7987
d2d.checksum_match(project=self.project, checksum_field="sha1", logger=self.log)

scanpipe/pipelines/root_filesystems.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from scanpipe.pipelines import Pipeline
2727
from scanpipe.pipes import rootfs
2828
from scanpipe.pipes import scancode
29+
from scanpipe.pipes import tag
2930

3031

3132
class RootFS(Pipeline):
@@ -95,7 +96,7 @@ def tag_uninteresting_codebase_resources(self):
9596

9697
def tag_empty_files(self):
9798
"""Flag empty files."""
98-
rootfs.tag_empty_codebase_resources(self.project)
99+
tag.tag_empty_codebase_resources(self.project)
99100

100101
def scan_for_application_packages(self):
101102
"""Scan unknown resources for packages information."""

scanpipe/pipelines/scan_codebase.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222

2323
from scanpipe import pipes
2424
from scanpipe.pipelines import Pipeline
25-
from scanpipe.pipes import rootfs
2625
from scanpipe.pipes import scancode
26+
from scanpipe.pipes import tag
2727
from scanpipe.pipes.input import copy_inputs
2828

2929

@@ -81,7 +81,7 @@ def collect_and_create_codebase_resources(self):
8181

8282
def tag_empty_files(self):
8383
"""Flag empty files."""
84-
rootfs.tag_empty_codebase_resources(self.project)
84+
tag.tag_empty_codebase_resources(self.project)
8585

8686
def scan_for_application_packages(self):
8787
"""Scan unknown resources for packages information."""

scanpipe/pipes/d2d.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
FROM = "from/"
3030
TO = "to/"
3131

32+
IGNORE_FILENAMES = ("packageinfo",)
33+
34+
IGNORE_EXTENSIONS = ()
35+
3236

3337
def get_inputs(project):
3438
"""Locate the `from` and `to` archives in project inputs directory."""
@@ -46,7 +50,7 @@ def get_inputs(project):
4650

4751
def checksum_match(project, checksum_field, logger=None):
4852
"""Match using checksum."""
49-
project_files = project.codebaseresources.files().not_empty()
53+
project_files = project.codebaseresources.files().no_status()
5054
from_resources = project_files.from_codebase().has_value(checksum_field)
5155
to_resources = (
5256
project_files.to_codebase().has_value(checksum_field).has_no_relation()
@@ -76,7 +80,7 @@ def java_to_class_match(project, logger=None):
7680
from_extension = ".java"
7781
to_extension = ".class"
7882

79-
project_files = project.codebaseresources.files()
83+
project_files = project.codebaseresources.files().no_status()
8084
from_resources = project_files.from_codebase()
8185
to_resources = project_files.to_codebase().has_no_relation()
8286

@@ -108,7 +112,7 @@ def java_to_class_match(project, logger=None):
108112

109113
def path_match(project, logger=None):
110114
"""Match using path similarities."""
111-
project_files = project.codebaseresources.files().not_empty().only("path")
115+
project_files = project.codebaseresources.files().no_status().only("path")
112116
from_resources = project_files.from_codebase()
113117
to_resources = project_files.to_codebase().has_no_relation()
114118
resource_count = to_resources.count()
@@ -158,8 +162,8 @@ def path_match(project, logger=None):
158162
def purldb_match(project, extensions, logger=None):
159163
to_resources = (
160164
project.codebaseresources.files()
161-
.not_empty()
162165
.to_codebase()
166+
.no_status()
163167
.has_value("sha1")
164168
.filter(extension__in=extensions)
165169
)

scanpipe/pipes/rootfs.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -313,12 +313,6 @@ def match_not_analyzed(
313313
matchable.save()
314314

315315

316-
def tag_empty_codebase_resources(project):
317-
"""Tags empty files as ignored."""
318-
qs = project.codebaseresources.files().empty()
319-
qs.filter(status__in=("", "not-analyzed")).update(status="ignored-empty-file")
320-
321-
322316
def tag_uninteresting_codebase_resources(project):
323317
"""
324318
Check any file that doesn’t belong to any system package and determine if it's:

scanpipe/pipes/tag.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# http://nexb.com and https://github.com/nexB/scancode.io
4+
# The ScanCode.io software is licensed under the Apache License version 2.0.
5+
# Data generated with ScanCode.io is provided as-is without warranties.
6+
# ScanCode is a trademark of nexB Inc.
7+
#
8+
# You may not use this software except in compliance with the License.
9+
# You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0
10+
# Unless required by applicable law or agreed to in writing, software distributed
11+
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12+
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
13+
# specific language governing permissions and limitations under the License.
14+
#
15+
# Data Generated with ScanCode.io is provided on an "AS IS" BASIS, WITHOUT WARRANTIES
16+
# OR CONDITIONS OF ANY KIND, either express or implied. No content created from
17+
# ScanCode.io should be considered or used as legal advice. Consult an Attorney
18+
# for any legal advice.
19+
#
20+
# ScanCode.io is a free software code scanning tool from nexB Inc. and others.
21+
# Visit https://github.com/nexB/scancode.io for support and download.
22+
23+
24+
def tag_empty_codebase_resources(project):
25+
"""Tags empty files as ignored."""
26+
qs = (
27+
project.codebaseresources.files()
28+
.empty()
29+
.filter(status__in=("", "not-analyzed"))
30+
)
31+
return qs.update(status="ignored-empty-file")
32+
33+
34+
def tag_ignored_filenames(project, filenames):
35+
"""Tag codebase resource as `ignored` status from list of `filenames`."""
36+
qs = project.codebaseresources.no_status().filter(name__in=filenames)
37+
return qs.update(status="ignored-filename")
38+
39+
40+
def tag_ignored_extensions(project, extensions):
41+
"""Tag codebase resource as `ignored` status from list of `extensions`."""
42+
qs = project.codebaseresources.no_status().filter(extension__in=extensions)
43+
return qs.update(status="ignored-extension")

scanpipe/tests/pipes/test_rootfs.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,6 @@ def test_scanpipe_pipes_rootfs_from_project_codebase_class_method(self):
4848
self.assertEqual("windows", distro.os)
4949
self.assertEqual("windows", distro.identifier)
5050

51-
def test_scanpipe_pipes_rootfs_tag_empty_codebase_resources(self):
52-
p1 = Project.objects.create(name="Analysis")
53-
resource1 = CodebaseResource.objects.create(project=p1, path="dir/")
54-
resource2 = CodebaseResource.objects.create(
55-
project=p1, path="filename.ext", type=CodebaseResource.Type.FILE
56-
)
57-
58-
rootfs.tag_empty_codebase_resources(p1)
59-
resource1.refresh_from_db()
60-
resource2.refresh_from_db()
61-
self.assertEqual("", resource1.status)
62-
self.assertEqual("ignored-empty-file", resource2.status)
63-
6451
def test_scanpipe_pipes_rootfs_tag_uninteresting_codebase_resources(self):
6552
p1 = Project.objects.create(name="Analysis")
6653
resource1 = CodebaseResource.objects.create(project=p1, path="filename.ext")

scanpipe/tests/pipes/test_tag.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# http://nexb.com and https://github.com/nexB/scancode.io
4+
# The ScanCode.io software is licensed under the Apache License version 2.0.
5+
# Data generated with ScanCode.io is provided as-is without warranties.
6+
# ScanCode is a trademark of nexB Inc.
7+
#
8+
# You may not use this software except in compliance with the License.
9+
# You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0
10+
# Unless required by applicable law or agreed to in writing, software distributed
11+
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12+
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
13+
# specific language governing permissions and limitations under the License.
14+
#
15+
# Data Generated with ScanCode.io is provided on an "AS IS" BASIS, WITHOUT WARRANTIES
16+
# OR CONDITIONS OF ANY KIND, either express or implied. No content created from
17+
# ScanCode.io should be considered or used as legal advice. Consult an Attorney
18+
# for any legal advice.
19+
#
20+
# ScanCode.io is a free software code scanning tool from nexB Inc. and others.
21+
# Visit https://github.com/nexB/scancode.io for support and download.
22+
23+
from django.test import TestCase
24+
25+
from scanpipe.models import CodebaseResource
26+
from scanpipe.models import Project
27+
from scanpipe.pipes import tag
28+
29+
30+
class ScanPipeTagPipesTest(TestCase):
31+
def setUp(self):
32+
self.project1 = Project.objects.create(name="Analysis")
33+
self.resource1 = CodebaseResource.objects.create(
34+
project=self.project1, path="dir/"
35+
)
36+
self.resource2 = CodebaseResource.objects.create(
37+
project=self.project1,
38+
type=CodebaseResource.Type.FILE,
39+
path="dir/filename.ext",
40+
name="filename.ext",
41+
extension=".ext",
42+
)
43+
44+
def test_scanpipe_pipes_tag_tag_empty_codebase_resources(self):
45+
tag.tag_empty_codebase_resources(self.project1)
46+
self.resource1.refresh_from_db()
47+
self.resource2.refresh_from_db()
48+
self.assertEqual("", self.resource1.status)
49+
self.assertEqual("ignored-empty-file", self.resource2.status)
50+
51+
def test_scanpipe_pipes_tag_tag_ignored_filenames(self):
52+
tag.tag_ignored_filenames(self.project1, filenames=[self.resource2.name])
53+
self.resource1.refresh_from_db()
54+
self.resource2.refresh_from_db()
55+
self.assertEqual("", self.resource1.status)
56+
self.assertEqual("ignored-filename", self.resource2.status)
57+
58+
def test_scanpipe_pipes_tag_tag_ignored_extensions(self):
59+
tag.tag_ignored_extensions(self.project1, extensions=[self.resource2.extension])
60+
self.resource1.refresh_from_db()
61+
self.resource2.refresh_from_db()
62+
self.assertEqual("", self.resource1.status)
63+
self.assertEqual("ignored-extension", self.resource2.status)

0 commit comments

Comments
 (0)