Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions cycode/cli/files_collector/sca/npm/restore_bun_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@
import typer

from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies, build_dep_tree_path
from cycode.cli.files_collector.sca.npm.workspace import (
BUN_LOCK_FILE_NAME,
MANIFEST_FILE_NAME,
is_covered_workspace_member,
)
from cycode.cli.models import Document
from cycode.cli.utils.path_utils import get_file_content
from cycode.cli.utils.path_utils import get_file_content, get_scan_roots_from_context
from cycode.cli.utils.shell_executor import shell
from cycode.logger import get_logger

logger = get_logger('Bun Restore Dependencies')

BUN_MANIFEST_FILE_NAME = 'package.json'
BUN_LOCK_FILE_NAME = 'bun.lock'
BUN_MANIFEST_FILE_NAME = MANIFEST_FILE_NAME

# Only Bun >=1.2 produces the text-based `bun.lock` lockfile that we parse.
# Older Bun versions emit a binary `bun.lockb`, which is not supported.
Expand Down Expand Up @@ -61,6 +65,9 @@ def is_project(self, document: Document) -> bool:
if manifest_dir and (Path(manifest_dir) / BUN_LOCK_FILE_NAME).is_file():
return True

if is_covered_workspace_member(manifest_dir, document.path, get_scan_roots_from_context(self.ctx)):
return False

return _indicates_bun(document.content)

def _is_supported_bun_version(self) -> bool:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
import typer

from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies, build_dep_tree_path
from cycode.cli.files_collector.sca.npm.workspace import DENO_LOCK_FILE_NAME
from cycode.cli.models import Document
from cycode.cli.utils.path_utils import get_file_content
from cycode.logger import get_logger

logger = get_logger('Deno Restore Dependencies')

DENO_MANIFEST_FILE_NAMES = ('deno.json', 'deno.jsonc')
DENO_LOCK_FILE_NAME = 'deno.lock'


class RestoreDenoDependencies(BaseRestoreDependencies):
Expand Down
42 changes: 29 additions & 13 deletions cycode/cli/files_collector/sca/npm/restore_npm_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,25 @@
import typer

from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies
from cycode.cli.files_collector.sca.npm.workspace import (
BUN_LOCK_FILE_NAME,
DENO_LOCK_FILE_NAME,
MANIFEST_FILE_NAME,
NPM_LOCK_FILE_NAME,
NPM_SHRINKWRAP_FILE_NAME,
PNPM_LOCK_FILE_NAME,
YARN_LOCK_FILE_NAME,
is_covered_workspace_member,
)
from cycode.cli.models import Document
from cycode.cli.utils.path_utils import get_scan_roots_from_context
from cycode.logger import get_logger

logger = get_logger('NPM Restore Dependencies')

NPM_MANIFEST_FILE_NAME = 'package.json'
NPM_LOCK_FILE_NAME = 'package-lock.json'
NPM_MANIFEST_FILE_NAME = MANIFEST_FILE_NAME
# These lockfiles indicate another package manager owns the project — NPM should not run
_ALTERNATIVE_LOCK_FILES = ('yarn.lock', 'pnpm-lock.yaml', 'deno.lock', 'bun.lock')
_ALTERNATIVE_LOCK_FILES = (YARN_LOCK_FILE_NAME, PNPM_LOCK_FILE_NAME, DENO_LOCK_FILE_NAME, BUN_LOCK_FILE_NAME)


class RestoreNpmDependencies(BaseRestoreDependencies):
Expand All @@ -37,16 +47,18 @@ def is_project(self, document: Document) -> bool:
return False

manifest_dir = self.get_manifest_dir(document)
if manifest_dir:
for lock_file in _ALTERNATIVE_LOCK_FILES:
if (Path(manifest_dir) / lock_file).is_file():
logger.debug(
'Skipping npm restore: alternative lockfile detected, %s',
{'path': document.path, 'lockfile': lock_file},
)
return False
if not manifest_dir:
return True

