RepositoryService.java

1
package edu.ucsb.cs156.frontiers.services;
2
3
import com.fasterxml.jackson.core.JsonProcessingException;
4
import com.fasterxml.jackson.databind.JsonNode;
5
import com.fasterxml.jackson.databind.ObjectMapper;
6
import edu.ucsb.cs156.frontiers.entities.Course;
7
import edu.ucsb.cs156.frontiers.entities.CourseStaff;
8
import edu.ucsb.cs156.frontiers.entities.RosterStudent;
9
import edu.ucsb.cs156.frontiers.entities.Team;
10
import edu.ucsb.cs156.frontiers.enums.RepositoryPermissions;
11
import edu.ucsb.cs156.frontiers.repositories.TeamRepository;
12
import java.security.NoSuchAlgorithmException;
13
import java.security.spec.InvalidKeySpecException;
14
import java.util.ArrayList;
15
import java.util.HashMap;
16
import java.util.List;
17
import java.util.Map;
18
import lombok.extern.slf4j.Slf4j;
19
import org.springframework.boot.web.client.RestTemplateBuilder;
20
import org.springframework.http.*;
21
import org.springframework.stereotype.Service;
22
import org.springframework.web.client.HttpClientErrorException;
23
import org.springframework.web.client.RestTemplate;
24
25
@Service
26
@Slf4j
27
public class RepositoryService {
28
  private final JwtService jwtService;
29
  private final GithubTeamService githubTeamService;
30
  private final TeamRepository teamRepository;
31
  private final RestTemplate restTemplate;
32
  private final ObjectMapper mapper;
33
34
  /**
35
   * Creates a GitHub repository for a user (student or staff), given only their GitHub login.
36
   *
37
   * <p>This helper method contains the shared logic used by both {@link
38
   * #createStudentRepository(Course, RosterStudent, String, Boolean, RepositoryPermissions)} and
39
   * {@link #createStaffRepository(Course, CourseStaff, String, Boolean, RepositoryPermissions)}.
40
   *
41
   * <ul>
42
   *   <li>Checks whether the repository already exists.
43
   *   <li>If not, creates a new repository under the course's organization.
44
   *   <li>Adds the user as a collaborator with the given permission level.
45
   * </ul>
46
   *
47
   * @param course the course whose organization the repo belongs to
48
   * @param githubLogin GitHub username of the student or staff member
49
   * @param repoPrefix prefix for the repository name (repoPrefix-githubLogin)
50
   * @param isPrivate whether the created repository should be private
51
   * @param permissions collaborator permissions to grant the user
52
   * @throws NoSuchAlgorithmException if signing fails
53
   * @throws InvalidKeySpecException if signing fails
54
   * @throws JsonProcessingException if JSON serialization fails
55
   */
56
  private void createRepositoryForStudentOrStaff(
57
      Course course,
58
      String githubLogin,
59
      String repoPrefix,
60
      Boolean isPrivate,
61
      RepositoryPermissions permissions)
62
      throws NoSuchAlgorithmException, InvalidKeySpecException, JsonProcessingException {
63
64
    String newRepoName = repoPrefix + "-" + githubLogin;
65
    String token = jwtService.getInstallationToken(course);
66
67
    String existenceEndpoint =
68
        "https://api.github.com/repos/" + course.getOrgName() + "/" + newRepoName;
69
    String createEndpoint = "https://api.github.com/orgs/" + course.getOrgName() + "/repos";
70
    String provisionEndpoint =
71
        "https://api.github.com/repos/"
72
            + course.getOrgName()
73
            + "/"
74
            + newRepoName
75
            + "/collaborators/"
76
            + githubLogin;
77
78
    HttpHeaders existenceHeaders = new HttpHeaders();
79 1 1. createRepositoryForStudentOrStaff : removed call to org/springframework/http/HttpHeaders::add → KILLED
    existenceHeaders.add("Authorization", "Bearer " + token);
80 1 1. createRepositoryForStudentOrStaff : removed call to org/springframework/http/HttpHeaders::add → KILLED
    existenceHeaders.add("Accept", "application/vnd.github+json");
81 1 1. createRepositoryForStudentOrStaff : removed call to org/springframework/http/HttpHeaders::add → KILLED
    existenceHeaders.add("X-GitHub-Api-Version", "2022-11-28");
82
83
    HttpEntity<String> existenceEntity = new HttpEntity<>(existenceHeaders);
84
85
    try {
86
      restTemplate.exchange(existenceEndpoint, HttpMethod.GET, existenceEntity, String.class);
87
    } catch (HttpClientErrorException e) {
88 1 1. createRepositoryForStudentOrStaff : negated conditional → KILLED
      if (e.getStatusCode().equals(HttpStatus.NOT_FOUND)) {
89
        HttpHeaders createHeaders = new HttpHeaders();
90 1 1. createRepositoryForStudentOrStaff : removed call to org/springframework/http/HttpHeaders::add → KILLED
        createHeaders.add("Authorization", "Bearer " + token);
91 1 1. createRepositoryForStudentOrStaff : removed call to org/springframework/http/HttpHeaders::add → KILLED
        createHeaders.add("Accept", "application/vnd.github+json");
92 1 1. createRepositoryForStudentOrStaff : removed call to org/springframework/http/HttpHeaders::add → KILLED
        createHeaders.add("X-GitHub-Api-Version", "2022-11-28");
93
94
        Map<String, Object> body = new HashMap<>();
95
        body.put("name", newRepoName);
96
        body.put("private", isPrivate);
97
        String bodyAsJson = mapper.writeValueAsString(body);
98
99
        HttpEntity<String> createEntity = new HttpEntity<>(bodyAsJson, createHeaders);
100
101
        restTemplate.exchange(createEndpoint, HttpMethod.POST, createEntity, String.class);
102
      } else {
103
        log.warn(
104
            "Unexpected response code {} when checking for existence of repository {}",
105
            e.getStatusCode(),
106
            newRepoName);
107
        return;
108
      }
109
    }
110
111
    try {
112
      Map<String, Object> provisionBody = new HashMap<>();
113
      provisionBody.put("permission", permissions.getApiName());
114
      String provisionAsJson = mapper.writeValueAsString(provisionBody);
115
116
      HttpEntity<String> provisionEntity = new HttpEntity<>(provisionAsJson, existenceHeaders);
117
      restTemplate.exchange(provisionEndpoint, HttpMethod.PUT, provisionEntity, String.class);
118
    } catch (HttpClientErrorException ignored) {
119
      // silently ignore if provisioning fails (same as before)
120
    }
121
  }
122
123
  public RepositoryService(
124
      JwtService jwtService,
125
      GithubTeamService githubTeamService,
126
      TeamRepository teamRepository,
127
      RestTemplateBuilder restTemplateBuilder,
128
      ObjectMapper mapper) {
129
    this.jwtService = jwtService;
130
    this.githubTeamService = githubTeamService;
131
    this.teamRepository = teamRepository;
132
    this.restTemplate = restTemplateBuilder.build();
133
    this.mapper = mapper;
134
  }
135
136
  /**
137
   * Creates a single student repository if it doesn't already exist, and provisions access to the
138
   * repository by that student
139
   *
140
   * @param course The Course in question
141
   * @param student RosterStudent of the student the repository should be created for
142
   * @param repoPrefix Name of the project or assignment. Used to title the repository, in the
143
   *     format repoPrefix-githubLogin
144
   * @param isPrivate Whether the repository is private or not
145
   */
146
  public void createStudentRepository(
147
      Course course,
148
      RosterStudent student,
149
      String repoPrefix,
150
      Boolean isPrivate,
151
      RepositoryPermissions permissions)
152
      throws NoSuchAlgorithmException, InvalidKeySpecException, JsonProcessingException {
153 1 1. createStudentRepository : removed call to edu/ucsb/cs156/frontiers/services/RepositoryService::createRepositoryForStudentOrStaff → KILLED
    createRepositoryForStudentOrStaff(
154
        course, student.getGithubLogin(), repoPrefix, isPrivate, permissions);
155
  }
156
157
  /**
158
   * Creates a single staff repository if it doesn't already exist, and provisions access to the
159
   * repository by that staff member
160
   *
161
   * @param course The Course in question
162
   * @param staff CourseStaff of the staff the repository should be created for
163
   * @param repoPrefix Name of the project or assignment. Used to title the repository, in the
164
   *     format repoPrefix-githubLogin
165
   * @param isPrivate Whether the repository is private or not
166
   */
167
  public void createStaffRepository(
168
      Course course,
169
      CourseStaff staff,
170
      String repoPrefix,
171
      Boolean isPrivate,
172
      RepositoryPermissions permissions)
173
      throws NoSuchAlgorithmException, InvalidKeySpecException, JsonProcessingException {
174
175 1 1. createStaffRepository : removed call to edu/ucsb/cs156/frontiers/services/RepositoryService::createRepositoryForStudentOrStaff → KILLED
    createRepositoryForStudentOrStaff(
176
        course, staff.getGithubLogin(), repoPrefix, isPrivate, permissions);
177
  }
178
179
  /**
180
   * Creates a GitHub repository for a team (student or staff), given only their team name.
181
   *
182
   * <ul>
183
   *   <li>Checks whether the repository already exists.
184
   *   <li>If not, creates a new repository under the course's organization.
185
   *   <li>Adds all team members as collaborators with the given permission level.
186
   * </ul>
187
   *
188
   * @param course the course whose organization the repo belongs to
189
   * @param team the team for which the repo is being created
190
   * @param repoPrefix prefix for the repository name (repoPrefix-teamSlug)
191
   * @param isPrivate whether the created repository should be private
192
   * @param permissions collaborator permissions to grant the user
193
   * @param orgId GitHub organization ID used for team-based repo provisioning
194
   * @throws NoSuchAlgorithmException if signing fails
195
   * @throws InvalidKeySpecException if signing fails
196
   * @throws JsonProcessingException if JSON serialization fails
197
   */
198
  public void createTeamRepository(
199
      Course course,
200
      Team team,
201
      String repoPrefix,
202
      Boolean isPrivate,
203
      RepositoryPermissions permissions,
204
      Integer orgId)
205
      throws NoSuchAlgorithmException, InvalidKeySpecException, JsonProcessingException {
206
    String teamSlug = getOrFetchTeamSlug(course, team, orgId);
207
    String newRepoName = repoPrefix + "-" + teamSlug;
208
    String token = jwtService.getInstallationToken(course);
209
210
    String existenceEndpoint =
211
        "https://api.github.com/repos/" + course.getOrgName() + "/" + newRepoName;
212
    String createEndpoint = "https://api.github.com/orgs/" + course.getOrgName() + "/repos";
213
    String provisionEndpoint =
214
        "https://api.github.com/organizations/"
215
            + orgId
216
            + "/team/"
217
            + team.getGithubTeamId()
218
            + "/repos/"
219
            + course.getOrgName()
220
            + "/"
221
            + newRepoName;
222
223
    HttpHeaders existenceHeaders = new HttpHeaders();
224 1 1. createTeamRepository : removed call to org/springframework/http/HttpHeaders::add → KILLED
    existenceHeaders.add("Authorization", "Bearer " + token);
225 1 1. createTeamRepository : removed call to org/springframework/http/HttpHeaders::add → KILLED
    existenceHeaders.add("Accept", "application/vnd.github+json");
226 1 1. createTeamRepository : removed call to org/springframework/http/HttpHeaders::add → KILLED
    existenceHeaders.add("X-GitHub-Api-Version", "2022-11-28");
227
228
    HttpEntity<String> existenceEntity = new HttpEntity<>(existenceHeaders);
229
230
    try {
231
      restTemplate.exchange(existenceEndpoint, HttpMethod.GET, existenceEntity, String.class);
232
    } catch (HttpClientErrorException e) {
233 1 1. createTeamRepository : negated conditional → KILLED
      if (e.getStatusCode().equals(HttpStatus.NOT_FOUND)) {
234
        HttpHeaders createHeaders = new HttpHeaders();
235 1 1. createTeamRepository : removed call to org/springframework/http/HttpHeaders::add → KILLED
        createHeaders.add("Authorization", "Bearer " + token);
236 1 1. createTeamRepository : removed call to org/springframework/http/HttpHeaders::add → KILLED
        createHeaders.add("Accept", "application/vnd.github+json");
237 1 1. createTeamRepository : removed call to org/springframework/http/HttpHeaders::add → KILLED
        createHeaders.add("X-GitHub-Api-Version", "2022-11-28");
238
239
        Map<String, Object> body = new HashMap<>();
240
        body.put("name", newRepoName);
241
        body.put("private", isPrivate);
242
        String bodyAsJson = mapper.writeValueAsString(body);
243
244
        HttpEntity<String> createEntity = new HttpEntity<>(bodyAsJson, createHeaders);
245
246
        restTemplate.exchange(createEndpoint, HttpMethod.POST, createEntity, String.class);
247
      } else {
248
        log.warn(
249
            "Unexpected response code {} when checking for existence of repository {}",
250
            e.getStatusCode(),
251
            newRepoName);
252
        return;
253
      }
254
    }
255
    try {
256
      Map<String, Object> provisionBody = new HashMap<>();
257
      provisionBody.put("permission", permissions.getApiName());
258
      String provisionAsJson = mapper.writeValueAsString(provisionBody);
259
260
      HttpEntity<String> provisionEntity = new HttpEntity<>(provisionAsJson, existenceHeaders);
261
      restTemplate.exchange(provisionEndpoint, HttpMethod.PUT, provisionEntity, String.class);
262
    } catch (HttpClientErrorException ignored) {
263
      // silently ignore if provisioning fails (same as before)
264
    }
265
  }
266
267
  private String getOrFetchTeamSlug(Course course, Team team, Integer orgId)
268
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
269 2 1. getOrFetchTeamSlug : negated conditional → KILLED
2. getOrFetchTeamSlug : negated conditional → KILLED
    if (team.getGithubTeamSlug() != null && !team.getGithubTeamSlug().isBlank()) {
270 1 1. getOrFetchTeamSlug : replaced return value with "" for edu/ucsb/cs156/frontiers/services/RepositoryService::getOrFetchTeamSlug → KILLED
      return team.getGithubTeamSlug();
271
    }
272
273 1 1. getOrFetchTeamSlug : negated conditional → KILLED
    if (team.getGithubTeamId() == null) {
274
      throw new IllegalStateException(
275
          "Cannot create team repository without a GitHub team ID for team '"
276
              + team.getName()
277
              + "'");
278
    }
279
280
    GithubTeamService.GithubTeamInfo teamInfo =
281
        githubTeamService.getTeamInfoById(orgId, team.getGithubTeamId(), course);
282
283 3 1. getOrFetchTeamSlug : negated conditional → KILLED
2. getOrFetchTeamSlug : negated conditional → KILLED
3. getOrFetchTeamSlug : negated conditional → KILLED
    if (teamInfo == null || teamInfo.slug() == null || teamInfo.slug().isBlank()) {
284
      throw new IllegalStateException(
285
          "Cannot determine GitHub team slug for team '" + team.getName() + "'");
286
    }
287
288 1 1. getOrFetchTeamSlug : removed call to edu/ucsb/cs156/frontiers/entities/Team::setGithubTeamSlug → KILLED
    team.setGithubTeamSlug(teamInfo.slug());
289
    teamRepository.save(team);
290 1 1. getOrFetchTeamSlug : replaced return value with "" for edu/ucsb/cs156/frontiers/services/RepositoryService::getOrFetchTeamSlug → KILLED
    return teamInfo.slug();
291
  }
