Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to continue searching for configuration file even if .git is found #941

Merged
merged 1 commit into from
Oct 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ provided using CLI, Robocop will try to find default configuration file using th
- otherwise, if the directory contains ``pyproject.toml`` file, load it
- otherwise, go to parent directory. Stop search if ``.git`` or top disk directory is found

It is possible to not stop searching parent directories even if ``.git`` directory is found using
``--ignore-git-dir`` flag.

``.robocop`` argument file
--------------------------

Expand Down
5 changes: 5 additions & 0 deletions docs/releasenotes/unreleased/other.2.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
--ignore-git-dir option to ignore .git when searching for configuration file (#908)
------------------------------------------------------------------------------------

When searching for the default configuration file, Robocop stop searching if ``.git`` directory is found. It is now
possible to disable this behaviour using ``--ignore-git-dir`` flag.
24 changes: 16 additions & 8 deletions robocop/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ def __init__(self, root=None, from_cli: bool = False):
self.recursive = True
self.verbose = False
self.persistent = False
self.ignore_git_dir = False
self.config_from = ""
self.root = find_project_root(root, ["."])
self.parse()
Expand Down Expand Up @@ -374,6 +375,13 @@ def _create_parser(self):
)
optional.add_argument("-A", "--argumentfile", metavar="PATH", help="Path to file with arguments.")
optional.add_argument("--config", metavar="PATH", help="Path to TOML configuration file.")
optional.add_argument(
"--ignore-git-dir",
action="store_true",
default=self.ignore_git_dir,
help="Use this flag to continue searching for the default configuration file even if parent directory "
"contains '.git' directory. Useful for multirepo.",
)
optional.add_argument(
"-g",
"--ignore",
Expand Down Expand Up @@ -435,7 +443,7 @@ def parse(self):
return
args = sys.argv[1:]
if not self.config_file_in_cli(args):
self.load_default_config_file()
self.load_default_config_file(ignore_git_dir="--ignore-git-dir" in args)
self.parse_args(args)

@staticmethod
Expand All @@ -459,20 +467,20 @@ def print_config_source(self):
else:
print("No config file found or configuration is empty. Using default configuration")

def load_default_config_file(self):
def load_default_config_file(self, ignore_git_dir: bool = False):
"""Find and load default configuration file.

First look for .robocop file. If it does not exist, search for pyproject.toml file."""
if self.load_robocop_file():
if self.load_robocop_file(ignore_git_dir):
return
pyproject_path = find_file_in_project_root("pyproject.toml", self.root)
if pyproject_path.is_file():
pyproject_path = find_file_in_project_root("pyproject.toml", self.root, ignore_git_dir)
if pyproject_path is not None:
self.load_pyproject_file(pyproject_path)

def load_robocop_file(self):
def load_robocop_file(self, ignore_git_dir: bool):
"""Returns True if .robocop exists"""
robocop_path = find_file_in_project_root(".robocop", self.root)
if not robocop_path.is_file():
robocop_path = find_file_in_project_root(".robocop", self.root, ignore_git_dir)
if robocop_path is None:
return False
argument_files_parser = ArgumentFileParser()
args = argument_files_parser.load_argument_file(robocop_path, robocop_path.parent)
Expand Down
7 changes: 4 additions & 3 deletions robocop/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ def find_project_root(root, srcs):
return directory


def find_file_in_project_root(config_name, root):
def find_file_in_project_root(config_name, root, ignore_git_dir: bool):
for parent in (root, *root.parents):
if (parent / ".git").exists() or (parent / config_name).is_file():
if (parent / config_name).is_file():
return parent / config_name
return parent / config_name
if not ignore_git_dir and (parent / ".git").exists():
return None


@lru_cache()
Expand Down
Empty file.
17 changes: 14 additions & 3 deletions tests/utest/test_configuration_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,25 @@ class TestConfigurationFile:
def test_find_project_root_same_dir(self, path_to_test_data):
src = path_to_test_data / "default_config"
with working_directory(src):
root = find_file_in_project_root(".robocop", src)
root = find_file_in_project_root(".robocop", src, False)
assert root == src / ".robocop"

def test_find_project_root_missing_but_git(self, path_to_test_data):
src = path_to_test_data / "default_config_missing" / "nested" / "deeper"
with working_directory(src):
root = find_file_in_project_root(".robocop", src)
assert root == Path(__file__).parent.parent.parent / ".robocop"
root = find_file_in_project_root(".robocop", src, False)
assert root is None

def test_ignore_git_dir(self, path_to_test_data):
src = path_to_test_data / "default_config_outside_git"
cwd_src = src / "root"
(cwd_src / ".git").mkdir(parents=True, exist_ok=True)
with working_directory(cwd_src):
config_file_disabled = find_file_in_project_root("pyproject.toml", cwd_src, False)
config_file_enabled = find_file_in_project_root("pyproject.toml", cwd_src, True)

assert config_file_disabled is None
assert config_file_enabled == src / "pyproject.toml"

def test_load_config_from_default_file(self, path_to_test_data):
src = path_to_test_data / "default_config"
Expand Down
Loading