ossa-scanner 0.1.0__py3-none-any.whl → 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ossa_scanner/__init__.py CHANGED
@@ -0,0 +1 @@
1
+ __version__ = "0.1.2"
ossa_scanner/cli.py ADDED
@@ -0,0 +1,35 @@
1
+ import argparse
2
+ from .scanner import Scanner
3
+ from .uploader import GitHubUploader
4
+
5
+ def main():
6
+ parser = argparse.ArgumentParser(description="OSSA Scanner CLI Tool")
7
+ parser.add_argument('--output-dir', type=str, required=True, help="Directory to save downloaded source")
8
+ parser.add_argument('--results-file', type=str, required=True, help="Path to save the JSON results")
9
+ parser.add_argument('--threads', type=int, default=4, help="Number of threads for parallel processing")
10
+ parser.add_argument('--upload', action='store_true', help="Upload results to GitHub")
11
+ parser.add_argument('--repo-owner', type=str, help="GitHub repository owner")
12
+ parser.add_argument('--repo-name', type=str, help="GitHub repository name")
13
+ parser.add_argument('--token', type=str, help="GitHub token")
14
+ parser.add_argument('--repo-dir', type=str, help="Target directory in GitHub repo for results")
15
+ args = parser.parse_args()
16
+
17
+ # Initialize the scanner
18
+ scanner = Scanner(output_dir=args.output_dir, threads=args.threads)
19
+
20
+ # Perform scanning
21
+ results = scanner.scan_packages()
22
+
23
+ # Save results locally
24
+ scanner.save_results(results, args.results_file)
25
+
26
+ # Upload results to GitHub if specified
27
+ if args.upload:
28
+ if not (args.repo_owner and args.repo_name and args.token and args.repo_dir):
29
+ raise ValueError("GitHub upload requires --repo-owner, --repo-name, --token, and --repo-dir")
30
+
31
+ uploader = GitHubUploader(args.token, args.repo_owner, args.repo_name)
32
+ scanner.upload_results(args.results_file, uploader, args.repo_dir)
33
+
34
+ if __name__ == "__main__":
35
+ main()
ossa_scanner/scanner.py CHANGED
@@ -1,21 +1,15 @@
1
1
  import os
2
2
  import json
3
3
  from concurrent.futures import ThreadPoolExecutor, as_completed
4
- from ossa_scanner.utils.os_detection import detect_os
5
- from ossa_scanner.utils.package_manager import list_packages, get_package_info, download_source
6
- from ossa_scanner.utils.hash_calculator import calculate_file_hash
7
- from ossa_scanner.utils.swhid_calculator import calculate_swhid
8
- from ossa_scanner.uploader import GitHubUploader
4
+ from .utils.os_detection import detect_os
5
+ from .utils.package_manager import list_packages, get_package_info
6
+ from .utils.downloader import download_source
7
+ from .utils.hash_calculator import calculate_file_hash
8
+ from .utils.swhid_calculator import calculate_swhid
9
+ from .uploader import GitHubUploader
9
10
 
10
11
  class Scanner:
11
12
  def __init__(self, output_dir, threads=4):
12
- """
13
- Initialize the scanner with the output directory and thread count.
14
-
15
- Args:
16
- output_dir (str): Directory to store downloaded files and extracted sources.
17
- threads (int): Number of threads for parallel processing.
18
- """
19
13
  self.output_dir = output_dir
20
14
  self.os_type = detect_os()
21
15
  self.threads = threads
@@ -75,7 +69,6 @@ class Scanner:
75
69
  print(f"Detected OS: {self.os_type}")
76
70
  print("Listing available packages...")
77
71
  packages = list_packages(self.os_type)
78
-
79
72
  results = []
80
73
  with ThreadPoolExecutor(max_workers=self.threads) as executor:
81
74
  # Submit tasks for parallel processing
@@ -1,11 +1,47 @@
1
1
  import subprocess
2
+ import os
3
+ import shutil
4
+ import glob
2
5
 
3
6
  def download_source(package_manager, package_name, output_dir):
