Search in sources :

Example 1 with RepositoryFunctionException

use of com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException in project bazel by bazelbuild.

the class DecompressorValueTest method testUnknownFileExtensionsThrow.

@Test
public void testUnknownFileExtensionsThrow() throws Exception {
    Path zipPath = fs.getPath("/foo/.external-repositories/some-repo/bar.baz");
    try {
        DecompressorDescriptor.builder().setArchivePath(zipPath).build();
        fail(".baz isn't a valid suffix");
    } catch (RepositoryFunctionException expected) {
        assertThat(expected.getMessage()).contains("Expected a file with a .zip, .jar,");
    }
}
Also used : Path(com.google.devtools.build.lib.vfs.Path) RepositoryFunctionException(com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException) Test(org.junit.Test)

Example 2 with RepositoryFunctionException

use of com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException in project bazel by bazelbuild.

the class CompressedTarFunction method decompress.

@Override
public Path decompress(DecompressorDescriptor descriptor) throws RepositoryFunctionException {
    Optional<String> prefix = descriptor.prefix();
    boolean foundPrefix = false;
    try (InputStream decompressorStream = getDecompressorStream(descriptor)) {
        TarArchiveInputStream tarStream = new TarArchiveInputStream(decompressorStream);
        TarArchiveEntry entry;
        while ((entry = tarStream.getNextTarEntry()) != null) {
            StripPrefixedPath entryPath = StripPrefixedPath.maybeDeprefix(entry.getName(), prefix);
            foundPrefix = foundPrefix || entryPath.foundPrefix();
            if (entryPath.skip()) {
                continue;
            }
            Path filename = descriptor.repositoryPath().getRelative(entryPath.getPathFragment());
            FileSystemUtils.createDirectoryAndParents(filename.getParentDirectory());
            if (entry.isDirectory()) {
                FileSystemUtils.createDirectoryAndParents(filename);
            } else {
                if (entry.isSymbolicLink() || entry.isLink()) {
                    PathFragment linkName = new PathFragment(entry.getLinkName());
                    boolean wasAbsolute = linkName.isAbsolute();
                    // Strip the prefix from the link path if set.
                    linkName = StripPrefixedPath.maybeDeprefix(linkName.getPathString(), prefix).getPathFragment();
                    if (wasAbsolute) {
                        // Recover the path to an absolute path as maybeDeprefix() relativize the path
                        // even if the prefix is not set
                        linkName = descriptor.repositoryPath().getRelative(linkName).asFragment();
                    }
                    if (entry.isSymbolicLink()) {
                        FileSystemUtils.ensureSymbolicLink(filename, linkName);
                    } else {
                        FileSystemUtils.createHardLink(filename, descriptor.repositoryPath().getRelative(linkName));
                    }
                } else {
                    Files.copy(tarStream, filename.getPathFile().toPath(), StandardCopyOption.REPLACE_EXISTING);
                    filename.chmod(entry.getMode());
                    // This can only be done on real files, not links, or it will skip the reader to
                    // the next "real" file to try to find the mod time info.
                    Date lastModified = entry.getLastModifiedDate();
                    filename.setLastModifiedTime(lastModified.getTime());
                }
            }
        }
    } catch (IOException e) {
        throw new RepositoryFunctionException(e, Transience.TRANSIENT);
    }
    if (prefix.isPresent() && !foundPrefix) {
        throw new RepositoryFunctionException(new IOException("Prefix " + prefix.get() + " was given, but not found in the archive"), Transience.PERSISTENT);
    }
    return descriptor.repositoryPath();
}
Also used : TarArchiveInputStream(org.apache.commons.compress.archivers.tar.TarArchiveInputStream) Path(com.google.devtools.build.lib.vfs.Path) TarArchiveInputStream(org.apache.commons.compress.archivers.tar.TarArchiveInputStream) InputStream(java.io.InputStream) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) IOException(java.io.IOException) TarArchiveEntry(org.apache.commons.compress.archivers.tar.TarArchiveEntry) Date(java.util.Date) RepositoryFunctionException(com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException)

Example 3 with RepositoryFunctionException