292
293
  /** Gets all repositories in the course's organization that start with the given prefix. */
294
  public List<String> getRepoNamesWithPrefix(Course course, String prefix)
295
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
296
    String token = jwtService.getInstallationToken(course);
297
    String endpoint = "https://api.github.com/orgs/" + course.getOrgName() + "/repos?per_page=100";
298
299
    HttpHeaders headers = new HttpHeaders();
300 1 1. getRepoNamesWithPrefix : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Authorization", "Bearer " + token);
301 1 1. getRepoNamesWithPrefix : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Accept", "application/vnd.github+json");
302 1 1. getRepoNamesWithPrefix : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("X-GitHub-Api-Version", "2022-11-28");
303
304
    HttpEntity<String> entity = new HttpEntity<>(headers);
305
    ResponseEntity<String> response =
306
        restTemplate.exchange(endpoint, HttpMethod.GET, entity, String.class);
307
308
    JsonNode root = mapper.readTree(response.getBody());
309
    List<String> matchingRepos = new ArrayList<>();
310
311
    for (JsonNode repoNode : root) {
312
      String name = repoNode.get("name").asText();
313 1 1. getRepoNamesWithPrefix : negated conditional → KILLED
      if (name.startsWith(prefix)) {
314
        matchingRepos.add(name);
315
      }
316
    }