4
- if package_manager == 'apt':
5
- cmd = ['apt-get', 'source', package_name, '-d', output_dir]
6
- elif package_manager in ['yum', 'dnf']:
7
- cmd = ['dnf', 'download', '--source', package_name, '--downloaddir', output_dir]
8
- else:
9
- raise ValueError("Unsupported package manager")
10
-
11
- subprocess.run(cmd)
7
+ try:
8
+ if package_manager == 'apt':
9
+ cmd = ['apt-get', 'source', package_name, '-d', output_dir]
10
+ subprocess.run(cmd, check=True)
11
+ elif package_manager in ['yum', 'dnf']:
12
+ cmd = ['dnf', 'download', '--source', package_name, '--downloaddir', output_dir]
13
+ subprocess.run(cmd, check=True)
14
+ elif package_manager == 'brew':
15
+ # Fetch the source tarball
16
+ cmd = ['brew', 'fetch', '--build-from-source', package_name]
17
+ subprocess.run(cmd, check=True, capture_output=True, text=True)
18
+ cache_dir = subprocess.run(
19
+ ['brew', '--cache', package_name],
20
+ capture_output=True,
21
+ text=True,
22
+ check=True
23
+ ).stdout.strip()
24
+ prefixes_to_remove = ['aarch64-elf-', 'arm-none-eabi-', 'other-prefix-']
25
+ stripped_package_name = package_name
26
+ for prefix in prefixes_to_remove:
27
+ if package_name.startswith(prefix):
28
+ stripped_package_name = package_name[len(prefix):]
29
+ break
30
+ cache_folder = os.path.dirname(cache_dir)
31
+ tarball_pattern = os.path.join(cache_folder, f"*{stripped_package_name}*")
32
+ matching_files = glob.glob(tarball_pattern)
33
+ if not matching_files:
34
+ raise FileNotFoundError(f"Tarball not found for {package_name} in {cache_folder}")
35
+ tarball_path = matching_files[0]
36
+ os.makedirs(output_dir, exist_ok=True)
37
+ target_path = os.path.join(output_dir, os.path.basename(tarball_path))
38
+ shutil.move(tarball_path, target_path)
39
+ return target_path
40
+ else:
41
+ raise ValueError("Unsupported package manager")
42
+ except subprocess.CalledProcessError as e:
43
+ print(f"Command failed: {e}")
44
+ return None
45
+ except Exception as e:
46
+ print(f"Error: {e}")
47
+ return None
@@ -1,10 +1,13 @@
1
- import platform
1
+ import distro
2
2
 
3
3
  def detect_os():
4
- dist, _, _ = platform.linux_distribution(full_distribution_name=False)
5
- if 'Ubuntu' in dist or 'Debian' in dist:
4
+ dist = distro.id()
5
+ if 'ubuntu' in dist or 'debian' in dist:
6
6
  return 'apt'
7
- elif 'Red Hat' in dist or 'CentOS' in dist or 'AlmaLinux' in dist:
7
+ elif 'redhat' in dist or 'centos' in dist or 'almalinux' in dist:
8
8
  return 'yum'
9
+ elif 'darwin' in dist:
10
+ return 'brew'
9
11
  else:
10
12
  raise ValueError("Unsupported OS")
13
+
@@ -1,5 +1,6 @@
1
1
  import subprocess
2
2
 
3
+
3
4
  def list_packages(package_manager):
4
5
  if package_manager == 'apt':
5
6
  result = subprocess.run(
@@ -13,19 +14,115 @@ def list_packages(package_manager):
13
14
  capture_output=True,
14
15
  text=True
15
16
  )
17
+ elif package_manager == 'brew':
18
+ result = subprocess.run(
19
+ ['brew', 'search', '.'],
20
+ capture_output=True,
21
+ text=True
22
+ )
16
23
  else:
17
- raise ValueError("Unsupported package manager")
24
+ raise ValueError("ER1: Unsupported package manager for search")
18
25
 
19
26
  packages = result.stdout.splitlines()
20
- return [pkg.split()[0] for pkg in packages]
27
+ extracted_packages = []
28
+ max_packages = 5
29
+ k_packages = 0
30
+ for line in packages:
31
+ if not line.strip() or line.startswith("==>"):
32
+ continue
33
+ extracted_packages.append(line.split()[0])
34
+ if k_packages >= max_packages:
35
+ break
36
+ k_packages += 1
37
+
38
+ return extracted_packages
39
+
21
40
 
22
41
  def get_package_info(package_manager, package_name):
23
42
  if package_manager == 'apt':
24
43
  cmd = ['apt-cache', 'show', package_name]
25
44
  elif package_manager in ['yum', 'dnf']:
26
45
  cmd = ['repoquery', '--info', package_name]
46
+ elif package_manager == 'brew':
47
+ cmd = ['brew', 'info', package_name]
27
48
  else:
