Skip to content

Commit 793ad53

Browse files
authored
Merge pull request #4 from composer-version-manager/application-service
Update PATH when version changes
2 parents b379dee + 4389d41 commit 793ad53

File tree

7 files changed

+137
-54
lines changed

7 files changed

+137
-54
lines changed

cvm/cli.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
from cvm.commands.command import Command
1010
from cvm.commands.hook_command import HookCommand
11-
from cvm.commands.install_command import InstallCommand
1211
from cvm.commands.list_command import ListCommand
1312
from cvm.commands.scan_command import ScanCommand
1413
from cvm.commands.use_command import UseCommand
@@ -21,7 +20,6 @@
2120

2221
COMMANDS = {
2322
UseCommand.NAME: UseCommand,
24-
InstallCommand.NAME: InstallCommand,
2523
ScanCommand.NAME: ScanCommand,
2624
ListCommand.NAME: ListCommand,
2725
HookCommand.NAME: HookCommand
@@ -30,11 +28,8 @@
3028

3129
def get_command_by_name(name: str) -> Optional[Command]:
3230
command = COMMANDS.get(name, None)
33-
if command is None:
34-
logging.error("Command {} not found".format(name))
35-
sys.exit(1)
3631

37-
return command()
32+
return command
3833

3934

4035
def main():
@@ -55,4 +50,8 @@ def main():
5550
args = parser.parse_args()
5651

5752
command = get_command_by_name(args.command)
58-
command.exec(args)
53+
if command is None:
54+
parser.print_help(sys.stdout)
55+
return
56+
57+
command().exec(args)

cvm/commands/install_command.py

Lines changed: 0 additions & 28 deletions
This file was deleted.

cvm/commands/scan_command.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,47 @@
44
from cvm.services.composer_service import ComposerService
55
from cvm.services.config_service import ConfigService
66
from cvm.services.github_service import GitHubService
7+
from cvm.services.application_service import ApplicationService
8+
from cvm.helpers.cli import warning
9+
from colorama import Fore
710

811

912
class ScanCommand(Command):
1013
NAME = 'scan'
1114
DESCRIPTION = 'If present use .cvm_config from the current or specified directory.'
1215

1316
def exec(self, args: Namespace):
14-
if not ConfigService.exists():
17+
version = None
18+
19+
if ConfigService.exists():
20+
version = self._check_local()
21+
else:
22+
version = self._check_global()
23+
24+
if version is None:
1525
return
1626

27+
github_service = GitHubService('composer', 'composer')
28+
composer_service = ComposerService(github_service)
29+
30+
updated_path = composer_service.use_version(version, False)
31+
32+
print(f"export PATH=\"{updated_path}\"; echo Updated path.;")
33+
34+
def _check_local(self):
1735
data = ConfigService.read()
1836
if not ConfigService.validate(data):
19-
print("echo Invalid cvm config.")
37+
msg = warning(".cvm_config format in current directory is invalid.")
38+
print(f"echo \"{msg}\"")
2039

21-
github_service = GitHubService('composer', 'composer')
22-
composer_service = ComposerService(github_service)
40+
return None
2341

24-
install_path = composer_service.use_version(data['requires'])
42+
return data['requires']
2543

26-
print(f"export PATH=:{install_path}:$PATH; echo Updated path.")
44+
def _check_global(self):
45+
application_service = ApplicationService()
46+
47+
return application_service.get('global')
2748

2849
@staticmethod
2950
def define_signature(parser: Action):

cvm/commands/use_command.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,28 @@
1+
import os
2+
import subprocess
13
from argparse import Action, Namespace
24

35
from cvm.commands.command import Command
46
from cvm.services.composer_service import ComposerService
7+
from cvm.services.config_service import ConfigService
58
from cvm.services.github_service import GitHubService
9+
from cvm.helpers.cli import info
10+
from colorama import Fore
611

712

813
class UseCommand(Command):
914
NAME = 'use'
10-
DESCRIPTION = 'Use a specific version of Composer; Defaulting to the latest stable major version when there is a ' \
11-
'lack of specificity (ie. 2). '
15+
DESCRIPTION = 'Globally use a specific composer version.'
1216

1317
def exec(self, args: Namespace):
14-
desired_version = args.version[0]
18+
version = args.version[0]
1519

1620
github_service = GitHubService('composer', 'composer')
1721
composer_service = ComposerService(github_service)
1822

19-
existed = composer_service.use_version(desired_version)
20-
if not existed:
21-
composer_service.install_version(desired_version)
22-
composer_service.use_version(desired_version, False)
23+
composer_service.use_version(version, True)
24+
25+
print(f"Global composer version updated to {version}.")
2326

2427
@staticmethod
2528
def define_signature(parser: Action):

cvm/helpers/cli.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,9 @@
44

55
def colored_fore(color: AnsiFore, text: str, default: str = Fore.LIGHTWHITE_EX) -> str:
66
return color + text + default
7+
8+
def warning(text: str, default: str = Fore.LIGHTWHITE_EX) -> str:
9+
return colored_fore(Fore.LIGHTRED_EX, text)
10+
11+
def info(text: str, default: str = Fore.LIGHTWHITE_EX) -> str:
12+
return colored_fore(Fore.LIGHTYELLOW_EX, text)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import json
2+
import logging
3+
import os
4+
import subprocess
5+
import re
6+
import pathlib
7+
import sys
8+
from enum import Enum
9+
from typing import Any, Optional
10+
11+
12+
class ComposerSource(Enum):
13+
Empty = ''
14+
Global = 'global'
15+
Config = 'config'
16+
17+
class ApplicationService:
18+
APP_DIR = pathlib.Path.home() / '.cvm'
19+
APP_FILE_PATH = APP_DIR / 'config.json'
20+
21+
def __init__(self):
22+
ApplicationService.APP_DIR.mkdir(parents=True, exist_ok=True)
23+
ApplicationService.APP_FILE_PATH.touch(exist_ok=True)
24+
self._parse()
25+
26+
def get_updated_path(self, bin_path: str) -> str:
27+
envPath = self._get_env_path()
28+
clean_path = self._clean_env_path(envPath)
29+
updated_path = f"{bin_path}:{clean_path}"
30+
31+
return updated_path
32+
33+
def _clean_env_path(self, envPath: str) -> str:
34+
return re.sub(r'\/(\b[^:]+)\/.cvm\/cache\/.+?(:|$)', '', envPath)
35+
36+
def _get_env_path(self) -> str:
37+
return subprocess.check_output("echo $PATH", shell=True).decode('ascii')
38+
39+
def _parse(self):
40+
try:
41+
self._app = json.load(ApplicationService.APP_FILE_PATH.open('r'))
42+
except:
43+
self._app = {}
44+
45+
if not self._app:
46+
self._app = {
47+
'global': None,
48+
'current': None,
49+
'source': str(ComposerSource.Empty),
50+
}
51+
self._write()
52+
53+
def _write(self):
54+
ApplicationService.APP_FILE_PATH.write_text(json.dumps(self._app))
55+
56+
def app(self) -> dict:
57+
return self._app
58+
59+
def get(self, key: str) -> Any:
60+
return self._app.get(key)
61+
62+
def set(self, key: str, value: Any):
63+
if type(value) is ComposerSource:
64+
value = str(value)
65+
66+
self._app[key] = value
67+
68+
def save(self):
69+
self._write()

cvm/services/composer_service.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from cvm.services.cache_service import CacheService
99
from cvm.services.github_service import GitHubService
10+
from cvm.services.application_service import ApplicationService, ComposerSource
1011

1112

1213
class ComposerService:
@@ -57,7 +58,7 @@ def _get_setup_path(self) -> pathlib.Path:
5758
setup_path.write_bytes(r.content)
5859
return setup_path
5960

60-
def install_version(self, tag_name: str, quiet=False) -> pathlib.Path:
61+
def install_version(self, tag_name: str, quiet=False) -> str:
6162
if not self.tag_exists(tag_name):
6263
logging.error("Tag {} does not exist.".format(tag_name))
6364
sys.exit(1)
@@ -66,16 +67,28 @@ def install_version(self, tag_name: str, quiet=False) -> pathlib.Path:
6667
cache_path = CacheService.make_cache_folder(tag_name)
6768

6869
if ComposerService.cached_version_exists(tag_name):
69-
return cache_path
70+
return str(cache_path)
7071

7172
cmd = ['php', str(setup_path), f'--install-dir={str(cache_path)}', '--filename=composer', f'--version={tag_name}']
7273
result = subprocess.run(cmd, stdout=subprocess.PIPE, check=True)
7374
if not quiet:
7475
print(result.stdout.decode('utf-8'))
7576

76-
return cache_path
77+
return str(cache_path)
7778

78-
def use_version(self, tag_name: str) -> str:
79-
install_path = self.install_version(tag_name, quiet=True)
79+
def use_version(self, tag_name: str, is_global: bool) -> str:
80+
bin_path = self.install_version(tag_name, quiet=True)
8081

81-
return str(install_path)
82+
application_service = ApplicationService()
83+
application_service.set('current', tag_name)
84+
85+
if is_global:
86+
application_service.set('global', tag_name)
87+
application_service.set('source', ComposerSource.Global.value)
88+
else:
89+
application_service.set('source', ComposerSource.Config.value)
90+
91+
application_service.save()
92+
updated_path = application_service.get_updated_path(bin_path)
93+
94+
return updated_path

0 commit comments

Comments
 (0)