use of com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException in project bazel by bazelbuild.

the class GitCloner method clone.

public static SkyValue clone(Rule rule, Path outputDirectory, ExtendedEventHandler eventHandler, Map<String, String> clientEnvironment) throws RepositoryFunctionException {
    WorkspaceAttributeMapper mapper = WorkspaceAttributeMapper.of(rule);
    if (mapper.isAttributeValueExplicitlySpecified("commit") == mapper.isAttributeValueExplicitlySpecified("tag")) {
        throw new RepositoryFunctionException(new EvalException(rule.getLocation(), "One of either commit or tag must be defined"), Transience.PERSISTENT);
    }
    GitRepositoryDescriptor descriptor;
    String startingPoint;
    try {
        if (mapper.isAttributeValueExplicitlySpecified("commit")) {
            startingPoint = mapper.get("commit", Type.STRING);
        } else {
            startingPoint = "tags/" + mapper.get("tag", Type.STRING);
        }
        descriptor = new GitRepositoryDescriptor(mapper.get("remote", Type.STRING), startingPoint, mapper.get("init_submodules", Type.BOOLEAN), outputDirectory);
    } catch (EvalException e) {
        throw new RepositoryFunctionException(e, Transience.PERSISTENT);
    }
    // Setup proxy if remote is http or https
    if (descriptor.remote != null && Ascii.toLowerCase(descriptor.remote).startsWith("http")) {
        try {
            new ProxyHelper(clientEnvironment).createProxyIfNeeded(new URL(descriptor.remote));
        } catch (IOException ie) {
            throw new RepositoryFunctionException(ie, Transience.TRANSIENT);
        }
    }
    Git git = null;
    try {
        if (descriptor.directory.exists()) {
            if (isUpToDate(descriptor)) {
                return new HttpDownloadValue(descriptor.directory);
            }
            try {
                FileSystemUtils.deleteTree(descriptor.directory);
            } catch (IOException e) {
                throw new RepositoryFunctionException(e, Transience.TRANSIENT);
            }
        }
        git = Git.cloneRepository().setURI(descriptor.remote).setCredentialsProvider(new NetRCCredentialsProvider()).setDirectory(descriptor.directory.getPathFile()).setCloneSubmodules(false).setNoCheckout(true).setProgressMonitor(new GitProgressMonitor(descriptor.remote, "Cloning " + descriptor.remote, eventHandler)).call();
        git.checkout().setCreateBranch(true).setName("bazel-checkout").setStartPoint(descriptor.checkout).call();
        // the first level.
        if (descriptor.initSubmodules && !git.submoduleInit().call().isEmpty()) {
            git.submoduleUpdate().setProgressMonitor(new GitProgressMonitor(descriptor.remote, "Cloning submodules for " + descriptor.remote, eventHandler)).call();
        }
    } catch (InvalidRemoteException e) {
        throw new RepositoryFunctionException(new IOException("Invalid Git repository URI: " + e.getMessage()), Transience.PERSISTENT);
    } catch (RefNotFoundException | InvalidRefNameException e) {
        throw new RepositoryFunctionException(new IOException("Invalid branch, tag, or commit: " + e.getMessage()), Transience.PERSISTENT);
    } catch (GitAPIException e) {
        // This is a sad attempt to actually get a useful error message out of jGit, which will bury
        // the actual (useful) cause of the exception under several throws.
        StringBuilder errmsg = new StringBuilder();
        errmsg.append(e.getMessage());
        Throwable throwable = e;
        while (throwable.getCause() != null) {
            throwable = throwable.getCause();
            errmsg.append(" caused by " + throwable.getMessage());
        }
        throw new RepositoryFunctionException(new IOException("Error cloning repository: " + errmsg), Transience.PERSISTENT);
    } catch (JGitInternalException e) {
        // caller of the command can handle them effectively." Thanks, jgit.
        throw new RepositoryFunctionException(new IOException(e.getMessage()), Transience.PERSISTENT);
    } finally {
        if (git != null) {
            git.close();
        }
    }
    return new HttpDownloadValue(descriptor.directory);
}
Also used : ProxyHelper(com.google.devtools.build.lib.bazel.repository.downloader.ProxyHelper) EvalException(com.google.devtools.build.lib.syntax.EvalException) IOException(java.io.IOException) URL(java.net.URL) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) Git(org.eclipse.jgit.api.Git) RefNotFoundException(org.eclipse.jgit.api.errors.RefNotFoundException) InvalidRefNameException(org.eclipse.jgit.api.errors.InvalidRefNameException) InvalidRemoteException(org.eclipse.jgit.api.errors.InvalidRemoteException) JGitInternalException(org.eclipse.jgit.api.errors.JGitInternalException) NetRCCredentialsProvider(org.eclipse.jgit.transport.NetRCCredentialsProvider) WorkspaceAttributeMapper(com.google.devtools.build.lib.rules.repository.WorkspaceAttributeMapper) RepositoryFunctionException(com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException)