317 1 1. getRepoNamesWithPrefix : replaced return value with Collections.emptyList for edu/ucsb/cs156/frontiers/services/RepositoryService::getRepoNamesWithPrefix → KILLED
    return matchingRepos;
318
  }
319
320
  /** Checks if a repository has any commits. */
321
  public boolean repoHasCommits(Course course, String repoName)
322
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
323
    String token = jwtService.getInstallationToken(course);
324
    String endpoint =
325
        "https://api.github.com/repos/"
326
            + course.getOrgName()
327
            + "/"
328
            + repoName
329
            + "/commits?per_page=1";
330
331
    HttpHeaders headers = new HttpHeaders();
332 1 1. repoHasCommits : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Authorization", "Bearer " + token);
333 1 1. repoHasCommits : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Accept", "application/vnd.github+json");
334 1 1. repoHasCommits : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("X-GitHub-Api-Version", "2022-11-28");
335
336
    HttpEntity<String> entity = new HttpEntity<>(headers);
337
338
    try {
339
      restTemplate.exchange(endpoint, HttpMethod.GET, entity, String.class);
340 1 1. repoHasCommits : replaced boolean return with false for edu/ucsb/cs156/frontiers/services/RepositoryService::repoHasCommits → KILLED
      return true; // Pitest BooleanTrueReturnValsMutator killed here
341
    } catch (HttpClientErrorException e) {
342 1 1. repoHasCommits : negated conditional → KILLED
      if (e.getStatusCode() == HttpStatus.CONFLICT) {
343 1 1. repoHasCommits : replaced boolean return with true for edu/ucsb/cs156/frontiers/services/RepositoryService::repoHasCommits → KILLED
        return false;
344
      }
345
      throw e;
346
    }
