Block Unwanted Files from Being Pushed

Overview

When pushing a commit, this custom pre-hook checks the files being pushed against a server side .gitignore template. If any of the files match those specified in the .gitignore template, the push is rejected.

This script was created and provided by GAIN Capital.

Example

Binaries increase repo size, which swells disk space consumption and enlarges git clone time locally and in other systems such as on a CI/CD server. Destroying files and associated history in Git is not easy and discouraged, so binaries should be rejected from the outset.

Good to Know

  • With this custom pre-hook, ScriptRunner for Bitbucket rejects the push with a custom error message.

Requirements

Bitbucket Bitbucket (6.3 - 7.12)

    
/** * Copyright © 2020, StoneX/Gain Capital. * * This script is released under the BSD 3-clause license: https://opensource.org/licenses/BSD-3-Clause * * Blocks all binaries in Bitbucket using template .gitignore */ import java.nio.file.FileSystems import java.nio.file.PathMatcher List getTemplateIgnoreFileContents() { def file = new File('path/to/file/gitignore.template.txt') file.readLines() } Map getIgnoreMatchers(List ignores) { def ignoreMatchers = [:] def fileSystem = FileSystems.default ignores.unique().any { ignore -> if (!(ignore ==~ /^\\s*#.*/)) { // We need to normalize some entries def newIgnore = ignore if (ignore.endsWith('/')) { newIgnore += '**' } if (ignore.startsWith('*.')) { newIgnore = '*' + ignore } def matcher = fileSystem.getPathMatcher("glob:" + newIgnore) ignoreMatchers.put(newIgnore, matcher) } } ignoreMatchers } try { def rejectedFiles = [] def fileSystem = FileSystems.default def gitIgnore = templateIgnoreFileContents def matchers = getIgnoreMatchers(gitIgnore) def keySet = matchers.keySet() refChanges.any { refChange -> refChange.getChangesets(repository).each { changeset -> changeset.changes.values.each { change -> // We do not check for delete operations. if (change.type.toString() != 'DELETE') { keySet.each { key -> def filePath = fileSystem.getPath(change.path.toString()) def matcher = matchers[key] if (matcher.matches(filePath)) { rejectedFiles.add(changeset.toCommit.displayId + " contains binary " + change.path.toString() + " (" + change.type.toString() + ") " + "by " + changeset.toCommit.author.name + " in '" + repository.name + "' repository. " + "Blocked by gitignore rule " + key) } } } } } } if (rejectedFiles.size() > 0) { rejectedFiles.each { line -> hookResponse.out().println(line) } hookResponse.out().println('\n') hookResponse.out().println('Binaries are not allowed. See https://.../display/ABC/Binaries+control') return false } return true } catch (Exception ex) { log.error("Exception: ${ex}") return false }
Discovered an issue? Report it here

Suggested for you