Search in sources :

Example 6 with Repository

use of de.tum.in.www1.artemis.domain.Repository in project ArTEMiS by ls1intum.

the class BitbucketService method forkRepository.

/**
 * Uses the configured Bitbucket account to fork the given repository inside the project.
 *
 * @param baseProjectKey     The project key of the base project.
 * @param baseRepositorySlug The repository slug of the base repository.
 * @param username           The user for whom the repository is being forked.
 * @return The slug of the forked repository (i.e. its identifier).
 */
private Map<String, String> forkRepository(String baseProjectKey, String baseRepositorySlug, String username) throws BitbucketException {
    String forkName = String.format("%s-%s", baseRepositorySlug, username);
    Map<String, Object> body = new HashMap<>();
    body.put("name", forkName);
    body.put("project", new HashMap<>());
    ((Map) body.get("project")).put("key", baseProjectKey);
    HttpHeaders headers = HeaderUtil.createAuthorization(BITBUCKET_USER, BITBUCKET_PASSWORD);
    HttpEntity<?> entity = new HttpEntity<>(body, headers);
    RestTemplate restTemplate = new RestTemplate();
    ResponseEntity<Map> response;
    try {
        response = restTemplate.exchange(BITBUCKET_SERVER_URL + "/rest/api/1.0/projects/" + baseProjectKey + "/repos/" + baseRepositorySlug, HttpMethod.POST, entity, Map.class);
    } catch (HttpClientErrorException e) {
        if (e.getStatusCode().equals(HttpStatus.CONFLICT)) {
            log.info("Repository already exists. Going to recover repository information...");
            Map<String, String> result = new HashMap<>();
            result.put("slug", forkName);
            result.put("cloneUrl", buildCloneUrl(baseProjectKey, forkName, username).toString());
            return result;
        } else {
            throw e;
        }
    } catch (Exception e) {
        log.error("Could not fork base repository for user " + username, e);
        throw new BitbucketException("Error while forking repository");
    }
    if (response != null && response.getStatusCode().equals(HttpStatus.CREATED)) {
        String slug = (String) response.getBody().get("slug");
        String cloneUrl = buildCloneUrl(baseProjectKey, forkName, username).toString();
        Map<String, String> result = new HashMap<>();
        result.put("slug", slug);
        result.put("cloneUrl", cloneUrl);
        return result;
    }
    return null;
}
Also used : HttpClientErrorException(org.springframework.web.client.HttpClientErrorException) HashMap(java.util.HashMap) MalformedURLException(java.net.MalformedURLException) BitbucketException(de.tum.in.www1.artemis.exception.BitbucketException) HttpClientErrorException(org.springframework.web.client.HttpClientErrorException) BitbucketException(de.tum.in.www1.artemis.exception.BitbucketException) RestTemplate(org.springframework.web.client.RestTemplate) HashMap(java.util.HashMap) Map(java.util.Map)

Example 7 with Repository

use of de.tum.in.www1.artemis.domain.Repository in project ArTEMiS by ls1intum.

the class ExerciseService method cleanup.

/**
 * Delete build plans (except BASE) and optionally repositores of all exercise participations.
 *
 * @param id id of the exercise for which build plans in respective participations are deleted
 */