347
  }
348
349
  /** Deletes a repository using the GitHub REST API. */
350
  public void deleteRepository(Course course, String repoName)
351
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
352
    String token = jwtService.getInstallationToken(course);
353
    String endpoint = "https://api.github.com/repos/" + course.getOrgName() + "/" + repoName;
354
355
    HttpHeaders headers = new HttpHeaders();
356 1 1. deleteRepository : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Authorization", "Bearer " + token);
357 1 1. deleteRepository : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Accept", "application/vnd.github+json");
358 1 1. deleteRepository : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("X-GitHub-Api-Version", "2022-11-28");
359
360
    HttpEntity<String> entity = new HttpEntity<>(headers);
361
    restTemplate.exchange(endpoint, HttpMethod.DELETE, entity, String.class);
362
  }
363
}

Mutations

79

1.1
Location : createRepositoryForStudentOrStaff
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:exits_if_not_not_found()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

80

1.1
Location : createRepositoryForStudentOrStaff
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:exits_if_not_not_found()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

81

1.1
Location : createRepositoryForStudentOrStaff
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:exits_if_not_not_found()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

88

1.1
Location : createRepositoryForStudentOrStaff
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:exits_if_not_not_found()]
negated conditional → KILLED

90

1.1
Location : createRepositoryForStudentOrStaff
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:successfully_creates_repo_private()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

