Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Programming exercises: Fix broken download button for auxiliary repositories #8826

Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
iyannsch marked this conversation as resolved.
Show resolved Hide resolved
for (final AuxiliaryRepository repo : programmingExercise.getAuxiliaryRepositories()) {
final String repositoryName = programmingExercise.generateRepositoryName(repo.getName());
Expand All @@ -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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,12 @@ public ResponseEntity<ProgrammingExercise> 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ <h3 class="section-headline" [id]="headlinesRecord[section.headline]">{{ section
<ul>
@for (auxiliaryRepository of detail.data.auxiliaryRepositories; track auxiliaryRepository) {
@if (auxiliaryRepository.id && auxiliaryRepository.repositoryUri && detail.data.exerciseId) {
<li>
<li class="mt-2">
<span>Repository: {{ auxiliaryRepository.name }}</span>
<jhi-clone-repo-button class="ms-2" [smallButtons]="true" [repositoryUri]="auxiliaryRepository.repositoryUri" />
<jhi-programming-exercise-instructor-repo-download
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { downloadZipFileFromResponse } from 'app/shared/util/download.util';
import { AlertService } from 'app/core/util/alert.service';
import { faDownload } from '@fortawesome/free-solid-svg-icons';

iyannsch marked this conversation as resolved.
Show resolved Hide resolved
import { catchError } from 'rxjs/operators';
import { of } from 'rxjs';

@Component({
selector: 'jhi-programming-exercise-instructor-repo-download',
templateUrl: './programming-exercise-instructor-repo-download.component.html',
Expand Down Expand Up @@ -40,10 +43,23 @@ export class ProgrammingExerciseInstructorRepoDownloadComponent {

exportRepository() {
if (this.exerciseId && this.repositoryType) {
this.programmingExerciseService.exportInstructorRepository(this.exerciseId, this.repositoryType, this.auxiliaryRepositoryId).subscribe((response) => {
downloadZipFileFromResponse(response);
this.alertService.success('artemisApp.programmingExercise.export.successMessageRepo');
});
this.programmingExerciseService
.exportInstructorRepository(this.exerciseId, this.repositoryType, this.auxiliaryRepositoryId)
.pipe(
catchError((error) => {
if (error.status === 500 || error.status === 404) {
this.alertService.error('artemisApp.programmingExercise.export.errorMessageRepo');
}
// Return an observable of undefined so the subscribe method can continue
return of(undefined);
}),
)
.subscribe((response) => {
if (response !== undefined) {
downloadZipFileFromResponse(response);
this.alertService.success('artemisApp.programmingExercise.export.successMessageRepo');
}
});
iyannsch marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
3 changes: 2 additions & 1 deletion src/main/webapp/i18n/de/programmingExercise.json
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,8 @@
"successMessageRepo": "Das Repository wurde erfolgreich exportiert. Die generierte zip-Datei wird jetzt heruntergeladen.",
"successMessageRepos": "Die Repositories wurden erfolgreich exportiert. Die generierte zip-Datei wird jetzt heruntergeladen.",
"successMessageExercise": "Die Programmierübung wurde erfolgreich exportiert. Die generierte zip-Datei wird jetzt heruntergeladen.",
"notFoundMessageRepos": "Keine Repositories heruntergeladen für Aufgabe {{exerciseId}}: Es sind noch keine Abgaben der angegebenen Studenten vorhanden."
"notFoundMessageRepos": "Keine Repositories heruntergeladen für Aufgabe {{exerciseId}}: Es sind noch keine Abgaben der angegebenen Studenten vorhanden.",
"errorMessageRepo": "Das Repository konnte nicht exportiert werden. Die angefragte Datei existiert nicht."
},
"resubmitOnFailedSubmission": "Die letzte Abgabe konnte nicht bewertet werden. Klicke den Button, um die Abgabe erneut bewerten zu lassen. Diese Aktion führt einen neuen Build aus, der die Abgabe testet.",
"resubmit": "Die letzte Abgabe erneut bewerten. Diese Aktion führt einen Build auf dem Repository der Teilnahme aus ohne einen Commit zu machen.",
Expand Down
3 changes: 2 additions & 1 deletion src/main/webapp/i18n/en/programmingExercise.json
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,8 @@
"successMessageRepo": "Export of repo was successful. The exported zip file is currently being downloaded.",
"successMessageRepos": "Export of repos was successful. The exported zip file with all repositories is currently being downloaded.",
"successMessageExercise": "Export of exercise was successful. The exported zip file with all exercise material is currently being downloaded.",
"notFoundMessageRepos": "No repos exported for exercise {{exerciseId}}: There are no submissions from the given students."
"notFoundMessageRepos": "No repos exported for exercise {{exerciseId}}: There are no submissions from the given students.",
"errorMessageRepo": "Export of repo failed. The requested repository does not exist."
},
"resubmitOnFailedSubmission": "An automatic assessment for this participant's last submission could not be generated. Click the button to submit again. This will trigger a new build run that tests the last submission.",
"resubmit": "Resubmit the last submission. This will execute a build run on the participant's repository without making a commit.",
Expand Down
Loading