diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..68618f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.my-work-resources/.config diff --git a/.my-work-resources/collect_lines_modified.py b/.my-work-resources/collect_lines_modified.py new file mode 100644 index 0000000..c09efa7 --- /dev/null +++ b/.my-work-resources/collect_lines_modified.py @@ -0,0 +1,25 @@ +# credits to OG: Piotr Karkut + +import subprocess +import sys +from collections import Counter + +data = Counter() +directory, date, gituser = sys.argv[1], sys.argv[2], sys.argv[3] + +log = subprocess.check_output(f'git -C ./{directory} log --all --after="{date}-01 00:00" --before="{date}-31 23:59" --author={gituser} --pretty=format:"%h"', shell=True) + +for commit in log.splitlines(): + commit = commit.decode() + try: + stats = subprocess.check_output(f'git -C ./{directory} diff %s^ %s --numstat' % (commit, commit), shell=True, stderr=open('/dev/null')) + except Exception: + stats = subprocess.check_output(f'git -C ./{directory} diff 4b825dc642cb6eb9a060e54bf8d69288fbee4904 %s --numstat' % commit, shell=True) + for stat in stats.splitlines(): + ins, dels, f = stat.split(None, 2) + try: + data[f.decode()] += (int(ins) + int(dels)) + except Exception: + pass + +print("('{0}', {1})".format(directory, list(data.items()) or [])) diff --git a/.my-work-resources/generate_report.py b/.my-work-resources/generate_report.py new file mode 100644 index 0000000..2e7934c --- /dev/null +++ b/.my-work-resources/generate_report.py @@ -0,0 +1,42 @@ +import sys +from pathlib import Path + +from weasyprint import HTML, CSS +from ast import literal_eval +from jinja2 import Environment, FileSystemLoader + + +current_directory = Path(__file__).parent + +env = Environment(loader=FileSystemLoader(current_directory)) + + +def render_template(_name_and_surname, _report_date, _report_data): + return env.get_template("report-template.j2").render( + name_and_surname=_name_and_surname, + report_date=_report_date, + report_data=_report_data, + ) + + +name_and_surname, report_date, report_data_file = sys.argv[1], sys.argv[2], sys.argv[3] +with open(report_data_file, "r") as f: + report_data_raw = f.read() + +# HACK: from bash array to Python list :facepalm: +report_data = literal_eval("[" + report_data_raw.replace(")(", "), (") + "]") +report_data = [entry for entry in report_data if entry[1]] + +html_text = render_template( + _name_and_surname=name_and_surname, + _report_date=report_date, + _report_data=report_data, +) + +html = HTML(string=html_text) +css = CSS(str(current_directory / "report-template.css")) + +html.write_pdf( + str(current_directory.parent / "my-work-reports" / f"{report_date}.pdf"), + stylesheets=[css], +) diff --git a/.my-work-resources/report-template.css b/.my-work-resources/report-template.css new file mode 100644 index 0000000..f55d343 --- /dev/null +++ b/.my-work-resources/report-template.css @@ -0,0 +1,6 @@ +@page { + margin-bottom: 2.5cm; + @bottom-center{ + content: "Strona " counter(page) " z " counter(pages); + } +} diff --git a/.my-work-resources/report-template.j2 b/.my-work-resources/report-template.j2 new file mode 100644 index 0000000..ca4b036 --- /dev/null +++ b/.my-work-resources/report-template.j2 @@ -0,0 +1,30 @@ + + + + raport-pracy-tworczej-{{ report_date }} + + +

[{{ name_and_surname }}] Zestawienie efektów pracy twórczej stanowiących utwór za okres {{ report_date }}

+

+ {% for project in report_data %} +

{{ project[0] }}

+ +
+ {% endfor %} +

+
+
+ Podpis pracownika:

+ ........................................ +
+
+ Podpis pracodawcy:

