Skip to content

Commit 1b46e8b

Browse files
SLCORE-1212 Don't fail on git blaming newly created file
1 parent 47064da commit 1b46e8b

File tree

8 files changed

+119
-13
lines changed

8 files changed

+119
-13
lines changed

backend/commons/src/main/java/org/sonarsource/sonarlint/core/commons/util/git/GitUtils.java

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import org.sonarsource.sonarlint.core.commons.SonarLintGitIgnore;
5656
import org.sonarsource.sonarlint.core.commons.Version;
5757
import org.sonarsource.sonarlint.core.commons.log.SonarLintLogger;
58+
import org.sonarsource.sonarlint.core.commons.util.git.exceptions.GitRepoNotFoundException;
5859

5960
import static java.util.Optional.ofNullable;
6061
import static org.eclipse.jgit.lib.Constants.GITIGNORE_FILENAME;

backend/commons/src/main/java/org/sonarsource/sonarlint/core/commons/util/git/ProcessWrapperFactory.java

+19-3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import java.util.function.Consumer;
3131
import javax.annotation.Nullable;
3232
import org.sonarsource.sonarlint.core.commons.log.SonarLintLogger;
33+
import org.sonarsource.sonarlint.core.commons.util.git.exceptions.GitRepoNotFoundException;
34+
import org.sonarsource.sonarlint.core.commons.util.git.exceptions.NoSuchPathException;
3335

3436
import static java.lang.String.format;
3537
import static java.lang.String.join;
@@ -74,7 +76,15 @@ private static void processInputStream(InputStream inputStream, Consumer<String>
7476
}
7577

7678
private static boolean isNotAGitRepo(LinkedList<String> output) {
77-
return output.stream().anyMatch(line -> line.contains("not a git repository"));
79+
return outputContains(output, "not a git repository");
80+
}
81+
82+
private static boolean noSuchPath(LinkedList<String> output) {
83+
return outputContains(output, "no such path");
84+
}
85+
86+
private static boolean outputContains(LinkedList<String> output, String text) {
87+
return output.stream().anyMatch(line -> line.contains(text));
7888
}
7989

