diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..7c2b992 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,38 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "gui", + "type": "python", + "request": "launch", + "program": "pico_project.py", + "args": [ + "--gui", + ], + "console": "integratedTerminal", + "justMyCode": true + }, + { + "name": "cli", + "type": "python", + "request": "launch", + "program": "pico_project.py", + "args": [ "--overwrite", "-p", "git", + "projectName", + ], + "console": "integratedTerminal", + "justMyCode": true + }, + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "justMyCode": true + }, + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..44cb5b9 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "python.linting.enabled": false, + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter" + }, + "python.formatting.provider": "none" +} \ No newline at end of file diff --git a/README.md b/README.md index b9dd2d9..4f3ad9b 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ IDE Options | Description ------------| ----------- Create VSCode Project | As well as the CMake files, also create the appropriate Visual Studio Code project files. Debugger | Use the specified debugger in the IDE +Git | Generate initial README and LICENSE, init the directory and do an initial commit diff --git a/pico_project.py b/pico_project.py index b906af1..32fcac4 100755 --- a/pico_project.py +++ b/pico_project.py @@ -15,6 +15,10 @@ import platform import shlex import csv +from jinja2 import FileSystemLoader, Template +import datetime +from importlib import resources as impresources +import templates # TODO: conditional import of tkinter if --gui option is used try: @@ -787,6 +791,9 @@ def init_window(self, args): ttk.Label(vscodeoptionsSubframe, text = " Debugger:").grid(row=0, column=1, padx=4, sticky=tk.W) + self.wantGit = tk.IntVar() + ttk.Checkbutton(vscodeoptionsSubframe, text="Git", variable=self.wantGit).grid(row=1, column=0, padx=4, sticky=tk.W) + self.debugger = ttk.Combobox(vscodeoptionsSubframe, values=debugger_list, state="readonly") self.debugger.grid(row=0, column=2, padx=4, sticky=tk.W) self.debugger.current(args.debugger) @@ -831,6 +838,8 @@ def OK(self): projects = list() if (self.wantVSCode.get()): projects.append("vscode") + if (self.wantGit.get()): + projects.append("git") params={ 'sdkPath' : self.sdkpath, @@ -1240,13 +1249,65 @@ def generateProjectFiles(projectPath, projectName, sdkPath, projects, debugger): file = open(VSCODE_EXTENSIONS_FILENAME, 'w') file.write(e1) file.close() - + elif p == "git": + initialiseGit(projectPath, projectName) else : print('Unknown project type requested') os.chdir(oldCWD) +def initialiseGit(projectPath:str, projectName:str) -> bool: + """ + Create basic setup for a git repo in the generated project directory. + + generate a basic .gitignore + generate a stub for README.md (and maybe an empty LICENCE.txt) + if we find a runnable git + git init in the generated project directory + an initial git commit of the generated files + """ + template_dir = os.path.join(os.path.split(os.path.abspath(__file__))[0], "templates") + template_dir = impresources.files(templates) + src_file = template_dir / '.gitignore' + dest_file = os.path.join(projectPath, '.gitignore') + try: + shutil.copyfile(src_file, dest_file) + except (IOError, PermissionError) as e: + print(f"Failed to copy {src_file} to {dest_file}\n{e}") + + templated_files = ['README.md', 'LICENCE.txt'] + template_data = {"ProjectName": projectName, "year": datetime.datetime.now().year} + for templated_file in templated_files: + with open(template_dir / f'{templated_file}.j2', "r") as f: + template = Template(f.read()) + rendered = template.render(template_data) + try: + with open(os.path.join(projectPath, templated_file), "w") as f: + f.write(rendered) + except (IOError, PermissionError) as e: + print(f"Failed to write {os.path.join(projectPath, templated_file)}\n{e}") + + # attempt to initialise the git repo + git = shutil.which("git") + if not git: + print("Failed to find an executable for git, skipping git init") + return False + commands = [[git, "init"], + [git, "add", "-A"], + [git, "commit", "-m", "'Initial project generated by pico-project-generator'"], + ] + for command in commands: + rc = subprocess.run(command, cwd=projectPath, capture_output=True, text=True) + if rc.returncode == 0: + if len(rc.stdout) > 0: + print(rc.stdout) + else: + print(rc.stderr) + break + + + def LoadConfigurations(): try: with open(args.tsv) as tsvfile: diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..95337eb --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +jinja2 + +pytest \ No newline at end of file diff --git a/templates/.gitignore b/templates/.gitignore new file mode 100644 index 0000000..059b295 --- /dev/null +++ b/templates/.gitignore @@ -0,0 +1,10 @@ +# generated by pico-project-generator - please amend as required +# initial contents inspired by https://github.com/raspberrypi/pico-examples/blob/master/.gitignore + +.idea +.vscode +_deps +cmake-* +build +.DS_Store +*.pdf \ No newline at end of file diff --git a/templates/LICENCE.txt.j2 b/templates/LICENCE.txt.j2 new file mode 100644 index 0000000..630bb49 --- /dev/null +++ b/templates/LICENCE.txt.j2 @@ -0,0 +1,5 @@ +{{ ProjectName }} Copyright {{ year }} + +Please complete with the licence of your choice. + +You may find some helpful material here https://opensource.guide/legal/ and https://choosealicense.com/ \ No newline at end of file diff --git a/templates/README.md.j2 b/templates/README.md.j2 new file mode 100644 index 0000000..04d852f --- /dev/null +++ b/templates/README.md.j2 @@ -0,0 +1,4 @@ +# {{ ProjectName }} + +An initial README.md generated by pico-project-generator. Please amend as required. + diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000..49b471f --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,32 @@ +""" +Tests for the command line version +""" +import pytest +import subprocess +import os +from shutil import rmtree + + +def test_git_init(tmp_path): + tests_dir = os.path.dirname(os.path.abspath(__file__)) + cmd = os.path.abspath(os.path.join(tests_dir, "../pico_project.py")) + project_name = "test_git_project" + # clear any previous data + try: + rmtree(os.path.join(tmp_path, project_name)) + except FileNotFoundError: + pass + os.chdir(tmp_path) + cli_cmd = [cmd, "--project", "git", project_name] + result = subprocess.run(cli_cmd, capture_output=True, text=True) + assert result.returncode == 0 + for generated_file in [".gitignore", "LICENCE.txt", "README.md"]: + exists = os.path.exists(os.path.join(tmp_path, project_name, generated_file)) + assert exists is True + os.chdir(os.path.join(tmp_path, project_name)) + result = subprocess.run(["git", "log"], capture_output=True, text=True) + assert result.returncode == 0, f"git log test failed {result.stderr}" + + +if __name__ == "__main__": + test_git_init("/tmp")