Преглед изворни кода

Fix project_dir to take first file in account

The order of precedence is:
- '--project-directory' option
- first file directory in '--file' option
- current directory

Signed-off-by: Ulysses Souza <[email protected]>
Ulysses Souza пре 4 година
родитељ
комит
e0edc908b5
3 измењених фајлова са 32 додато и 30 уклоњено
  1. 15 7
      compose/cli/command.py
  2. 10 8
      compose/cli/main.py
  3. 7 15
      tests/unit/cli/command_test.py

+ 15 - 7
compose/cli/command.py

@@ -35,7 +35,7 @@ SILENT_COMMANDS = {
 
 def project_from_options(project_dir, options, additional_options=None):
     additional_options = additional_options or {}
-    override_dir = options.get('--project-directory')
+    override_dir = get_project_dir(options)
     environment_file = options.get('--env-file')
     environment = Environment.from_env_file(override_dir or project_dir, environment_file)
     environment.silent = options.get('COMMAND', None) in SILENT_COMMANDS
@@ -59,7 +59,7 @@ def project_from_options(project_dir, options, additional_options=None):
 
     return get_project(
         project_dir,
-        get_config_path_from_options(project_dir, options, environment),
+        get_config_path_from_options(options, environment),
         project_name=options.get('--project-name'),
         verbose=options.get('--verbose'),
         context=context,
@@ -87,21 +87,29 @@ def set_parallel_limit(environment):
         parallel.GlobalLimit.set_global_limit(parallel_limit)
 
 
+def get_project_dir(options):
+    override_dir = None
+    files = get_config_path_from_options(options, os.environ)
+    if files:
+        if files[0] == '-':
+            return '.'
+        override_dir = os.path.dirname(files[0])
+    return options.get('--project-directory') or override_dir
+
+
 def get_config_from_options(base_dir, options, additional_options=None):
     additional_options = additional_options or {}
-    override_dir = options.get('--project-directory')
+    override_dir = get_project_dir(options)
     environment_file = options.get('--env-file')
     environment = Environment.from_env_file(override_dir or base_dir, environment_file)
-    config_path = get_config_path_from_options(
-        base_dir, options, environment
-    )
+    config_path = get_config_path_from_options(options, environment)
     return config.load(
         config.find(base_dir, config_path, environment, override_dir),
         not additional_options.get('--no-interpolate')
     )
 
 
-def get_config_path_from_options(base_dir, options, environment):
+def get_config_path_from_options(options, environment):
     def unicode_paths(paths):
         return [p.decode('utf-8') if isinstance(p, bytes) else p for p in paths]
 

+ 10 - 8
compose/cli/main.py

@@ -39,6 +39,7 @@ from ..service import ImageType
 from ..service import NeedsBuildError
 from ..service import OperationFailedError
 from .command import get_config_from_options
+from .command import get_project_dir
 from .command import project_from_options
 from .docopt_command import DocoptDispatcher
 from .docopt_command import get_handler
@@ -245,7 +246,7 @@ class TopLevelCommand:
 
     @property
     def project_dir(self):
-        return self.toplevel_options.get('--project-directory') or '.'
+        return get_project_dir(self.toplevel_options)
 
     @property
     def toplevel_environment(self):
@@ -431,6 +432,7 @@ class TopLevelCommand:
         Options:
             --json      Output events as a stream of json objects
         """
+
         def format_event(event):
             attributes = ["%s=%s" % item for item in event['attributes'].items()]
             return ("{time} {type} {action} {id} ({attrs})").format(
@@ -1382,13 +1384,13 @@ def get_docker_start_call(container_options, container_id):
 
 
 def log_printer_from_project(
-    project,
-    containers,
-    monochrome,
-    log_args,
-    cascade_stop=False,
-    event_stream=None,
-    keep_prefix=True,
+        project,
+        containers,
+        monochrome,
+        log_args,
+        cascade_stop=False,
+        event_stream=None,
+        keep_prefix=True,
 ):
     return LogPrinter(
         containers,

+ 7 - 15
tests/unit/cli/command_test.py

@@ -14,49 +14,41 @@ class TestGetConfigPathFromOptions:
         paths = ['one.yml', 'two.yml']
         opts = {'--file': paths}
         environment = Environment.from_env_file('.')
-        assert get_config_path_from_options('.', opts, environment) == paths
+        assert get_config_path_from_options(opts, environment) == paths
 
     def test_single_path_from_env(self):
         with mock.patch.dict(os.environ):
             os.environ['COMPOSE_FILE'] = 'one.yml'
             environment = Environment.from_env_file('.')
-            assert get_config_path_from_options('.', {}, environment) == ['one.yml']
+            assert get_config_path_from_options({}, environment) == ['one.yml']
 
     @pytest.mark.skipif(IS_WINDOWS_PLATFORM, reason='posix separator')
     def test_multiple_path_from_env(self):
         with mock.patch.dict(os.environ):
             os.environ['COMPOSE_FILE'] = 'one.yml:two.yml'
             environment = Environment.from_env_file('.')
-            assert get_config_path_from_options(
-                '.', {}, environment
-            ) == ['one.yml', 'two.yml']
+            assert get_config_path_from_options({}, environment) == ['one.yml', 'two.yml']
 
     @pytest.mark.skipif(not IS_WINDOWS_PLATFORM, reason='windows separator')
     def test_multiple_path_from_env_windows(self):
         with mock.patch.dict(os.environ):
             os.environ['COMPOSE_FILE'] = 'one.yml;two.yml'
             environment = Environment.from_env_file('.')
-            assert get_config_path_from_options(
-                '.', {}, environment
-            ) == ['one.yml', 'two.yml']
+            assert get_config_path_from_options({}, environment) == ['one.yml', 'two.yml']
 
     def test_multiple_path_from_env_custom_separator(self):
         with mock.patch.dict(os.environ):
             os.environ['COMPOSE_PATH_SEPARATOR'] = '^'
             os.environ['COMPOSE_FILE'] = 'c:\\one.yml^.\\semi;colon.yml'
             environment = Environment.from_env_file('.')
-            assert get_config_path_from_options(
-                '.', {}, environment
-            ) == ['c:\\one.yml', '.\\semi;colon.yml']
+            assert get_config_path_from_options({}, environment) == ['c:\\one.yml', '.\\semi;colon.yml']
 
     def test_no_path(self):
         environment = Environment.from_env_file('.')
-        assert not get_config_path_from_options('.', {}, environment)
+        assert not get_config_path_from_options({}, environment)
 
     def test_unicode_path_from_options(self):
         paths = [b'\xe5\xb0\xb1\xe5\x90\x83\xe9\xa5\xad/docker-compose.yml']
         opts = {'--file': paths}
         environment = Environment.from_env_file('.')
-        assert get_config_path_from_options(
-            '.', opts, environment
-        ) == ['就吃饭/docker-compose.yml']
+        assert get_config_path_from_options(opts, environment) == ['就吃饭/docker-compose.yml']