91

1.1
Location : createRepositoryForStudentOrStaff
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:successfully_creates_repo_private()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

92

1.1
Location : createRepositoryForStudentOrStaff
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:successfully_creates_repo_private()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

153

1.1
Location : createStudentRepository
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:exits_if_not_not_found()]
removed call to edu/ucsb/cs156/frontiers/services/RepositoryService::createRepositoryForStudentOrStaff → KILLED

175

1.1
Location : createStaffRepository
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:successfully_creates_staff_repo_public()]
removed call to edu/ucsb/cs156/frontiers/services/RepositoryService::createRepositoryForStudentOrStaff → KILLED

224

1.1
Location : createTeamRepository
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:exits_if_team_repo_not_not_found()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

225

1.1
Location : createTeamRepository
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:exits_if_team_repo_not_not_found()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

226

1.1
Location : createTeamRepository
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:exits_if_team_repo_not_not_found()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

233

1.1
Location : createTeamRepository
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:exits_if_team_repo_not_not_found()]
negated conditional → KILLED

235

1.1
Location : createTeamRepository
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:successfully_creates_team_repo_private()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

236

1.1
Location : createTeamRepository
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:successfully_creates_team_repo_private()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

237

1.1
Location : createTeamRepository
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:successfully_creates_team_repo_private()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