28
- raise ValueError("Unsupported package manager")
49
+ raise ValueError("ER: Unsupported package manager for info")
50
+
51
+ try:
52
+ result = subprocess.run(cmd, capture_output=True, text=True, check=True)
53
+ output = result.stdout
54
+
55
+ # Parse the output based on the package manager
56
+ if package_manager == 'brew':
57
+ return parse_brew_info(output)
58
+ elif package_manager in ['yum', 'dnf']:
59
+ return parse_yum_info(output)
60
+ elif package_manager == 'apt':
61
+ return parse_apt_info(output)
62
+ except subprocess.CalledProcessError as e:
63
+ print(f"Command failed: {e}")
64
+ return None
65
+
66
+
67
+ def parse_brew_info(output):
68
+ """Parses brew info output to extract license, website, and description."""
69
+ info = {}
70
+ lines = output.splitlines()
71
+ info["license"] = "Unknown"
72
+ info["website"] = "Unknown"
73
+ info["description"] = "Unknown"
74
+
75
+ for i, line in enumerate(lines):
76
+ if i == 1: # The description is usually on the second line
77
+ info["description"] = line.strip()
78
+ elif line.startswith("https://"): # The website URL
79
+ info["website"] = line.strip()
80
+ elif line.startswith("License:"): # The license information
81
+ info["license"] = line.split(":", 1)[1].strip()
82
+
83
+ # Ensure all keys are present even if some fields are missing
84
+ return info
85
+
86
+
87
+
88
+ def parse_yum_info(output):
89
+ """Parses yum repoquery --info output."""
90
+ info = {}
91
+ lines = output.splitlines()
92
+
93
+ for line in lines:
94
+ if line.startswith("License"):
95
+ info["license"] = line.split(":", 1)[1].strip()
96
+ elif line.startswith("URL"):
97
+ info["website"] = line.split(":", 1)[1].strip()
98
+ elif "Copyright" in line:
99
+ info["copyright"] = line.strip()
100
+
101
+ # Ensure all keys are present even if data is missing
102
+ return {
103
+ "license": info.get("license", "Unknown"),
104
+ "copyright": info.get("copyright", "Unknown"),
105
+ "website": info.get("website", "Unknown"),
106
+ }
107
+
108
+
109
+ def parse_apt_info(output):
110
+ """Parses apt-cache show output."""
111
+ info = {}
112
+ lines = output.splitlines()
113
+
114
+ for line in lines:
115
+ if line.startswith("License:") or "License" in line:
116
+ info["license"] = line.split(":", 1)[1].strip()
117
+ elif line.startswith("Homepage:"):
118
+ info["website"] = line.split(":", 1)[1].strip()
119
+ elif "Copyright" in line:
120
+ info["copyright"] = line.strip()
121
+
122
+ # Ensure all keys are present even if data is missing
123
+ return {
124
+ "license": info.get("license", "Unknown"),
125
+ "copyright": info.get("copyright", "Unknown"),
126
+ "website": info.get("website", "Unknown"),
127
+ }
29
128
 
30
- result = subprocess.run(cmd, capture_output=True, text=True)
31
- return result.stdout
@@ -1,4 +1,3 @@
1
- from swh.model.hashutil import hash_directory
2
1
 
3
2
  def calculate_swhid(directory_path):
