Skip to content
Open
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
75 changes: 47 additions & 28 deletions qbuild/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,51 +31,70 @@ def is_ignored_by_gitignore(path):
return False


def _list_unignored(base_dir, only_files, path):
base, dirs, files = next(os.walk(path))
for f in files:
ff = os.path.join(base, f)
if f == ".gitignore":
yield ff
elif not is_ignored_by_gitignore(ff):
yield ff
for d in dirs:
if d == ".git":
def _list_dirs(path):
for base, _, _ in os.walk(path):
if base == path:
continue
dd = os.path.join(base, d)
if not is_ignored_by_gitignore(dd):
if not only_files:
yield dd
yield from _list_unignored(base_dir, only_files, dd)
if "/.git/" in os.path.normpath(base) + "/":
continue
yield base


def _list_all(path, only_files):
for base, dirnames, filenames in os.walk(path):
for filename in filenames:
yield os.path.join(base, filename)
if not only_files:
for dirname in dirnames:
if dirname == ".git":
continue
yield os.path.join(base, dirname)
def _list_unignored(base_dir, only_files, only_dirs, path):
if only_dirs:
yield from _list_dirs(path)
else:
base, dirs, files = next(os.walk(path))
for f in files:
ff = os.path.join(base, f)
if f == ".gitignore":
yield ff
elif not is_ignored_by_gitignore(ff):
yield ff
for d in dirs:
if d == ".git":
continue
dd = os.path.join(base, d)
if not is_ignored_by_gitignore(dd):
if not only_files:
yield dd
yield from _list_unignored(base_dir, only_files, only_dirs, dd)


def _list_all(path, only_files, only_dirs):
if only_dirs:
yield from _list_dirs(path)
else:
for base, dirnames, filenames in os.walk(path):
for filename in filenames:
yield os.path.join(base, filename)
if not only_files:
for dirname in dirnames:
if dirname == ".git":
continue
yield os.path.join(base, dirname)


def ls_recursive(path, relative=False, exclude_gitignore=False, only_files=False):
def ls_recursive(path, relative=False, exclude_gitignore=False, only_files=False, only_dirs=False):
"""
Always skips .git folder
:param path: The path to list files (or dirs) inside it
:param relative: If True, returned paths will be relative to `path`
:param exclude_gitignore: If True, only paths that are not ignored by .gitignore files will be returned.
In this case, `path` must be inside a git repo.
:param only_files: If True, only files will be returned (skips directories)
:param only_dirs: If True, only directories will be returned (skips files)
:return: A list of paths inside `path`
"""
if only_dirs and only_files:
raise Exception("Only one of `only_dirs` and `only_files` can be True")
if exclude_gitignore:
if not is_inside_git_repo(path):
raise NotGitRepoException
absolute_paths = list(_list_unignored(path, only_files, path))

absolute_paths = list(_list_unignored(path, only_files, only_dirs, path))
else:
absolute_paths = list(_list_all(path, only_files))
absolute_paths = list(_list_all(path, only_files, only_dirs))
if relative:
return [os.path.relpath(i, start=path) for i in absolute_paths]
else:
Expand All @@ -94,7 +113,7 @@ def get_comment_style(commented_line, scb):
raise Exception
ss, ff = comment_parts[0].lstrip(), comment_parts[1].rstrip()
s, f = ss.rstrip(), ff.lstrip()
return [s, ss[len(s) :], ff[: -len(f)], f]
return [s, ss[len(s):], ff[: -len(f)], f]


def uncomment(commented_line, comment_style):
Expand Down
22 changes: 22 additions & 0 deletions qbuild/qbuild
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,27 @@ import shutil
from collections import OrderedDict
from fnmatch import fnmatchcase
import sh
from uuid import uuid4
from jinja2 import Environment, TemplateNotFound
from qbuild.color_print import Color, cprint
from qbuild.helpers import ls_recursive, load_statement_templates, uncomment, get_comment_style
from qbuild.tree import tree


def create_file_in_all_empty_directories(path, file_name=None):
if file_name is None:
file_name = f"{uuid4().hex}.to_be_deleted_file"

created_files = []
for d in ls_recursive(path, only_dirs=True):
if not os.listdir(d):
file_path = os.path.join(d, file_name)
open(os.path.join(d, file_name), "w").close()
created_files.append(file_path)

return created_files


class Builder:
SOLUTION_COMMENT_BEGIN = ["_q_hide_from_users_begin", "_q_solution_begin"]
TEST_COMMENT_BEGIN = ["_q_test_begin"]
Expand Down Expand Up @@ -150,11 +165,14 @@ class Builder:
except FileNotFoundError:
pass
os.rename(os.path.join(path, ignorefile), os.path.join(path, ".gitignore"))
to_be_deleted_files = create_file_in_all_empty_directories(path)
sh.git.init(_cwd=path)
sh.git.add(".", _cwd=path)
sh.git.clean("-xdf", _cwd=path)
shutil.rmtree(os.path.join(path, ".git"))
os.remove(os.path.join(path, ".gitignore"))
for f in to_be_deleted_files:
os.remove(f)

@staticmethod
def run_qrun(path, export):
Expand Down Expand Up @@ -363,6 +381,10 @@ class Builder:
if not os.path.exists(d):
os.makedirs(d)
shutil.copy2(os.path.join(self.SRC_DIR, item), d)
for d in ls_recursive(self.SRC_DIR, relative=True, exclude_gitignore=True, only_dirs=True):
d_copy_path = os.path.join(self.SRC_DIR_2, d)
if not os.path.exists(d_copy_path):
os.makedirs(d_copy_path)

for export in self.EXPORTS:
name = self.get_export_name(export)
Expand Down
2 changes: 1 addition & 1 deletion qbuild/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.3.7"
__version__ = "0.3.8"