Skip to content

Commit adcca27

Browse files
authored
Skip symlinks for analysis (#611)
* Exclude symlinks from analysis * Attempt to capture Semgrep SARIF upon failure * Add unit test for symlink exclusion
1 parent 9679b51 commit adcca27

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

src/codemodder/codemodder.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -199,11 +199,15 @@ def run(original_args) -> int:
199199
log_list(logging.INFO, "including paths", included_paths)
200200
log_list(logging.INFO, "excluding paths", argv.path_exclude)
201201

202-
files_to_analyze: list[Path] = match_files(
203-
context.directory,
204-
argv.path_exclude,
205-
included_paths,
206-
)
202+
files_to_analyze: list[Path] = [
203+
path
204+
for path in match_files(
205+
context.directory,
206+
argv.path_exclude,
207+
included_paths,
208+
)
209+
if path.is_file() and not path.is_symlink()
210+
]
207211

208212
full_names = [str(path) for path in files_to_analyze]
209213
log_list(logging.DEBUG, "matched files", full_names)

src/codemodder/semgrep.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ def run(
110110
if call.returncode != 0:
111111
if not execution_context.verbose:
112112
logger.error("captured semgrep stderr: %s", call.stderr)
113+
try:
114+
logger.error("semgrep sarif output: %s", temp_sarif_file.read())
115+
except Exception as e:
116+
logger.error("failed to read semgrep sarif output: %s", e)
117+
113118
raise subprocess.CalledProcessError(call.returncode, command)
114119
# semgrep prepends the folders into the rule-id, we want the base name only
115120
results = InternalSemgrepResultSet.from_sarif(

tests/test_codemodder.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from codemodder.diff import create_diff_from_tree
99
from codemodder.registry import load_registered_codemods
1010
from codemodder.result import ResultSet
11+
from codemodder.semgrep import run as semgrep_run
1112

1213

1314
@pytest.fixture(autouse=True, scope="module")
@@ -74,6 +75,20 @@ def test_no_files_matched(self, mock_parse, dir_structure):
7475
mock_parse.assert_not_called()
7576
assert codetf.exists()
7677

78+
def test_skip_symlinks(self, mocker, dir_structure):
79+
# Override fixture for this specific test case
80+
mocker.patch("codemodder.codemods.semgrep.semgrep_run", semgrep_run)
81+
code_dir, codetf = dir_structure
82+
(code_dir / "symlink.py").symlink_to(code_dir / "test_request.py")
83+
args = [
84+
str(code_dir),
85+
"--output",
86+
str(codetf),
87+
"--codemod-include=url-sandbox",
88+
]
89+
res = run(args)
90+
assert res == 0
91+
7792
@mock.patch("libcst.parse_module", side_effect=Exception)
7893
@mock.patch("codemodder.codetf.CodeTF.build")
7994
def test_cst_parsing_fails(self, build_report, mock_parse, dir_structure):

0 commit comments

Comments
 (0)