+ ........................................ +
+
+ + diff --git a/README.md b/README.md new file mode 100644 index 0000000..fe096ef --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# internal-tools +### Lokalny setup + +Projekt pozwala na proste generowanie raportów potrzebnych do rozliczania godzin pracy twórczej. +Aby narzędzie działało poprawnie należy spełnić podstawowe zależności: + - Python 3 + - poprawnie uporządkowane katalogi projektowe (przykład w zakładce #WSF (Wymagana Struktura Folderów)) + +### WSF (Wymagana Struktura Folderów) +Do poprawnego działania skyptu wymagana jest następująca folderów: + +``` + /folder-glowny (tutaj powinny znjdować się wszystkie projekty które chcemy uwzględnić w raporcie) + /projekt1 + /projekt2 + ... +``` + +W `/folder-glowny` nie powinien znajdować się plik `.git` - taka sytuacja mogłaby wskazywać na złe umiejscowienie pliku skryptu. + +### I w końcu - jak tego użyć :national_park: + +Skopiuj zawartość repozytorium do katalogu głównego: + +*Upewnij się, że jesteś w folderze głównym, a repozytorium `internal-tools` również zostało umieszczone pod nim. + +```bash +$ pwd +/.../folder-glowny +$ cp -r internal-tools/. . +$ ls +projekt1 projekt2 my-work.sh ... +``` + +Opcjonalnie można też usunąć plik README.md: + +```bash +$ pwd +/.../folder-glowny +$ rm -f README.md +``` + +### Uruchomienie skryptu + +```bash +$ ./my-work.sh +``` + +### Gdzie znajdę raport :thinking: + +Raporty będę dostępne w katalogu `my-work-reports` znajdującego się w katalogu `/folder-glowny` diff --git a/my-work.sh b/my-work.sh index a13c055..159e56b 100755 --- a/my-work.sh +++ b/my-work.sh @@ -1,54 +1,94 @@ #!/bin/sh +BASE_RESOURCE_PATH=./.my-work-resources/ +PROJECT_PYTHON_ENV_NAME=my-work-venv +LINES_MODIFIED_PATH=${BASE_RESOURCE_PATH}collect_lines_modified.py +REPORT_GENERATE_PATH=${BASE_RESOURCE_PATH}generate_report.py +CONFIG_FILE_PATH=${BASE_RESOURCE_PATH}.config +REPORT_MULTI_LINE_PROJECT_ARRAY=() + +is_git_repo() { + [[ -d .git ]] || git -C ${1} rev-parse --git-dir > /dev/null 2>&1 +} + +check_if_python_virtual_env_exits() { + [[ -f "${BASE_RESOURCE_PATH}${PROJECT_PYTHON_ENV_NAME}" ]] +} + +create_python_virtual_env() { + python3 -m venv ${BASE_RESOURCE_PATH}${PROJECT_PYTHON_ENV_NAME} +} + +check_if_weasyprint_installed() { + pip list --disable-pip-version-check | grep -c WeasyPrint +} + +check_if_jinja2_installed() { + pip list --disable-pip-version-check | grep -c Jinja2 +} + + +if ! [[ -f "$CONFIG_FILE_PATH" ]]; then + read -p "Imię i nazwisko: " name surname + name_and_surname="${name} ${surname}" + if ! [[ -z "$name_and_surname" ]]; then + touch "${CONFIG_FILE_PATH}" + echo "name_and_surname='${name_and_surname}'" > "${CONFIG_FILE_PATH}" + fi; else + . ${CONFIG_FILE_PATH} +fi + +if [[ -z "$name_and_surname" ]]; then + echo "Konieczne poprawne wprowadzenie: Imię i nazwisko" +fi + defdate=`date "+%Y-%m"` read -p "Data logu rrrr-mm [${defdate}]: " date > "${CONFIG_FILE_PATH}" fi -echo -echo - -echo "=========================================================================" -echo "ZAŁĄCZNIK A do Raportu wykonania zlecenia" -echo "Changes in ${PWD##*/} for date: ${date}, created by: ${gituser}" -echo - -python > /dev/tty <<-EOF -import subprocess -from collections import Counter +mkdir -p my-work-reports -data = Counter() +if is_git_repo .; then + echo "'my-work.sh' should run in top directory" + exit 1 +fi -log = subprocess.check_output('git log --all --after="${date}-01 00:00" --before="${date}-31 23:59" --author=${gituser} --pretty=format:"%h"', shell=True) +if ! check_if_python_virtual_env_exits; then + create_python_virtual_env +fi -for commit in log.splitlines(): - commit = commit.decode() - try: - stats = subprocess.check_output('git diff %s^ %s --numstat' % (commit, commit), shell=True, stderr=open('/dev/null')) - except Exception: - stats = subprocess.check_output('git diff 4b825dc642cb6eb9a060e54bf8d69288fbee4904 %s --numstat' % commit, shell=True) - for stat in stats.splitlines(): - # print(stat.decode()) - ins, dels, f = stat.split(None, 2) - try: - data[f.decode()] += (int(ins) + int(dels)) - except Exception: - pass +if [ -f ${BASE_RESOURCE_PATH}${PROJECT_PYTHON_ENV_NAME}/bin/activate ]; then + source ${BASE_RESOURCE_PATH}${PROJECT_PYTHON_ENV_NAME}/bin/activate +else + source ${BASE_RESOURCE_PATH}${PROJECT_PYTHON_ENV_NAME}/Scripts/activate +fi -for f, ch in data.items(): - print("File %s, modified lines: %s" % (f, ch)) -EOF +if [[ "$(check_if_weasyprint_installed)" -lt 1 || "$(check_if_jinja2_installed)" -lt 1 ]]; then + pip install weasyprint + pip install Jinja2 +fi -echo "............. .............." -echo "Zleceniodawca Zleceniobiorca" -echo "=========================================================================" +for f in *; do + if [[ -d "$f" ]]; then + if is_git_repo "./$f"; then + REPORT_MULTI_LINE_PROJECT_ARRAY+="$(python ${LINES_MODIFIED_PATH} "$f" "$date" "$gituser")" + fi + fi +done +echo ${REPORT_MULTI_LINE_PROJECT_ARRAY[0]} > ${BASE_RESOURCE_PATH}/tmp +python ${REPORT_GENERATE_PATH} "${name_and_surname}" "${date}" "${BASE_RESOURCE_PATH}/tmp" +rm ${BASE_RESOURCE_PATH}/tmp \ No newline at end of file