Skip to content

Commit

Permalink
feat: ascii art prints and log class
Browse files Browse the repository at this point in the history
  • Loading branch information
lpmatos committed Jul 29, 2020
1 parent 4f68095 commit ee47144
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 29 deletions.
2 changes: 1 addition & 1 deletion gitlabrc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

VERSION = (0, 0, 1)

__version__ = ".".join(map(str, VERSION))
__version__ = ".".join(map(str, VERSION)) + "-rc10"
56 changes: 34 additions & 22 deletions gitlabrc/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from art import *
from git import Repo

from .log import Log
from .tree import Tree
from .process import Process
from .base import GitLabBase
Expand All @@ -16,6 +17,12 @@
from .progress import CloneProgress
from . import __version__ as VERSION

# ==============================================================================
# GLOBAL
# ==============================================================================

logger = Log("/var/log/gitlabrc", "file.log", "INFO", "GitLabRC").logger

# ==============================================================================
# FUNCTIONS
# ==============================================================================
Expand All @@ -25,8 +32,8 @@ def pname():

def check_git():
if shutil.which("git") == "None":
sys.stderr.write("Error: git executable not installed or not in $PATH" + "\n")
exit(2)
logger.error("Error: git executable not installed or not in $PATH")
exit(1)

def get_subgroups(gl, group, root=False, info=False):
if root:
Expand All @@ -43,6 +50,7 @@ def get_projects(gl, group, root=False):
return group.projects.list(all=True)

def get_all_projects(gl, namespace):
logger.info("getting all projects")
projects = list()
root_projects = get_projects(gl, namespace, root=True)
rooot_subgroups = get_subgroups(gl, namespace, root=True)
Expand Down Expand Up @@ -70,66 +78,70 @@ def get_all_projects(gl, namespace):
return projects

def main():
Art=text2art("GitLabRC")
print(Art)
print(text2art("GitLabRC"))
check_git()
args = Arguments(argv=None if sys.argv[1:] else ["--help"]).args
if args.version:
print(f"Version: {VERSION}")
sys.exit(0)
exit(1)
else:
print(f"Version: {VERSION}\n")
run(args)
run(args)

def run(options):
url, token, namespace, path = options.url, options.token, options.namespace, options.path
gl, t = GitLabBase(url, token).client, time.time()

if path:
if not os.path.isdir(path):
sys.stderr.write("\nError: destination path does not exist " + options.path + "\n\n")
logger.error(f"error: destination path does not exist {options.path}")
exit(1)

print("Getting projects...\n")
if not namespace:
logger.error("error: we need a namespace")
exit(1)

projects = get_all_projects(gl, namespace)

if options.tree:
print(text2art("Tree"))
tree = Tree()
projects_parse = [project.path_with_namespace for project in projects]
projects_parse_content = [[value + " " for value in elemento.split("/")] for elemento in projects_parse]
d = tree.make(projects_parse_content)
tree.show(d)
parse = [project.path_with_namespace for project in projects]
parse_content = [[value + " " for value in elemento.split("/")] for elemento in parse]
tree.show(tree.make(parse_content))
logger.info(f"mission accomplished in {str(round(time.time() - t, 2))} s")
exit(0)

print(text2art("Projects"))
for project in projects:
print(f"{pname()} found {project.path_with_namespace}")

print(pname() + " mission accomplished in " + str(round(time.time() - t, 2)) + "s")
exit(0)

if not options.dryrun:
for index, project in enumerate(projects, start=1):
print(pname() + " clone/fetch project " + project.path_with_namespace)
print(f"{pname()} clone/fetch project {project.path_with_namespace}")
folders = [f.strip().lower() for f in project.path_with_namespace.split("/")]
if options.noroot:
folders.remove(namespace)

if options.noroot: folders.remove(namespace)

mkdir = options.path
for i in range(len(folders) - 1):
mkdir = mkdir + "/" + folders[i]
if not os.path.isdir(mkdir):
os.mkdir(mkdir)

clone_path = options.path + "/" + "/".join(str(x) for x in folders)
clone_path = re.sub("/+", "/", clone_path)
print(pname() + " folder " + clone_path)

print(f"{pname()} folder {clone_path}")

project_url = project.http_url_to_repo if options.method is CloneMethod.HTTP else project.ssh_url_to_repo

if not os.path.isdir(clone_path):
print(f"\n{pname()} cloning {project_url}")
print(text2art("Cloning"))
Repo.clone_from(project_url, clone_path, branch="master", progress=CloneProgress())
else:
print(f"\n{pname()} fetching {project_url}")
print(text2art("Fetching"))
Process().run_command(f"git -C {clone_path} fetch --all")

