Skip to content

Commit 14458c2

Browse files
committed
fix: setup package name
1 parent 6b223d7 commit 14458c2

File tree

8 files changed

+57
-164
lines changed

8 files changed

+57
-164
lines changed

gitlabrc/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
22

3-
VERSION = (1, 3, 0)
3+
VERSION = (1, 0, 1)
44

55
__version__ = ".".join(map(str, VERSION))

gitlabrc/arguments.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def __init__(self, argv: Optional[Sequence[str]] = None) -> None:
1616

1717
def _create_parser_object(self) -> ArgumentParser:
1818
return ArgumentParser(
19-
description="GitlabRC is a CLI that help you clone projects inside a specific group (namespace) in Gitlab",
19+
description="GitlabRC is a CLI that helps you clone projects inside a specific group (namespace) in Gitlab",
2020
prog="gitlabrc",
2121
epilog=CLI,
2222
formatter_class=RawTextHelpFormatter,
@@ -48,15 +48,15 @@ def _adding_arguments(self) -> None:
4848
dest="namespace",
4949
default="",
5050
metavar="<namespace>",
51-
help="namespace that represent a GitLab group used to clone/fetch all projects",
51+
help="namespace that represents a GitLab group used to clone/fetch all projects",
5252
)
5353
self._parser.add_argument(
5454
"-p",
5555
"--path",
5656
dest="path",
5757
default=self._config.get_env("PWD"),
5858
metavar="<path>",
59-
help="destination path into your system to clone/fetch all projects",
59+
help="destination path in your system to clone/fetch all projects",
6060
)
6161
self._parser.add_argument(
6262
"-m",
@@ -66,7 +66,7 @@ def _adding_arguments(self) -> None:
6666
default=self._config.get_env("GITLAB_CLONE_METHOD", "http"),
6767
metavar="<method>",
6868
choices=list(CloneMethod),
69-
help="method used in GitLabRC to cloning repositories (either <http> or <ssh>)",
69+
help="method used in GitLabRC to clone repositories (either <http> or <ssh>)",
7070
)
7171
self._parser.add_argument(
7272
"--disable-root",
@@ -94,6 +94,14 @@ def _adding_arguments(self) -> None:
9494
action="store_true",
9595
dest="signal",
9696
default=False,
97-
help="enable signal handler to exit in a CTRL + C",
97+
help="enable signal handler to exit on CTRL + C",
9898
)
9999
self._parser.add_argument("--version", action="store_true", help="show version")
100+
self._parser.add_argument(
101+
"--log-level",
102+
type=str,
103+
dest="log_level",
104+
default="WARNING",
105+
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
106+
help="set the logging level",
107+
)

gitlabrc/base.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from dataclasses import dataclass, field
66
from gitlab.client import Gitlab
77
import gitlab.exceptions as exceptions
8+
from loguru import logger
89

910

1011
class CloneMethod(Enum):
@@ -32,7 +33,7 @@ def client(self) -> Gitlab:
3233
instance = Gitlab(self.url, private_token=self.token)
3334
instance.auth()
3435
except exceptions.GitlabAuthenticationError as error:
35-
print(f"GitLab authenticantion error - {error}")
36+
logger.error(f"GitLab authentication error - {error}")
3637
exit()
3738
else:
3839
return instance

gitlabrc/cli.py

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,21 @@
66
import time
77
import signal
88
import shutil
9-
from art import text2art
109
from git import Repo
1110

12-
from .log import Log
11+
from .log import setup_logging
1312
from .tree import Tree
1413
from .process import Process
1514
from .arguments import Arguments
1615
from .progress import CloneProgress
1716
from .base import GitLabBase, CloneMethod
1817
from . import __version__ as VERSION
19-
20-
# ==============================================================================
21-
# GLOBAL
22-
# ==============================================================================
23-
24-
logger = Log("/var/log/gitlabrc", "file.log", "INFO", "GitLabRC").logger
18+
from loguru import logger
2519

2620
# ==============================================================================
2721
# FUNCTIONS
2822
# ==============================================================================
2923

30-
3124
def pname():
3225
return f"[gitlabrc - {str(os.getpid())}]"
3326

@@ -38,7 +31,7 @@ def signal_handler(sig, frame):
3831

3932

4033
def check_git():
41-
if shutil.which("git") == "None":
34+
if shutil.which("git") is None:
4235
logger.error("Error: git executable not installed or not in $PATH")
4336
exit(1)
4437

@@ -62,7 +55,7 @@ def get_projects(gl, group, root=False):
6255

6356

6457
def get_all_projects(gl, namespace):
65-
logger.info("getting all projects")
58+
logger.info("Getting all projects")
6659
projects = list()
6760
root_projects = get_projects(gl, namespace, root=True)
6861
root_subgroups = get_subgroups(gl, namespace, root=True)
@@ -105,11 +98,10 @@ def create_directories(path, folders, namespace, noroot):
10598