return True
for lock_file in _ALTERNATIVE_LOCK_FILES:
if (Path(manifest_dir) / lock_file).is_file():
logger.debug(
'Skipping npm restore: alternative lockfile detected, %s',
{'path': document.path, 'lockfile': lock_file},
)
return False

return not is_covered_workspace_member(manifest_dir, document.path, get_scan_roots_from_context(self.ctx))

def get_commands(self, manifest_file_path: str) -> list[list[str]]:
return [
Expand All @@ -65,7 +77,11 @@ def get_lock_file_name(self) -> str:
return NPM_LOCK_FILE_NAME

def get_lock_file_names(self) -> list[str]:
return [NPM_LOCK_FILE_NAME]
return [NPM_LOCK_FILE_NAME, NPM_SHRINKWRAP_FILE_NAME]

def get_restored_lock_file_name(self, restore_file_path: str) -> str:
name = Path(restore_file_path).name
return name if name in self.get_lock_file_names() else self.get_lock_file_name()

@staticmethod
def prepare_manifest_file_path_for_command(manifest_file_path: str) -> str:
Expand Down
13 changes: 10 additions & 3 deletions cycode/cli/files_collector/sca/npm/restore_pnpm_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@
import typer

from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies, build_dep_tree_path
from cycode.cli.files_collector.sca.npm.workspace import (
MANIFEST_FILE_NAME,
PNPM_LOCK_FILE_NAME,
is_covered_workspace_member,
)
from cycode.cli.models import Document
from cycode.cli.utils.path_utils import get_file_content
from cycode.cli.utils.path_utils import get_file_content, get_scan_roots_from_context
from cycode.logger import get_logger

logger = get_logger('Pnpm Restore Dependencies')

PNPM_MANIFEST_FILE_NAME = 'package.json'
PNPM_LOCK_FILE_NAME = 'pnpm-lock.yaml'
PNPM_MANIFEST_FILE_NAME = MANIFEST_FILE_NAME


def _indicates_pnpm(package_json_content: Optional[str]) -> bool:
Expand Down Expand Up @@ -44,6 +48,9 @@ def is_project(self, document: Document) -> bool:
if manifest_dir and (Path(manifest_dir) / PNPM_LOCK_FILE_NAME).is_file():
return True

if is_covered_workspace_member(manifest_dir, document.path, get_scan_roots_from_context(self.ctx)):
return False

return _indicates_pnpm(document.content)

def try_restore_dependencies(self, document: Document) -> Optional[Document]:
Expand Down
13 changes: 10 additions & 3 deletions cycode/cli/files_collector/sca/npm/restore_yarn_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@
import typer

from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies, build_dep_tree_path
from cycode.cli.files_collector.sca.npm.workspace import (
MANIFEST_FILE_NAME,
YARN_LOCK_FILE_NAME,
is_covered_workspace_member,
)
from cycode.cli.models import Document
from cycode.cli.utils.path_utils import get_file_content
from cycode.cli.utils.path_utils import get_file_content, get_scan_roots_from_context
from cycode.logger import get_logger

logger = get_logger('Yarn Restore Dependencies')

YARN_MANIFEST_FILE_NAME = 'package.json'
YARN_LOCK_FILE_NAME = 'yarn.lock'
YARN_MANIFEST_FILE_NAME = MANIFEST_FILE_NAME


def _indicates_yarn(package_json_content: Optional[str]) -> bool:
Expand Down Expand Up @@ -44,6 +48,9 @@ def is_project(self, document: Document) -> bool:
if manifest_dir and (Path(manifest_dir) / YARN_LOCK_FILE_NAME).is_file():
return True

if is_covered_workspace_member(manifest_dir, document.path, get_scan_roots_from_context(self.ctx)):
return False

return _indicates_yarn(document.content)

def try_restore_dependencies(self, document: Document) -> Optional[Document]:
Expand Down
Loading