1#!/usr/bin/env python3
2
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# See LICENSE.txt included in this distribution for the specific
10# language governing permissions and limitations under the License.
11#
12# When distributing Covered Code, include this CDDL HEADER in each
13# file and include the License file at LICENSE.txt.
14# If applicable, add the following below this CDDL HEADER, with the
15# fields enclosed by brackets "[]" replaced with your own identifying
16# information: Portions Copyright [yyyy] [name of copyright owner]
17#
18# CDDL HEADER END
19
20#
21# Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
22# Portions Copyright (c) 2017-2018, Chris Fraire <cfraire@me.com>.
23#
24
25
26from .utils import get_command
27from .command import Command
28from .java import Java
29import logging
30
31
32"""
33  opengrok.jar wrapper
34
35  This script can be used to run the OpenGrok indexer.
36"""
37
38
39class Indexer(Java):
40    """
41    Wrapper class to make it easier to execute the OpenGrok indexer.
42    """
43
44    def __init__(self, command, logger=None, java=None, jar='opengrok.jar',
45                 java_opts=None, env_vars=None, doprint=False):
46
47        java_options = []
48        if java_opts:
49            java_options.extend(java_opts)
50        java_options = merge_properties(java_options,
51                                        get_SCM_properties(logger))
52        logger.debug("Java options: {}".format(java_options))
53
54        super().__init__(command, jar=jar, java=java, java_opts=java_options,
55                         logger=logger, env_vars=env_vars, doprint=doprint)
56
57
58def get_SCM_properties(logger):
59    """
60    Return list of Java System properties that contain valid paths to
61    SCM commands.
62    """
63    SCM_COMMANDS = {
64        'bk': '-Dorg.opengrok.indexer.history.BitKeeper',
65        'hg': '-Dorg.opengrok.indexer.history.Mercurial',
66        'cvs': '-Dorg.opengrok.indexer.history.cvs',
67        'svn': '-Dorg.opengrok.indexer.history.Subversion',
68        'sccs': '-Dorg.opengrok.indexer.history.SCCS',
69        'cleartool': '-Dorg.opengrok.indexer.history.ClearCase',
70        'git': '-Dorg.opengrok.indexer.history.git',
71        'p4': '-Dorg.opengrok.indexer.history.Perforce',
72        'mtn': '-Dorg.opengrok.indexer.history.Monotone',
73        'blame': '-Dorg.opengrok.indexer.history.RCS',
74        'bzr': '-Dorg.opengrok.indexer.history.Bazaar'}
75
76    properties = []
77    for cmd in SCM_COMMANDS.keys():
78        executable = get_command(logger, None, cmd, level=logging.INFO)
79        if executable:
80            properties.append("{}={}".
81                              format(SCM_COMMANDS[cmd], executable))
82
83    return properties
84
85
86def merge_properties(base, extra):
87    """
88    Merge two lists of options (strings in the form of name=value).
89    Take everything from base and add properties from extra
90    (according to names) that are not present in the base.
91    :param base: list of properties
92    :param extra: list of properties
93    :return: merged list
94    """
95
96    extra_prop_names = set(map(lambda x: x.split('=')[0], base))
97
98    ret = set(base)
99    for item in extra:
100        nv = item.split("=")
101        if nv[0] not in extra_prop_names:
102            ret.add(item)
103
104    return list(ret)
105
106
107def FindCtags(logger):
108    """
109    Search for Universal ctags intelligently, skipping over other ctags
110    implementations. Return path to the command or None if not found.
111    """
112    binary = None
113    logger.debug("Trying to find ctags binary")
114    for program in ['universal-ctags', 'ctags']:
115        executable = get_command(logger, None, program, level=logging.DEBUG)
116        if executable:
117            # Verify that this executable is or is Universal Ctags
118            # by matching the output when run with --version.
119            logger.debug("Checking ctags command {}".format(executable))
120            cmd = Command([executable, '--version'], logger=logger)
121            cmd.execute()
122
123            output_str = cmd.getoutputstr()
124            if output_str and output_str.find("Universal Ctags") != -1:
125                logger.debug("Got valid ctags binary: {}".format(executable))
126                binary = executable
127                break
128
129    return binary
130