@Transactional
public java.io.File cleanup(Long id, boolean deleteRepositories) throws java.io.IOException {
    Exercise exercise = findOneLoadParticipations(id);
    log.info("Request to cleanup all participations for Exercise : {}", exercise.getTitle());
    List<Repository> studentRepositories = new ArrayList<>();
    Path finalZipFilePath = null;
    if (Optional.ofNullable(exercise).isPresent() && exercise instanceof ProgrammingExercise) {
        exercise.getParticipations().forEach(participation -> {
            if (participation.getBuildPlanId() != null) {
                // ignore participations without build plan id
                try {
                    continuousIntegrationService.get().deleteBuildPlan(participation.getBuildPlanId());
                } catch (BambooException ex) {
                    log.error(ex.getMessage());
                    if (ex.getCause() != null) {
                        log.error(ex.getCause().getMessage());
                    }
                }
                participation.setInitializationState(ParticipationState.INACTIVE);
                participation.setBuildPlanId(null);
                participationService.save(participation);
            }
            if (deleteRepositories == true && participation.getRepositoryUrl() != null) {
                // ignore participations without repository URL
                try {
                    // 1. clone the repository
                    Repository repo = gitService.get().getOrCheckoutRepository(participation);
                    // 2. collect the repo file
                    studentRepositories.add(repo);
                } catch (GitAPIException | IOException ex) {
                    log.error("Archiving and deleting the repository " + participation.getRepositoryUrlAsUrl() + " did not work as expected", ex);
                }
            }
        });
        if (deleteRepositories == false) {
            // in this case, we are done
            return null;
        }
        if (studentRepositories.isEmpty()) {
            log.info("No student repositories have been found.");
            return null;
        }
        // from here on, deleteRepositories is true and does not need to be evaluated again
        log.info("Create zip file for all repositories");
        Files.createDirectories(Paths.get("zippedRepos"));
        finalZipFilePath = Paths.get("zippedRepos", exercise.getCourse().getTitle() + " " + exercise.getTitle() + " Student Repositories.zip");
        zipAllRepositories(studentRepositories, finalZipFilePath);
        exercise.getParticipations().forEach(participation -> {
            if (participation.getRepositoryUrl() != null) {
                // ignore participations without repository URL
                try {
                    // 3. delete the locally cloned repo again
                    gitService.get().deleteLocalRepository(participation);
                } catch (IOException e) {
                    log.error("Archiving and deleting the repository " + participation.getRepositoryUrlAsUrl() + " did not work as expected", e);
                }
                // 4. finally delete the repository on the VC Server
                versionControlService.get().deleteRepository(participation.getRepositoryUrlAsUrl());
                participation.setRepositoryUrl(null);
                participation.setInitializationState(ParticipationState.FINISHED);
                participationService.save(participation);
            }
        });
        scheduleForDeletion(finalZipFilePath, 300);
    } else {
        log.info("Exercise with id {} is not an instance of ProgrammingExercise. Ignoring the request to cleanup repositories and build plan", id);
        return null;
    }
    return new java.io.File(finalZipFilePath.toString());
}
Also used : Path(java.nio.file.Path) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) ExerciseRepository(de.tum.in.www1.artemis.repository.ExerciseRepository) BambooException(de.tum.in.www1.artemis.exception.BambooException) IOException(java.io.IOException) Transactional(org.springframework.transaction.annotation.Transactional)

Example 8 with Repository

use of de.tum.in.www1.artemis.domain.Repository in project ArTEMiS by ls1intum.

the class ExerciseService method zipAllRepositories.

public Path zipAllRepositories(List<Repository> repositories, Path zipFilePath) throws IOException {
    try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(zipFilePath))) {
        repositories.forEach(repository -> {
            Path repoPath = repository.getLocalPath();
            Path parentRepoPath = repoPath.getParent();
            try {
                Files.walk(repoPath).filter(path -> !Files.isDirectory(path)).forEach(path -> {
                    ZipEntry zipEntry = new ZipEntry(parentRepoPath.relativize(path).toString());
                    try {
                        zipOutputStream.putNextEntry(zipEntry);
                        Files.copy(path, zipOutputStream);
                        zipOutputStream.closeEntry();
                    } catch (Exception e) {
                        log.error("Create zip file error", e);
                    }
                });
            } catch (IOException e) {
                log.error("Create zip file error", e);
            }
        });
    }
    return zipFilePath;
}
Also used : Path(java.nio.file.Path) ZipOutputStream(java.util.zip.ZipOutputStream) java.util(java.util) ScheduledFuture(java.util.concurrent.ScheduledFuture) LoggerFactory(org.slf4j.LoggerFactory) ExerciseRepository(de.tum.in.www1.artemis.repository.ExerciseRepository) Service(org.springframework.stereotype.Service) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) Pageable(org.springframework.data.domain.Pageable) Path(java.nio.file.Path) ZipEntry(java.util.zip.ZipEntry) Logger(org.slf4j.Logger) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) Files(java.nio.file.Files) IOException(java.io.IOException) Page(org.springframework.data.domain.Page) Collectors(java.util.stream.Collectors) Executors(java.util.concurrent.Executors) BambooException(de.tum.in.www1.artemis.exception.BambooException) TimeUnit(java.util.concurrent.TimeUnit) ParticipationState(de.tum.in.www1.artemis.domain.enumeration.ParticipationState) de.tum.in.www1.artemis.domain(de.tum.in.www1.artemis.domain) Principal(java.security.Principal) Stream(java.util.stream.Stream) Paths(java.nio.file.Paths) PageImpl(org.springframework.data.domain.PageImpl) Transactional(org.springframework.transaction.annotation.Transactional) ZipOutputStream(java.util.zip.ZipOutputStream) ZipEntry(java.util.zip.ZipEntry) IOException(java.io.IOException) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) IOException(java.io.IOException) BambooException(de.tum.in.www1.artemis.exception.BambooException)

