How to read file contents in a global prereceive hook?

Hi,

I’m trying to read the content of a specific file in a prereceive hook in Bitbucket Server to make sure that this file has a valid content. Unfortunately, the following code does not work and I always get a NoSuchPathException when trying to read the file:

public class PrereceiveHook implements PreReceiveHook {
    private final CommitService commitService;
    private final ContentService contentService;

    public PrereceiveHook(CommitService commitService, ContentService contentService) {
        this.commitService = commitService;
        this.contentService = contentService;
    }

    public boolean onReceive(Repository repo, Collection<RefChange> refChanges, HookResponse hookResponse) {
        for (RefChange change : refChanges) {
            if (change.getType() != RefChangeType.DELETE) {
                CommitsBetweenRequest request = new CommitsBetweenRequest.Builder(repo)
                        .exclude(change.getFromHash())
                        .include(change.getToHash())
                        .build();
                
                for (Commit commit : commitService.getCommitsBetween(request, PageUtils.newRequest(0, 999)).getValues()) {
                    ChangesRequest changesRequest = new ChangesRequest.Builder(repo, commit.getId()).build();
                    commitService.streamChanges(changesRequest, new ChangeCallback() {
                        @Override
                        public boolean onChange(@Nonnull Change change) throws IOException {
                           if (change.getPath().getName().equals("file.txt")) {
                                try {
                                    ByteArrayOutputStream os = new ByteArrayOutputStream();
                                    contentService.streamFile(repo, commit.getId(), "file.txt", new TypeAwareOutputSupplier() {
                                        @Override
                                        public OutputStream getStream(@Nonnull String s) throws IOException {
                                            return os;
                                        }
                                    });
                                    String fileContent = new String(os.toByteArray(), "UTF-8");
                                    // parse file
                                } catch (NoSuchPathException e) {
                                    hookResponse.err().println("failed to read file.txt");
                                }
                            }
                            return true;
                        }
                    });
                }
            }
        }
        return true;
    }
}

Any suggestions would be much appreciated. I tried this code with Bitbucket Server versions 4.8 and 5.7, both resulting in the same error as described above even when a file called “file.txt” is part of the committed code.

Thanks,
Michael

try use contentService.streamFile(repo, commit.getId(), change.getPath().toString()
instead of contentService.streamFile(repo, commit.getId(), "file.txt"

Thanks a lot for your reply. But unfortunately, that didn’t make any differences.

change.getPath().toString()

was equal to “file.txt” (and not e.g., “/file.txt” as I supposed when I read your answer).

Do you have any other ideas what could be wrong?

I also encountered this error, did you manage to find a solution?

Hi,

Unfortunately not, I’m still looking for a solution to this problem.

Thanks,
Michael

Hi,

I have not tried/verified yet, but this sounds suspiciously like the issues discussed in:

Both are pointing to BSERV-10437: Pre-receive hooks can only read objects from the repository being pushed to on Git 2.11+ as the underlying bug/issue.

NOTE: BSERV-10437 is supposed to be fixed in 5.7.0, i.e. your tests with 5.7 should have worked then, but I guess it is at least worth a second look.

Cheers,
Henrik

1 Like

There’s a recent discussion with Atlassian engineer @jpalacios on community.atlassian.com that’s probably related to this:

The discussion there also references issues around Git 2.11+ and its pre-receive quarantine area.