docs: @Get("regex:/projects/(?<projectName>[^/]+)/repos/(?<repoName>[^/]+)/contents(?<path>(|/.*))$")
      public CompletableFuture<?> getFiles(
              @Param("path") String path, @Param("revision") @Default("-1") String revision,
              Repository repository,
              @RequestConverter(WatchRequestConverter.class) Optional<WatchRequest> watchRequest,
              @RequestConverter(QueryRequestConverter.class) Optional<Query<?>> query) {
          final String normalizedPath = normalizePath(path);
  
          // watch repository or a file
          if (watchRequest.isPresent()) {
              final Revision lastKnownRevision = watchRequest.get().lastKnownRevision();
              final long timeOutMillis = watchRequest.get().timeoutMillis();
              if (query.isPresent()) {
                  return watchFile(repository, lastKnownRevision, query.get(), timeOutMillis);
              }
  
              return watchRepository(repository, lastKnownRevision, normalizedPath, timeOutMillis);
          }
  
          final Revision normalizedRev = repository.normalizeNow(new Revision(revision));
          if (query.isPresent()) {
              // get a file
              return repository.get(normalizedRev, query.get())
                               .handle(returnOrThrow((Entry<?> result) -> convert(repository, normalizedRev,
                                                                                  result, true)));
          }
  
          // get files
          final CompletableFuture<List<EntryDto<?>>> future = new CompletableFuture<>();
          listFiles(repository, normalizedPath, normalizedRev, true, future);
          return future;
      }