Example 9 with Repository

use of de.tum.in.www1.artemis.domain.Repository in project ArTEMiS by ls1intum.

the class GitService method getOrCheckoutRepository.

/**
 * Get the local repository for a given participation.
 * If the local repo does not exist yet, it will be checked out.
 *
 * @param participation Participation the remote repository belongs to.
 * @return
 * @throws IOException
 * @throws GitAPIException
 */
public Repository getOrCheckoutRepository(Participation participation) throws IOException, GitAPIException {
    URL repoUrl = participation.getRepositoryUrlAsUrl();
    Repository repository = getOrCheckoutRepository(repoUrl);
    repository.setParticipation(participation);
    return repository;
}
Also used : Repository(de.tum.in.www1.artemis.domain.Repository) URL(java.net.URL)

Example 10 with Repository

use of de.tum.in.www1.artemis.domain.Repository in project ArTEMiS by ls1intum.

the class GitService method getOrCheckoutRepository.

/**
 * Get the local repository for a given remote repository URL.
 * If the local repo does not exist yet, it will be checked out.
 *
 * @param repoUrl The remote repository.
 * @return
 * @throws IOException
 * @throws GitAPIException
 */
public Repository getOrCheckoutRepository(URL repoUrl) throws IOException, GitAPIException {
    Path localPath = new java.io.File(REPO_CLONE_PATH + folderNameForRepositoryUrl(repoUrl)).toPath();
    // check if Repository object already created and available in cachedRepositories
    if (cachedRepositories.containsKey(localPath)) {
        return cachedRepositories.get(localPath);
    }
    // Check if the repository is already checked out on the server
    if (!Files.exists(localPath)) {
        // Repository is not yet available on the server
        // We need to check it out from the remote repository
        log.info("Cloning from " + repoUrl + " to " + localPath);
        Git result = Git.cloneRepository().setURI(repoUrl.toString()).setCredentialsProvider(new UsernamePasswordCredentialsProvider(GIT_USER, GIT_PASSWORD)).setDirectory(localPath.toFile()).call();
        result.close();
    } else {
        log.info("Repository at " + localPath + " already exists");
    }
    // Open the repository from the filesystem
    FileRepositoryBuilder builder = new FileRepositoryBuilder();
    builder.setGitDir(new java.io.File(localPath + "/.git")).readEnvironment().findGitDir().setup();
    // Create the JGit repository object
    Repository repository = new Repository(builder);
    repository.setLocalPath(localPath);
    // Cache the JGit repository object for later use
    // Avoids the expensive re-opening of local repositories
    cachedRepositories.put(localPath, repository);
    return repository;
}
Also used : Path(java.nio.file.Path) UsernamePasswordCredentialsProvider(org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider) Repository(de.tum.in.www1.artemis.domain.Repository) Git(org.eclipse.jgit.api.Git) FileRepositoryBuilder(org.eclipse.jgit.storage.file.FileRepositoryBuilder) File(de.tum.in.www1.artemis.domain.File)

Aggregations

Repository (de.tum.in.www1.artemis.domain.Repository)9 Participation (de.tum.in.www1.artemis.domain.Participation)7 Test (org.junit.Test)6 SpringBootTest (org.springframework.boot.test.context.SpringBootTest)6 Path (java.nio.file.Path)5 BitbucketException (de.tum.in.www1.artemis.exception.BitbucketException)4 IOException (java.io.IOException)4 MalformedURLException (java.net.MalformedURLException)4 Git (org.eclipse.jgit.api.Git)4 GitAPIException (org.eclipse.jgit.api.errors.GitAPIException)4 HttpClientErrorException (org.springframework.web.client.HttpClientErrorException)4 RestTemplate (org.springframework.web.client.RestTemplate)4 File (de.tum.in.www1.artemis.domain.File)3 BambooException (de.tum.in.www1.artemis.exception.BambooException)3 ExerciseRepository (de.tum.in.www1.artemis.repository.ExerciseRepository)3 UsernamePasswordCredentialsProvider (org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider)3 Transactional (org.springframework.transaction.annotation.Transactional)3 File (java.io.File)2 URL (java.net.URL)2 Files (java.nio.file.Files)2