class MonotoneRepository extends Repository {

    private static final Logger LOGGER = LoggerFactory.getLogger(MonotoneRepository.class);

    private static final long serialVersionUID = 1L;
    /**
     * The property name used to obtain the client command for this repository.
     */
    public static final String CMD_PROPERTY_KEY = "org.opengrok.indexer.history.Monotone";
    /**
     * The command to use to access the repository if none was given explicitly.
     */
    public static final String CMD_FALLBACK = "mnt";

    public MonotoneRepository() {
        type = "Monotone";
        datePatterns = new String[]{
            "yyyy-MM-dd'T'hh:mm:ss"
        };
    }

    @Override
    boolean getHistoryGet(OutputStream out, String parent, String basename, String rev) {<FILL_FUNCTION_BODY>}

    /**
     * Get an executor to be used for retrieving the history log for the named
     * file or directory.
     *
     * @param file The file or directory to retrieve history for
     * @param sinceRevision the oldest changeset to return from the executor, or
     *                  {@code null} if all changesets should be returned
     * @return An Executor ready to be started
     */
    Executor getHistoryLogExecutor(File file, String sinceRevision)
            throws IOException {
        String filename = getRepoRelativePath(file);

        List<String> cmd = new ArrayList<>();
        ensureCommand(CMD_PROPERTY_KEY, CMD_FALLBACK);
        cmd.add(RepoCommand);
        cmd.add("log");

        if (sinceRevision != null) {
            cmd.add("--to");
            cmd.add(sinceRevision);
        }

        cmd.add("--no-graph");
        cmd.add("--no-merges");
        cmd.add("--no-format-dates");
        cmd.add(filename);

        return new Executor(cmd, new File(getDirectoryName()), sinceRevision != null);
    }

    /**
     * Annotate the specified file/revision using the {@code mnt annotate} command.
     *
     * @param file file to annotate
     * @param revision revision to annotate
     * @return file annotation
     * @throws java.io.IOException if I/O exception occurred or the command failed
     */
    @Override
    public Annotation annotate(File file, String revision) throws IOException {
        ArrayList<String> cmd = new ArrayList<>();
        ensureCommand(CMD_PROPERTY_KEY, CMD_FALLBACK);
        cmd.add(RepoCommand);
        cmd.add("annotate");
        cmd.add(getQuietOption());
        if (revision != null) {
            cmd.add("-r");
            cmd.add(revision);
        }
        cmd.add(file.getName());
        File directory = new File(getDirectoryName());

        Executor executor = new Executor(cmd, directory,
                RuntimeEnvironment.getInstance().getInteractiveCommandTimeout());
        MonotoneAnnotationParser parser = new MonotoneAnnotationParser(file);
        int status = executor.exec(true, parser);
        if (status != 0) {
            LOGGER.log(Level.WARNING,
                    "Failed to get annotations for: \"{0}\" Exit code: {1}",
                    new Object[]{file.getAbsolutePath(), String.valueOf(status)});
            throw new IOException(executor.getErrorString());
        } else {
            return parser.getAnnotation();
        }
    }

    @Override
    public boolean fileHasAnnotation(File file) {
        return true;
    }

    @Override
    public boolean fileHasHistory(File file) {
        return true;
    }

    @Override
    boolean isRepositoryFor(File file, CommandTimeoutType cmdType) {
        File f = new File(file, "_MTN");
        return f.exists() && f.isDirectory();
    }

    @Override
    public boolean isWorking() {
        if (working == null) {
            ensureCommand(CMD_PROPERTY_KEY, CMD_FALLBACK);
            working = checkCmd(RepoCommand, "--help");
        }
        return working;
    }

    @Override
    boolean hasHistoryForDirectories() {
        return true;
    }

    @Override
    History getHistory(File file) throws HistoryException {
        return getHistory(file, null);
    }

    @Override
    History getHistory(File file, String sinceRevision)
            throws HistoryException {
        return new MonotoneHistoryParser(this).parse(file, sinceRevision);
    }

    private String getQuietOption() {
        if (useDeprecated()) {
            return "--reallyquiet";
        } else {
            return "--quiet --quiet";
        }
    }

    public static final String DEPRECATED_KEY
            = "org.opengrok.indexer.history.monotone.deprecated";

    private boolean useDeprecated() {
        return Boolean.parseBoolean(System.getProperty(DEPRECATED_KEY, "false"));
    }

    @Override
    String determineParent(CommandTimeoutType cmdType) throws IOException {
        String parent = null;
        File directory = new File(getDirectoryName());

        List<String> cmd = new ArrayList<>();
        ensureCommand(CMD_PROPERTY_KEY, CMD_FALLBACK);
        cmd.add(RepoCommand);
        cmd.add("ls");
        cmd.add("vars");
        cmd.add("database");
        Executor executor = new Executor(cmd, directory,
                RuntimeEnvironment.getInstance().getCommandTimeout(cmdType));
        executor.exec();

        try (BufferedReader in = new BufferedReader(executor.getOutputReader())) {
            String line;
            while ((line = in.readLine()) != null) {
                if (line.startsWith("database") && line.contains("default-server")) {
                    String[] parts = line.split("\\s+");
                    if (parts.length != 3) {
                        LOGGER.log(Level.WARNING,
                                "Failed to get parent for {0}", getDirectoryName());
                    }
                    parent = parts[2];
                    break;
                }
            }
        }

        return parent;
    }

    @Override
    String determineBranch(CommandTimeoutType cmdType) {
        return null;
    }

    @Override
    String determineCurrentVersion(CommandTimeoutType cmdType) throws IOException {
        return null;
    }
}


        File directory = new File(getDirectoryName());
        try {
            String filename = (new File(parent, basename)).getCanonicalPath()
                    .substring(getDirectoryName().length() + 1);
            ensureCommand(CMD_PROPERTY_KEY, CMD_FALLBACK);
            String[] argv = {RepoCommand, "cat", "-r", rev, filename};
            Executor executor = new Executor(Arrays.asList(argv), directory,
                    RuntimeEnvironment.getInstance().getInteractiveCommandTimeout());
            copyBytes(out::write, executor.getOutputStream());
            return true;
        } catch (Exception exp) {
            LOGGER.log(Level.SEVERE,
                    "Failed to get history: {0}", exp.getClass().toString());
        }

        return false;
    
<methods>public final java.lang.String determineBranch() throws java.io.IOException,public final java.lang.String determineCurrentVersion() throws java.io.IOException,public final java.lang.String determineParent() throws java.io.IOException,public static java.lang.String format(java.util.Date) ,public boolean getHistoryGet(java.io.File, java.lang.String, java.lang.String, java.lang.String) throws java.io.IOException,public java.io.InputStream getHistoryGet(java.lang.String, java.lang.String, java.lang.String) ,public List<java.lang.String> getIgnoredDirs() ,public List<java.lang.String> getIgnoredFiles() ,public org.opengrok.indexer.history.HistoryEntry getLastHistoryEntry(java.io.File, boolean) throws org.opengrok.indexer.history.HistoryException,public java.lang.String getRepoCommand() ,public final boolean isRepositoryFor(java.io.File) ,public java.util.Date parse(java.lang.String) throws java.text.ParseException<variables>private static final java.util.logging.Logger LOGGER,protected static final java.text.SimpleDateFormat OUTPUT_DATE_FORMAT,protected java.lang.String RepoCommand,protected final non-sealed List<java.lang.String> ignoredDirs,protected final non-sealed List<java.lang.String> ignoredFiles,private static final long serialVersionUID,protected NavigableSet<org.opengrok.indexer.history.TagEntry> tagList