269

1.1
Location : getOrFetchTeamSlug
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:team_repo_throws_when_slug_missing_and_team_id_missing()]
negated conditional → KILLED

2.2
Location : getOrFetchTeamSlug
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:exits_if_team_repo_not_not_found()]
negated conditional → KILLED

270

1.1
Location : getOrFetchTeamSlug
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:exits_if_team_repo_not_not_found()]
replaced return value with "" for edu/ucsb/cs156/frontiers/services/RepositoryService::getOrFetchTeamSlug → KILLED

273

1.1
Location : getOrFetchTeamSlug
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:team_repo_throws_when_slug_missing_and_team_id_missing()]
negated conditional → KILLED

283

1.1
Location : getOrFetchTeamSlug
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:team_repo_throws_when_fetched_team_slug_is_blank()]
negated conditional → KILLED

2.2
Location : getOrFetchTeamSlug
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:team_repo_throws_when_fetched_team_slug_is_null()]
negated conditional → KILLED

3.3
Location : getOrFetchTeamSlug
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:team_repo_throws_when_fetched_team_info_is_null()]
negated conditional → KILLED

288

1.1
Location : getOrFetchTeamSlug
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:team_repo_fetches_and_persists_slug_when_missing()]
removed call to edu/ucsb/cs156/frontiers/entities/Team::setGithubTeamSlug → KILLED

290

1.1
Location : getOrFetchTeamSlug
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:team_repo_fetches_and_persists_slug_when_missing()]
replaced return value with "" for edu/ucsb/cs156/frontiers/services/RepositoryService::getOrFetchTeamSlug → KILLED

300

1.1
Location : getRepoNamesWithPrefix
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:getRepoNamesWithPrefix_returns_filtered_list()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

301

1.1
Location : getRepoNamesWithPrefix
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:getRepoNamesWithPrefix_returns_filtered_list()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

302

1.1
Location : getRepoNamesWithPrefix
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:getRepoNamesWithPrefix_returns_filtered_list()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

313

1.1
Location : getRepoNamesWithPrefix
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:getRepoNamesWithPrefix_returns_filtered_list()]
negated conditional → KILLED

317

1.1
Location : getRepoNamesWithPrefix
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:getRepoNamesWithPrefix_returns_filtered_list()]
replaced return value with Collections.emptyList for edu/ucsb/cs156/frontiers/services/RepositoryService::getRepoNamesWithPrefix → KILLED

332

1.1
Location : repoHasCommits
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:repoHasCommits_returns_true_when_200_OK()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

333

1.1
Location : repoHasCommits
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:repoHasCommits_returns_true_when_200_OK()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

334

1.1
Location : repoHasCommits
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:repoHasCommits_returns_true_when_200_OK()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

340

1.1
Location : repoHasCommits
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:repoHasCommits_returns_true_when_200_OK()]
replaced boolean return with false for edu/ucsb/cs156/frontiers/services/RepositoryService::repoHasCommits → KILLED

342

1.1
Location : repoHasCommits
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:repoHasCommits_returns_false_when_409_Conflict()]
negated conditional → KILLED

343

1.1
Location : repoHasCommits
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:repoHasCommits_returns_false_when_409_Conflict()]
replaced boolean return with true for edu/ucsb/cs156/frontiers/services/RepositoryService::repoHasCommits → KILLED

356

1.1
Location : deleteRepository
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:deleteRepository_successfully_sends_delete_request()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

357

1.1
Location : deleteRepository
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:deleteRepository_successfully_sends_delete_request()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

358

1.1
Location : deleteRepository
Killed by : edu.ucsb.cs156.frontiers.services.RepositoryServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.RepositoryServiceTests]/[method:deleteRepository_successfully_sends_delete_request()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0