4
- return hash_directory(directory_path)
3
+ return directory_path
@@ -0,0 +1,28 @@
1
+ Metadata-Version: 2.1
2
+ Name: ossa_scanner
3
+ Version: 0.1.2
4
+ Summary: A Python library for scanning Linux packages, managing metadata, and generating SWHIDs.
5
+ Home-page: https://github.com/oscarvalenzuelab/ossa_scanner
6
+ Author: Oscar Valenzuela
7
+ Author-email: oscar.valenzuela.b@gmail.com
8
+ License: MIT
9
+ Keywords: linux packages SWHID open-source compliance
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.6
15
+ Classifier: Programming Language :: Python :: 3.7
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Operating System :: POSIX :: Linux
20
+ Requires-Python: >=3.6
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: click
24
+ Requires-Dist: swh.model
25
+ Requires-Dist: distro
26
+
27
+ # ossa_scanner
28
+ Open Source Advisory Scanner (Generator)
@@ -0,0 +1,16 @@
1
+ ossa_scanner/__init__.py,sha256=YvuYzWnKtqBb-IqG8HAu-nhIYAsgj9Vmc_b9o7vO-js,22
2
+ ossa_scanner/cli.py,sha256=hyRUOgp9kcwFtQrIeyth5vTxeK7eOlxfn5R9E7HX5sA,1640
3
+ ossa_scanner/scanner.py,sha256=SAkiBLjAuO3dklbHPgXs0p047buO6Pp51RROq6G7Yq8,4082
4
+ ossa_scanner/uploader.py,sha256=X8bo7GqfpBjz2NlnvSwDR_rVqNoZDRPF2pnQMaVENbc,2436
5
+ ossa_scanner/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ ossa_scanner/utils/downloader.py,sha256=3ccwcde9yJ_SEP0mG9TDr2O0MMdA1p-K6hpzqme-KQ4,2081
7
+ ossa_scanner/utils/hash_calculator.py,sha256=i47KS_HoZNiSbGyd0iP9_TcDwxWS2SrmkIcNF2MWLcA,254
8
+ ossa_scanner/utils/os_detection.py,sha256=QdRKQ4li4SOHgBofe1qWf8OOcw8XvhM-XWUNu0Cy0a4,315
9
+ ossa_scanner/utils/package_manager.py,sha256=tWuQwgkFQjTzeisem0Gz8uFvWw5Cxd-Tft5HM8tIQmk,4028
10
+ ossa_scanner/utils/swhid_calculator.py,sha256=4Z0H2GmECMAJlvH6JBbUmaLXSLRNntyYEdxsS6CTEMQ,63
11
+ ossa_scanner-0.1.2.dist-info/LICENSE,sha256=9slQ_XNiEkio28l90NwihP7a90fCL2GQ6YhcVXTBls4,1064
12
+ ossa_scanner-0.1.2.dist-info/METADATA,sha256=dWWsJKRvqN1vdal81dAseom9Cb1OwLjuOZAllrfOoMs,1043
13
+ ossa_scanner-0.1.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
14
+ ossa_scanner-0.1.2.dist-info/entry_points.txt,sha256=UVoAo-wTPxT82g3cfqTs2CmQnazd57TAwhd9VwEKD1c,55
15
+ ossa_scanner-0.1.2.dist-info/top_level.txt,sha256=uUp5CvhZfJLapXn9DyUXvgH7QK3uzF2ibH943lWN5Bs,13
16
+ ossa_scanner-0.1.2.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ ossa_scanner = ossa_scanner.cli:main
@@ -1,41 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: ossa-scanner
3
- Version: 0.1.0
4
- Summary: A CLI tool to scan Linux packages, manage metadata, and upload results to GitHub.
5
- Author: Oscar Valenzuela
6
- Author-email: Oscar Valenzuela <oscar.valenzuela.b@gmail.com>
7
- License: MIT License
8
-
9
- Copyright (c) 2024 Oscar V
10
-
11
- Permission is hereby granted, free of charge, to any person obtaining a copy
12
- of this software and associated documentation files (the "Software"), to deal
13
- in the Software without restriction, including without limitation the rights
14
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
- copies of the Software, and to permit persons to whom the Software is
16
- furnished to do so, subject to the following conditions:
17
-
18
- The above copyright notice and this permission notice shall be included in all
19
- copies or substantial portions of the Software.
20
-
21
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
- SOFTWARE.
28
-
29
- Keywords: linux,packages,SWHID,GitHub,open-source
30
- Classifier: Development Status :: 3 - Alpha
31
- Classifier: Intended Audience :: Developers
32
- Classifier: License :: OSI Approved :: MIT License
33
- Classifier: Programming Language :: Python :: 3
34
- Classifier: Operating System :: POSIX :: Linux
35
- Requires-Python: >=3.7
36
- Description-Content-Type: text/markdown
37
- License-File: LICENSE
38
- Requires-Dist: swh.model
39
-
40
- # ossa_scanner
41
- Open Source Advisory Scanner (Generator)
@@ -1,14 +0,0 @@
1
- ossa_scanner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- ossa_scanner/scanner.py,sha256=nku8pJR1n7Z2Fjs5F3lbxBlv9xFUWrUb3dfucZZcM30,4387
3
- ossa_scanner/uploader.py,sha256=X8bo7GqfpBjz2NlnvSwDR_rVqNoZDRPF2pnQMaVENbc,2436
4
- ossa_scanner/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- ossa_scanner/utils/downloader.py,sha256=5fV531x-oiFTyh6B17Afi4W72zFC2ejopvMpn1qNpw4,408
6
- ossa_scanner/utils/hash_calculator.py,sha256=i47KS_HoZNiSbGyd0iP9_TcDwxWS2SrmkIcNF2MWLcA,254
7
- ossa_scanner/utils/os_detection.py,sha256=h2hlS5QHHVyyGSHI5jDwq7aivGZTEHk1v_Ml9lTTxbQ,320
8
- ossa_scanner/utils/package_manager.py,sha256=N_noGTVHxxCTfH9q6ftq2GhkACj1ExOt1AXhNdFFgNQ,953
9
- ossa_scanner/utils/swhid_calculator.py,sha256=mvjx4wlTDCrWhH3Z_6TitKtt1WsPMC7QYwmWSMck7Ro,126
10
- ossa_scanner-0.1.0.dist-info/LICENSE,sha256=9slQ_XNiEkio28l90NwihP7a90fCL2GQ6YhcVXTBls4,1064
11
- ossa_scanner-0.1.0.dist-info/METADATA,sha256=VdiOAhrJ6M75qRG6ntG8UGxYFUR8IQoPNvtFX-bB_Nk,1927
12
- ossa_scanner-0.1.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
13
- ossa_scanner-0.1.0.dist-info/top_level.txt,sha256=uUp5CvhZfJLapXn9DyUXvgH7QK3uzF2ibH943lWN5Bs,13
14
- ossa_scanner-0.1.0.dist-info/RECORD,,