print(pname() + " mission accomplished in " + str(round(time.time() - t, 2)) + "s")
logger.info(f"mission accomplished in {str(round(time.time() - t, 2))} s")
exit(0)
93 changes: 93 additions & 0 deletions gitlabrc/log.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# -*- coding: utf-8 -*-

import logging
import coloredlogs
from typing import NoReturn, Text
from pythonjsonlogger import jsonlogger
from abc import ABCMeta, abstractmethod
from typing import NoReturn, Text, List

class StrategyHandler(metaclass=ABCMeta):

@abstractmethod
def handler(self, *args, **kwargs) -> NoReturn:
pass

class ContextHandler:

def __init__(self, strategy: StrategyHandler) -> NoReturn:
self._strategy = strategy

@property
def strategy(self) -> StrategyHandler:
return self._strategy

def get_handler(self, *args, **kwargs) -> NoReturn:
return self._strategy.handler(*args, **kwargs)

class BaseFileHandler(StrategyHandler):

@staticmethod
def handler(*args, **kwargs) -> logging.FileHandler:
file_handler = logging.FileHandler(filename=kwargs["log_file"])
file_handler.setLevel(kwargs["log_level"])
file_handler.setFormatter(jsonlogger.JsonFormatter(kwargs["formatter"]))
return file_handler

class BaseStreamHandler(StrategyHandler):

@staticmethod
def handler(*args, **kwargs) -> logging.StreamHandler:
stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setLevel(kwargs["log_level"])
stream_handler.setFormatter(jsonlogger.JsonFormatter(kwargs["formatter"]))
return stream_handler

class SingletonLogger(type):

_instances = {}

def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(SingletonLogger, cls).__call__(*args, **kwargs)
return cls._instances[cls]

class Log(metaclass=SingletonLogger):

def __init__(self, log_path: Text, log_file: Text, log_level: Text, logger_name: Text) -> NoReturn:

self._log_path = log_path
self._log_file = log_file
self._log_level = log_level if log_level in ["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "NOTSET"] else None
self._logger_name = logger_name
self.formatter = "%(levelname)s - %(asctime)s - %(message)s - %(funcName)s"
self._logger = logging.getLogger(self.logger_name)
self._logger.setLevel(self.log_level)
self._base_configuration_log_colored()
self._logger.addHandler(ContextHandler(BaseFileHandler()).get_handler(log_file=self.log_file, log_level=self.log_level, formatter=self.formatter))

def _base_configuration_log_colored(self) -> coloredlogs.install:
coloredlogs.install(level=self._log_level,
logger=self.logger,
fmt=self.formatter,
milliseconds=True)

@property
def log_path(self) -> Text:
return self._log_path

@property
def log_file(self) -> Text:
return self._log_file

@property
def log_level(self) -> Text:
return self._log_level

@property
def logger_name(self) -> Text:
return self._logger_name

@property
def logger(self) -> Text:
return self._logger
8 changes: 4 additions & 4 deletions gitlabrc/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def run_command(command: Type[Text]) -> Text:
try:
if not isinstance(command, str):
sys.stderr.write(f"We spec a string value, not {type(command)}")
sys.exit(1)
exit(1)
process = subprocess.Popen(
command,
stdin=subprocess.PIPE,
Expand All @@ -22,11 +22,11 @@ def run_command(command: Type[Text]) -> Text:
output, errors = process.communicate()
if process.returncode != 0:
sys.stderr.write(f"Run command failed - status process returncode - {process.returncode}")
sys.exit(1)
exit(1)
return (output, errors)
except subprocess.CalledProcessError as error:
sys.stderr.write(f"Subprocess error when run the command {command} - {error}")
sys.exit(1)
exit(1)
except Exception as error:
sys.stderr.write(f"Error general exception in run the command {command} - {error}")
sys.exit(1)
exit(1)
8 changes: 7 additions & 1 deletion gitlabrc/progress.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
from git import RemoteProgress
from typing import NoReturn, Optional, Text

class CloneProgress(RemoteProgress):

def update(self, op_code, cur_count, max_count=None, message=""):
def update(self,
op_code: int,
cur_count: int,
max_count: Optional = None,
message: Text = ""
) -> NoReturn:
end = "\r"

if op_code & RemoteProgress.END:
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
art==4.7
tqdm==4.43.0
GitPython==3.1.7
coloredlogs==14.0
python-gitlab==2.4.0
python-json-logger==0.1.11
4 changes: 3 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
"art",
"tqdm",
"GitPython",
"python-gitlab"
"coloredlogs",
"python-gitlab",
"python-json-logger"
]

# Getting current location.
Expand Down

0 comments on commit ee47144

Please sign in to comment.