8090
public void execute() throws IOException {
@@ -104,8 +114,10 @@ public void execute() throws IOException {
104114
int exit = p.waitFor();
105115
if (exit != 0) {
106116
if (isNotAGitRepo(output)) {
107-
var dirStr = baseDir != null ? baseDir.toString() : "null";
108-
throw new GitRepoNotFoundException(dirStr);
117+
throw new GitRepoNotFoundException(getBaseDir());
118+
}
119+
if (noSuchPath(output)) {
120+
throw new NoSuchPathException(getBaseDir());
109121
}
110122
var gitBlameOutput = join(System.lineSeparator(), output);
111123
throw new IllegalStateException(format("Command execution exited with code: %d and error message: %s", exit, gitBlameOutput));
@@ -117,6 +129,10 @@ public void execute() throws IOException {
117129
p.destroy();
118130
}
119131
}
132+
133+
private String getBaseDir() {
134+
return baseDir != null ? baseDir.toString() : "null";
135+
}
120136
}
121137

122138
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* SonarLint Core - Commons
3+
* Copyright (C) 2016-2025 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonarsource.sonarlint.core.commons.util.git.exceptions;
21+
22+
public class GitException extends IllegalStateException {
23+
private final String path;
24+
25+
public GitException(String path) {
26+
this.path = path;
27+
}
28+
29+
public String getPath() {
30+
return path;
31+
}
32+
}

backend/commons/src/main/java/org/sonarsource/sonarlint/core/commons/util/git/GitRepoNotFoundException.java backend/commons/src/main/java/org/sonarsource/sonarlint/core/commons/util/git/exceptions/GitRepoNotFoundException.java

+3-7
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,12 @@
1717
* along with this program; if not, write to the Free Software Foundation,
1818
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1919
*/
20-
package org.sonarsource.sonarlint.core.commons.util.git;
20+
package org.sonarsource.sonarlint.core.commons.util.git.exceptions;
2121

22-
public class GitRepoNotFoundException extends IllegalStateException {
23-
private final String path;
22+
public class GitRepoNotFoundException extends GitException {
2423

2524
public GitRepoNotFoundException(String path) {
26-
this.path = path;
25+
super(path);
2726
}
2827

29-
public String getPath() {
30-
return path;
31-
}
3228
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* SonarLint Core - Commons
3+
* Copyright (C) 2016-2025 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonarsource.sonarlint.core.commons.util.git.exceptions;
21+
22+
public class NoSuchPathException extends GitException {
23+
public NoSuchPathException(String path) {
24+
super(path);
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* SonarLint Core - Commons
3+
* Copyright (C) 2016-2025 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
@ParametersAreNonnullByDefault
21+
package org.sonarsource.sonarlint.core.commons.util.git.exceptions;
22+
23+
import javax.annotation.ParametersAreNonnullByDefault;

backend/commons/src/test/java/org/sonarsource/sonarlint/core/commons/util/git/GitUtilsTest.java

+12
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import org.sonarsource.sonarlint.core.commons.LogTestStartAndEnd;
5454
import org.sonarsource.sonarlint.core.commons.log.LogOutput;
5555
import org.sonarsource.sonarlint.core.commons.log.SonarLintLogTester;
56+
import org.sonarsource.sonarlint.core.commons.util.git.exceptions.NoSuchPathException;
5657

5758
import static java.util.function.Predicate.not;
5859
import static org.assertj.core.api.Assertions.assertThat;
@@ -123,6 +124,17 @@ void it_should_blame_file() throws IOException, GitAPIException {
123124
.allMatch(date -> date.equals(c1));
124125
}
125126

127+
@Test
128+
void it_should_not_blame_new_file() throws IOException {
129+
createFile(projectDirPath, "fileA", "line1", "line2", "line3");
130+
131+
var fileAPath = projectDirPath.resolve("fileA");
132+
var filePaths = Set.of(fileAPath);
133+
var fileUris = Set.of(fileAPath.toUri());
134+
var now = Instant.now();
135+
assertThrows(NoSuchPathException.class, () -> getBlameResult(projectDirPath, filePaths, fileUris, path -> "", now));
136+
}
137+
126138
@Test
127139
void it_should_fallback_to_jgit_blame() throws IOException, GitAPIException {
128140
createFile(projectDirPath, "fileA", "line1", "line2", "line3");

backend/core/src/main/java/org/sonarsource/sonarlint/core/tracking/TrackingService.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
import org.sonarsource.sonarlint.core.commons.RuleType;
4545
import org.sonarsource.sonarlint.core.commons.SonarLintBlameResult;
4646
import org.sonarsource.sonarlint.core.commons.log.SonarLintLogger;
47-
import org.sonarsource.sonarlint.core.commons.util.git.GitRepoNotFoundException;
47+
import org.sonarsource.sonarlint.core.commons.util.git.exceptions.GitException;
4848
import org.sonarsource.sonarlint.core.file.PathTranslationService;
4949
import org.sonarsource.sonarlint.core.local.only.LocalOnlyIssueStorageService;
5050
import org.sonarsource.sonarlint.core.newcode.NewCodeService;
@@ -282,8 +282,8 @@ private IntroductionDateProvider getIntroductionDateProvider(String configuratio
282282
var thresholdDate = newCodeDefinition.map(NewCodeDefinition::getThresholdDate).orElse(NewCodeDefinition.withAlwaysNew().getThresholdDate());
283283
var sonarLintBlameResult = getBlameResult(baseDir, fileRelativePaths, fileUris, fileContentProvider, thresholdDate);
284284
return (filePath, lineNumbers) -> determineIntroductionDate(filePath, lineNumbers, sonarLintBlameResult);
285-
} catch (GitRepoNotFoundException e) {
286-
LOG.info("Git Repository not found for {}. The path {} is not in a Git repository", configurationScopeId, e.getPath());
285+
} catch (GitException e) {
286+
LOG.info("Could not get git blame data for file {} in {}. ", e.getPath(), configurationScopeId);
287287
} catch (Exception e) {
288288
LOG.error("Cannot access blame info for " + configurationScopeId, e);
289289
}

0 commit comments

Comments
 (0)