Example 4 with RepositoryFunctionException

use of com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException in project bazel by bazelbuild.

the class SkylarkRepositoryContext method downloadAndExtract.

@SkylarkCallable(name = "download_and_extract", doc = "Download a file to the output path for the provided url, and extract it.", parameters = { @Param(name = "url", allowedTypes = { @ParamType(type = String.class), @ParamType(type = SkylarkList.class, generic1 = String.class) }, named = true, doc = "List of mirror URLs referencing the same file."), @Param(name = "output", allowedTypes = { @ParamType(type = String.class), @ParamType(type = Label.class), @ParamType(type = SkylarkPath.class) }, defaultValue = "''", named = true, doc = "path to the directory where the archive will be unpacked," + " relative to the repository directory."), @Param(name = "sha256", type = String.class, defaultValue = "''", named = true, doc = "the expected SHA-256 hash of the file downloaded." + " This must match the SHA-256 hash of the file downloaded. It is a security risk" + " to omit the SHA-256 as remote files can change. At best omitting this field" + " will make your build non-hermetic. It is optional to make development easier" + " but should be set before shipping."), @Param(name = "type", type = String.class, defaultValue = "''", named = true, doc = "the archive type of the downloaded file." + " By default, the archive type is determined from the file extension of the URL." + " If the file has no extension, you can explicitly specify either \"zip\"," + " \"jar\", \"war\", \"tar.gz\", \"tgz\", \"tar.bz2\", or \"tar.xz\" here."), @Param(name = "stripPrefix", type = String.class, defaultValue = "''", named = true, doc = "a directory prefix to strip from the extracted files." + "\nMany archives contain a top-level directory that contains all files in the" + " archive. Instead of needing to specify this prefix over and over in the" + " <code>build_file</code>, this field can be used to strip it from extracted" + " files.") })
public void downloadAndExtract(Object url, Object output, String sha256, String type, String stripPrefix) throws RepositoryFunctionException, InterruptedException, EvalException {
    validateSha256(sha256);
    List<URL> urls = getUrls(url);
    // Download to outputDirectory and delete it after extraction
    SkylarkPath outputPath = getPath("download_and_extract()", output);
    checkInOutputDirectory(outputPath);
    createDirectory(outputPath.getPath());
    Path downloadedPath;
    try {
        downloadedPath = httpDownloader.download(urls, sha256, Optional.of(type), outputPath.getPath(), env.getListener(), osObject.getEnvironmentVariables());
    } catch (InterruptedException e) {
        throw new RepositoryFunctionException(new IOException("thread interrupted"), Transience.TRANSIENT);
    } catch (IOException e) {
        throw new RepositoryFunctionException(e, Transience.TRANSIENT);
    }
    DecompressorValue.decompress(DecompressorDescriptor.builder().setTargetKind(rule.getTargetKind()).setTargetName(rule.getName()).setArchivePath(downloadedPath).setRepositoryPath(outputPath.getPath()).setPrefix(stripPrefix).build());
    try {
        if (downloadedPath.exists()) {
            downloadedPath.delete();
        }
    } catch (IOException e) {
        throw new RepositoryFunctionException(new IOException("Couldn't delete temporary file (" + downloadedPath.getPathString() + ")", e), Transience.TRANSIENT);
    }
}
Also used : RootedPath(com.google.devtools.build.lib.vfs.RootedPath) Path(com.google.devtools.build.lib.vfs.Path) IOException(java.io.IOException) URL(java.net.URL) RepositoryFunctionException(com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException) SkylarkCallable(com.google.devtools.build.lib.skylarkinterface.SkylarkCallable)