10699
def clone_project(project, clone_path, project_url):
107100
if not os.path.isdir(clone_path):
108-
print(text2art("Cloning"))
101+
logger.info(f"Cloning {project.path_with_namespace}")
109102
try:
110103
if project.empty_repo:
111104
logger.warning(f"Repository is empty: {project.path_with_namespace}")
112-
print(f"Warning: Repository is empty: {project.path_with_namespace}")
113105
os.makedirs(clone_path, exist_ok=True)
114106
Repo.init(clone_path)
115107
repo = Repo(clone_path)
@@ -130,9 +122,6 @@ def clone_project(project, clone_path, project_url):
130122
logger.warning(
131123
f"Failed to clone {project.path_with_namespace} with branch 'main': {e_main}",
132124
)
133-
print(
134-
f"Warning: Failed to clone {project.path_with_namespace} with branch 'main': {e_main}",
135-
)
136125
try:
137126
Repo.clone_from(
138127
project_url,
@@ -145,41 +134,38 @@ def clone_project(project, clone_path, project_url):
145134
logger.error(
146135
f"Failed to clone {project.path_with_namespace} with branch 'master': {e_master}",
147136
)
148-
print(
149-
f"Failed to clone {project.path_with_namespace} with branch 'master': {e_master}",
150-
)
151137
except Exception as e:
152138
logger.error(f"Failed to clone {project.path_with_namespace}: {e}")
153-
print(f"Failed to clone {project.path_with_namespace}: {e}")
154139

155140

156141
def fetch_project(clone_path):
157-
print(text2art("Fetching"))
142+
logger.info(f"Fetching updates for {clone_path}")
158143
Process().run_command(f"git -C {clone_path} fetch --all")
159144

160145

161146
def handle_tree_option(projects, t):
162-
print(text2art("Tree"))
147+
logger.info("Generating tree representation")
163148
tree = Tree()
164149
parse = [project.path_with_namespace for project in projects]
165150
parse_content = [
166151
[value + " " for value in elemento.split("/")] for elemento in parse
167152
]
168153
tree.show(tree.make(parse_content))
169-
logger.info(f"mission accomplished in {str(round(time.time() - t, 2))} s")
154+
logger.info(f"Mission accomplished in {str(round(time.time() - t, 2))} s")
170155
exit(0)
171156

172157

173158
def main():
174-
print(text2art("GitLabRC"))
175-
check_git()
176159
args = Arguments(argv=None if sys.argv[1:] else ["--help"]).args
160+
setup_logging(log_level=args.log_level)
161+
logger.info("Starting GitLabRC")
162+
check_git()
177163
if args.version:
178164
print(f"Version: {VERSION}")
179165
exit(1)
180166
if args.signal:
181167
signal.signal(signal.SIGINT, signal_handler)
182-
print(f"Version: {VERSION}\n")
168+
logger.info(f"Version: {VERSION}")
183169
run(args)
184170

185171

@@ -194,25 +180,25 @@ def run(options):
194180

195181
if path:
196182
if not os.path.isdir(path):
197-
logger.error(f"error: destination path does not exist {options.path}")
183+
logger.error(f"Error: destination path does not exist {options.path}")
198184
exit(1)
199185

200186
if not namespace:
201-
logger.error("error: we need a namespace")
187+
logger.error("Error: we need a namespace")
202188
exit(1)
203189

204190
projects = get_all_projects(gl, namespace)
205191

206192
if options.tree:
207193
handle_tree_option(projects, t)
208194

209-
print(text2art("Projects"))
195+
logger.info("Listing all projects")
210196
for project in projects:
211-
print(f"{pname()} found {project.path_with_namespace}")
197+
logger.info(f"Found {project.path_with_namespace}")
212198

213199
if not options.dryrun:
214200
for index, project in enumerate(projects, start=1):
215-
print(f"{pname()} clone/fetch project {project.path_with_namespace}")
201+
logger.info(f"Clone/fetch project {project.path_with_namespace}")
216202
folders = [
217203
f.strip().lower() for f in project.path_with_namespace.split("/")
218204
]
@@ -222,7 +208,7 @@ def run(options):
222208
clone_path = path + "/" + "/".join(str(x) for x in folders)
223209
clone_path = re.sub("/+", "/", clone_path)
224210

225-
print(f"{pname()} folder {clone_path}")
211+
logger.info(f"Folder {clone_path}")
226212

227213
project_url = (
228214
project.http_url_to_repo
@@ -234,5 +220,5 @@ def run(options):
234220
clone_project(project, clone_path, project_url)
235221
fetch_project(clone_path)
236222

237-
logger.info(f"mission accomplished in {str(round(time.time() - t, 2))} s")
223+
logger.info(f"Mission accomplished in {str(round(time.time() - t, 2))} s")
238224
exit(0)

gitlabrc/log.py

Lines changed: 5 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,9 @@
11
# -*- coding: utf-8 -*-
22

3-
import logging
4-
import coloredlogs
5-
from pythonjsonlogger import jsonlogger
6-
from abc import ABCMeta, abstractmethod
7-
from typing import TypeVar, Generic, Text, Optional
3+
from loguru import logger
84
import sys
95

10-
T = TypeVar("T", bound=logging.Handler)
11-
12-
13-
class StrategyHandler(Generic[T], metaclass=ABCMeta):
14-
@abstractmethod
15-
def handler(self, *args, **kwargs) -> T:
16-
pass
17-
18-
19-
class ContextHandler:
20-
def __init__(self, strategy: StrategyHandler) -> None:
21-
self._strategy = strategy
22-
23-
@property
24-
def strategy(self) -> StrategyHandler:
25-
return self._strategy
26-
27-
def get_handler(self, *args, **kwargs) -> logging.Handler:
28-
return self._strategy.handler(*args, **kwargs)
29-
30-
31-
class BaseFileHandler(StrategyHandler[logging.FileHandler]):
32-
@staticmethod
33-
def handler(*args, **kwargs) -> logging.FileHandler:
34-
file_handler = logging.FileHandler(filename=kwargs["log_file"])
35-
file_handler.setLevel(kwargs["log_level"])
36-
file_handler.setFormatter(jsonlogger.JsonFormatter(kwargs["formatter"]))
37-
return file_handler
38-
39-
40-
class BaseStreamHandler(StrategyHandler[logging.StreamHandler]):
41-
@staticmethod
42-
def handler(*args, **kwargs) -> logging.StreamHandler:
43-
stream_handler = logging.StreamHandler(sys.stdout)
44-
stream_handler.setLevel(kwargs["log_level"])
45-
stream_handler.setFormatter(jsonlogger.JsonFormatter(kwargs["formatter"]))
46-
return stream_handler
47-
48-
49-
class SingletonLogger(type):
50-
51-
_instances = {}
52-
53-
def __call__(cls, *args, **kwargs):
54-
if cls not in cls._instances:
55-
cls._instances[cls] = super(SingletonLogger, cls).__call__(*args, **kwargs)
56-
return cls._instances[cls]
57-
58-
59-
class Log(metaclass=SingletonLogger):
60-
def __init__(
61-
self,
62-
log_path: Text,
63-
log_file: Text,
64-
log_level: Optional[Text],
65-
logger_name: Text,
66-
) -> None:
67-
self._log_path = log_path
68-
self._log_file = log_file
69-
self._log_level = (
70-
log_level
71-
if log_level in ["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "NOTSET"]
72-
else "NOTSET"
73-
)
74-
self._logger_name = logger_name
75-
self.formatter = "%(levelname)s - %(asctime)s - %(message)s - %(funcName)s"
76-
self._logger = logging.getLogger(self.logger_name)
77-
self._logger.setLevel(self.log_level)
78-
self._base_configuration_log_colored()
79-
self._logger.addHandler(
80-
ContextHandler(BaseFileHandler()).get_handler(
81-
log_file=self.log_file,
82-
log_level=self.log_level,
83-
formatter=self.formatter,
84-
),
85-
)
86-
87-
def _base_configuration_log_colored(self) -> None:
88-
coloredlogs.install(
89-
level=self._log_level,
90-
logger=self.logger,
91-
fmt=self.formatter,
92-
milliseconds=True,
93-
)
94-
95-
@property
96-
def log_path(self) -> Text:
97-
return self._log_path
98-
99-
@property
100-
def log_file(self) -> Text:
101-
return self._log_file
102-
103-
@property
104-
def log_level(self) -> Text:
105-
return self._log_level
106-
107-
@property
108-
def logger_name(self) -> Text:
109-
return self._logger_name
110-
111-
@property
112-
def logger(self) -> logging.Logger:
113-
return self._logger
6+
def setup_logging(log_level="INFO"):
7+
logger.remove()
8+
logger.add(sys.stdout, format="{time} {level} {message}", level=log_level)
9+
logger.add("file.log", rotation="1 week", retention="1 month", level=log_level)

gitlabrc/process.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
# -*- coding: utf-8 -*-
22

3-
import sys
43
import subprocess
54
from typing import Text, Tuple
5+
from loguru import logger
66

77

88
class Process:
99
@staticmethod
1010
def run_command(command: Text) -> Tuple[Text, Text]:
1111
try:
1212
if not isinstance(command, str):
13-
sys.stderr.write(f"We expect a string value, not {type(command)}\n")
13+
logger.error(f"We expect a string value, not {type(command)}")
1414
exit(1)
1515
process = subprocess.Popen(
1616
command,
@@ -22,13 +22,13 @@ def run_command(command: Text) -> Tuple[Text, Text]:
2222
)
2323
output, errors = process.communicate()
2424
if process.returncode != 0:
25-
sys.stderr.write(
26-
f"Run command failed - status process returncode - {process.returncode}\n",
25+
logger.error(
26+
f"Run command failed - status process returncode - {process.returncode}",
2727
)
2828
exit(1)
2929
return (output, errors)
3030
except subprocess.CalledProcessError as error:
31-
sys.stderr.write(
32-
f"Subprocess error when running the command {command} - {error}\n",
31+
logger.error(
32+
f"Subprocess error when running the command {command} - {error}",
3333
)
3434
exit(1)

0 commit comments

Comments
 (0)