# Copyright 2019 The Meson development team

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations

import os
import subprocess
from pathlib import Path
import typing as T

def ls_as_bytestream() -> bytes:
    if os.path.exists('.git'):
        return subprocess.run(['git', 'ls-tree', '-r', '--name-only', 'HEAD'],
                              stdout=subprocess.PIPE).stdout

    files = [str(p) for p in Path('.').glob('**/*')
             if not p.is_dir() and
             not next((x for x in p.parts if x.startswith('.')), None)]
    return '\n'.join(files).encode()


def cscope() -> int:
    ls = b'\n'.join([b'"%s"' % f for f in ls_as_bytestream().split()])
    return subprocess.run(['cscope', '-v', '-b', '-i-'], input=ls).returncode


def ctags() -> int:
    ls = ls_as_bytestream()
    return subprocess.run(['ctags', '-L-'], input=ls).returncode


def etags() -> int:
    ls = ls_as_bytestream()
    return subprocess.run(['etags', '-'], input=ls).returncode


def run(args: T.List[str]) -> int:
    tool_name = args[0]
    srcdir_name = args[1]
    os.chdir(srcdir_name)
    assert tool_name in {'cscope', 'ctags', 'etags'}
    res = globals()[tool_name]()
    assert isinstance(res, int)
    return res
