diff --git a/src/main/java/de/tum/in/www1/artemis/service/programming/ProgrammingExerciseRepositoryService.java b/src/main/java/de/tum/in/www1/artemis/service/programming/ProgrammingExerciseRepositoryService.java index f60ddf2fca53..2f219a695cc6 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/programming/ProgrammingExerciseRepositoryService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/programming/ProgrammingExerciseRepositoryService.java @@ -229,6 +229,13 @@ void createRepositoriesForNewExercise(final ProgrammingExercise programmingExerc createAndInitializeAuxiliaryRepositories(projectKey, programmingExercise); } + /** + * Creates and initializes all auxiliary repositories for a new programming exercise. + * + * @param projectKey The key of the project the exercise belongs to. Can be found in the programming exercise. + * @param programmingExercise The programming exercise for which the auxiliary repositories should be created. + * @throws GitAPIException Thrown in case creating a repository fails. + */ private void createAndInitializeAuxiliaryRepositories(final String projectKey, final ProgrammingExercise programmingExercise) throws GitAPIException { for (final AuxiliaryRepository repo : programmingExercise.getAuxiliaryRepositories()) { final String repositoryName = programmingExercise.generateRepositoryName(repo.getName()); @@ -240,6 +247,56 @@ private void createAndInitializeAuxiliaryRepositories(final String projectKey, f } } + /** + * Handles the VC part of auxiliary repositories when updating a programming exercise. Does not modify the database. + * + * @param programmingExerciseBeforeUpdate The programming exercise before the update + * @param updatedProgrammingExercise The programming exercise after the update + */ + public void handleAuxiliaryRepositoriesWhenUpdatingExercises(ProgrammingExercise programmingExerciseBeforeUpdate, ProgrammingExercise updatedProgrammingExercise) { + // Create new VC repositories for new auxiliary repositories + updatedProgrammingExercise.getAuxiliaryRepositories().stream().filter(repo -> (repo.getId() == null)).forEach(repo -> { + try { + createAndInitializeAuxiliaryRepository(updatedProgrammingExercise, repo); + } + catch (GitAPIException ex) { + log.error("Could not create new auxiliary repository", ex); + } + }); + + // Remove VC repositories for deleted auxiliary repositories + programmingExerciseBeforeUpdate.getAuxiliaryRepositories().stream() + .filter(repo -> updatedProgrammingExercise.getAuxiliaryRepositories().stream().noneMatch(updatedRepo -> repo.getId().equals(updatedRepo.getId()))) + .forEach(this::removeAuxiliaryRepository); + } + + /** + * Creates and initializes a specific auxiliary repository if not existent. + * + * @param programmingExercise The programming exercise for which the repository should be created. + * @throws GitAPIException Thrown in case creating the repository fails. + */ + private void createAndInitializeAuxiliaryRepository(final ProgrammingExercise programmingExercise, final AuxiliaryRepository repo) throws GitAPIException { + final String repositoryName = programmingExercise.generateRepositoryName(repo.getName()); + versionControlService.orElseThrow().createRepository(programmingExercise.getProjectKey(), repositoryName, null); + repo.setRepositoryUri(versionControlService.orElseThrow().getCloneRepositoryUri(programmingExercise.getProjectKey(), repositoryName).toString()); + + final Repository vcsRepository = gitService.getOrCheckoutRepository(repo.getVcsRepositoryUri(), true); + gitService.commitAndPush(vcsRepository, SETUP_COMMIT_MESSAGE, true, null); + } + + /** + * Deletes an auxiliary repository from the version control system if existent. Performs no DB changes. + * + * @param auxiliaryRepository The auxiliary repository to delete. + */ + private void removeAuxiliaryRepository(AuxiliaryRepository auxiliaryRepository) { + if (auxiliaryRepository.getId() == null) { + throw new IllegalArgumentException("Cannot delete auxiliary repository without id"); + } + versionControlService.orElseThrow().deleteRepository(auxiliaryRepository.getVcsRepositoryUri()); + } + /** * Copy template and push, if no file is currently in the repository. * diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java index fdead0c65162..7e24cd235db5 100644 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java @@ -327,8 +327,12 @@ public ResponseEntity updateProgrammingExercise(@RequestBod updatedProgrammingExercise.setAuxiliaryRepositories(new ArrayList<>()); } + // Update the auxiliary repositories in the DB and ProgrammingExercise instance auxiliaryRepositoryService.handleAuxiliaryRepositoriesWhenUpdatingExercises(programmingExerciseBeforeUpdate, updatedProgrammingExercise); + // Update the auxiliary repositories in the VCS. This needs to be decoupled to break circular dependencies. + programmingExerciseRepositoryService.handleAuxiliaryRepositoriesWhenUpdatingExercises(programmingExerciseBeforeUpdate, updatedProgrammingExercise); + if (updatedProgrammingExercise.getBonusPoints() == null) { // make sure the default value is set properly updatedProgrammingExercise.setBonusPoints(0.0); diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html index d78aba39991a..ab9a26940a13 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html @@ -80,7 +80,7 @@

{{ section