Example 5 with RepositoryFunctionException

use of com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException in project bazel by bazelbuild.

the class SkylarkRepositoryContext method createFileFromTemplate.

@SkylarkCallable(name = "template", doc = "Generate a new file using a <code>template</code>. Every occurrence in " + "<code>template</code> of a key of <code>substitutions</code> will be replaced by " + "the corresponding value. The result is written in <code>path</code>. An optional" + "<code>executable</code> argument (default to true) can be set to turn on or off" + "the executable bit.", parameters = { @Param(name = "path", allowedTypes = { @ParamType(type = String.class), @ParamType(type = Label.class), @ParamType(type = SkylarkPath.class) }, doc = "path of the file to create, relative to the repository directory."), @Param(name = "template", allowedTypes = { @ParamType(type = String.class), @ParamType(type = Label.class), @ParamType(type = SkylarkPath.class) }, doc = "path to the template file."), @Param(name = "substitutions", type = SkylarkDict.class, defaultValue = "{}", named = true, doc = "substitutions to make when expanding the template."), @Param(name = "executable", type = Boolean.class, defaultValue = "True", named = true, doc = "set the executable flag on the created file, true by default.") })
public void createFileFromTemplate(Object path, Object template, SkylarkDict<String, String> substitutions, Boolean executable) throws RepositoryFunctionException, EvalException, InterruptedException {
    SkylarkPath p = getPath("template()", path);
    SkylarkPath t = getPath("template()", template);
    try {
        checkInOutputDirectory(p);
        makeDirectories(p.getPath());
        String tpl = FileSystemUtils.readContent(t.getPath(), StandardCharsets.UTF_8);
        for (Map.Entry<String, String> substitution : substitutions.entrySet()) {
            tpl = StringUtilities.replaceAllLiteral(tpl, substitution.getKey(), substitution.getValue());
        }
        try (OutputStream stream = p.getPath().getOutputStream()) {
            stream.write(tpl.getBytes(StandardCharsets.UTF_8));
        }
        if (executable) {
            p.getPath().setExecutable(true);
        }
    } catch (IOException e) {
        throw new RepositoryFunctionException(e, Transience.TRANSIENT);
    }
}
Also used : OutputStream(java.io.OutputStream) IOException(java.io.IOException) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) RepositoryFunctionException(com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException) SkylarkCallable(com.google.devtools.build.lib.skylarkinterface.SkylarkCallable)

Aggregations

RepositoryFunctionException (com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException)20 IOException (java.io.IOException)18 Path (com.google.devtools.build.lib.vfs.Path)8 EvalException (com.google.devtools.build.lib.syntax.EvalException)6 SkylarkCallable (com.google.devtools.build.lib.skylarkinterface.SkylarkCallable)5 URL (java.net.URL)5 Nullable (javax.annotation.Nullable)4 ImmutableMap (com.google.common.collect.ImmutableMap)3 WorkspaceAttributeMapper (com.google.devtools.build.lib.rules.repository.WorkspaceAttributeMapper)3 FileValue (com.google.devtools.build.lib.skyframe.FileValue)3 Fingerprint (com.google.devtools.build.lib.util.Fingerprint)3 PathFragment (com.google.devtools.build.lib.vfs.PathFragment)3 RootedPath (com.google.devtools.build.lib.vfs.RootedPath)3 Map (java.util.Map)3 TreeMap (java.util.TreeMap)3 BlazeDirectories (com.google.devtools.build.lib.analysis.BlazeDirectories)2 Rule (com.google.devtools.build.lib.packages.Rule)2 OutputStream (java.io.OutputStream)2 MalformedURLException (java.net.MalformedURLException)2 ArrayList (java.util.ArrayList)2