From a4abb65ef397db439e388f58583e3c1fb1ca370d Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Mon, 5 Sep 2022 13:35:04 -0300 Subject: [PATCH] [Diff] Added support for stashing submodules Related to #265 --- kibot/out_diff.py | 42 ++++++++++++++++++++++++++------ tests/test_plot/test_misc.py | 47 ++++++++++++++++++++++++++---------- tests/utils/context.py | 2 +- 3 files changed, 69 insertions(+), 22 deletions(-) diff --git a/kibot/out_diff.py b/kibot/out_diff.py index 7269fc75..2242270a 100644 --- a/kibot/out_diff.py +++ b/kibot/out_diff.py @@ -21,6 +21,7 @@ Dependencies: """ from hashlib import sha1 import os +import re from shutil import rmtree, copy2 from tempfile import mkdtemp, NamedTemporaryFile from .error import KiPlotConfigurationError @@ -139,8 +140,31 @@ class DiffOptions(BaseOptions): def cache_file(self, name=None): return self.cache_pcb(name) if self.pcb else self.cache_sch(name) - def run_git(self, cmd): - return run_command([self.git_command]+cmd, change_to=self.repo_dir) + def run_git(self, cmd, cwd=None): + if cwd is None: + cwd = self.repo_dir + return run_command([self.git_command]+cmd, change_to=cwd) + + def stash_pop(self, cwd=None): + # We don't know if we stashed anything (push always returns 0) + # So we check that the last stash contains our message + res = self.run_git(['stash', 'list', 'stash@{0}'], cwd) + if STASH_MSG in res: + self.run_git(['stash', 'pop', '--index'], cwd) + + def git_submodules(self): + res = self.run_git(['submodule']) + reg = re.compile(r'^\s*([\da-z]+)\s+(\S+)\s+') + subs = [] + for ln in res.split('\n'): + rm = reg.search(ln) + if rm: + subm = os.path.join(self.repo_dir, rm.group(2)) + subs.append(subm) + if not os.path.isdir(subm): + KiPlotConfigurationError('Missing git submodule `{}`'.format(subm)) + logger.debug('Git submodules '+str(subs)) + return subs def undo_git(self): if self.checkedout: @@ -148,11 +172,10 @@ class DiffOptions(BaseOptions): self.run_git(['checkout', '--recurse-submodules', self.branch]) if self.stashed: logger.debug('Restoring changes') - # We don't know if we stashed anything (push always returns 0) - # So we check that the last stash contains our message - res = self.run_git(['stash', 'list', 'stash@{0}']) - if STASH_MSG in res: - self.run_git(['stash', 'pop', '--index']) + self.stash_pop() + # Do the same for each submodule + for sub in self.git_submodules(): + self.stash_pop(sub) def solve_git_name(self, name): ori = name @@ -195,6 +218,8 @@ class DiffOptions(BaseOptions): logger.debug('Saving current changes') self.run_git(['stash', 'push', '-m', STASH_MSG]) self.stashed = True + # Also save the submodules + self.run_git(['submodule', 'foreach', 'git stash push -m '+STASH_MSG]) # Find the current branch self.branch = self.run_git(['rev-parse', '--abbrev-ref', 'HEAD']) if self.branch == 'HEAD': @@ -291,7 +316,8 @@ class DiffOptions(BaseOptions): @output_class class Diff(BaseOutput): # noqa: F821 """ Diff - Generates a PDF with the differences between two PCBs or schematics """ + Generates a PDF with the differences between two PCBs or schematics. + Recursive git submodules aren't supported (submodules inside submodules) """ def __init__(self): super().__init__() self._category = ['PCB/docs', 'Schematic/docs'] diff --git a/tests/test_plot/test_misc.py b/tests/test_plot/test_misc.py index 48431232..1b4f9bdf 100644 --- a/tests/test_plot/test_misc.py +++ b/tests/test_plot/test_misc.py @@ -1278,10 +1278,10 @@ def test_diff_file_1(test_dir): ctx.clean_up(keep_project=True) -def git_init(ctx): - ctx.run_command(['git', 'init', '.'], chdir_out=True) - ctx.run_command(['git', 'config', 'user.email', 'pytest@nowherem.com'], chdir_out=True) - ctx.run_command(['git', 'config', 'user.name', 'KiBot test'], chdir_out=True) +def git_init(ctx, cwd=True): + ctx.run_command(['git', 'init', '.'], chdir_out=cwd) + ctx.run_command(['git', 'config', 'user.email', 'pytest@nowherem.com'], chdir_out=cwd) + ctx.run_command(['git', 'config', 'user.name', 'KiBot test'], chdir_out=cwd) def test_diff_git_1(test_dir): @@ -1313,33 +1313,54 @@ def test_diff_git_2(test_dir): prj = 'light_control' yaml = 'diff_git_2' ctx = context.TestContext(test_dir, prj, yaml) + # Create something to use as submodule + sub_dir = os.path.join(ctx.output_dir, 'sub') + os.makedirs(sub_dir) + git_init(ctx, sub_dir) + some_file = os.path.join(sub_dir, 'some_file.txt') + with open(some_file, 'wt') as f: + f.write('Hello!\n') + ctx.run_command(['git', 'add', 'some_file.txt'], chdir_out=sub_dir) + ctx.run_command(['git', 'commit', '-m', 'Some change'], chdir_out=sub_dir) # Create a git repo - git_init(ctx) + repo_dir = os.path.join(ctx.output_dir, 'repo') + os.makedirs(repo_dir) + git_init(ctx, repo_dir) # Copy the "old" file pcb = prj+'.kicad_pcb' - file = ctx.get_out_path(pcb) + file = os.path.join(repo_dir, pcb) shutil.copy2(ctx.board_file, file) shutil.copy2(ctx.board_file.replace('.kicad_pcb', context.KICAD_SCH_EXT), file.replace('.kicad_pcb', context.KICAD_SCH_EXT)) # Add it to the repo - ctx.run_command(['git', 'add', pcb], chdir_out=True) - ctx.run_command(['git', 'commit', '-m', 'Reference'], chdir_out=True) + ctx.run_command(['git', 'add', pcb], chdir_out=repo_dir) + ctx.run_command(['git', 'commit', '-m', 'Reference'], chdir_out=repo_dir) + # Add a submodule + ctx.run_command(['git', 'submodule', 'add', '../sub'], chdir_out=repo_dir) # Add an extra commit - dummy = ctx.get_out_path('dummy') + dummy = os.path.join(repo_dir, 'dummy') with open(dummy, 'wt') as f: f.write('dummy\n') - ctx.run_command(['git', 'add', 'dummy'], chdir_out=True) - ctx.run_command(['git', 'commit', '-m', 'Dummy noise'], chdir_out=True) + ctx.run_command(['git', 'add', 'dummy'], chdir_out=repo_dir) + ctx.run_command(['git', 'commit', '-m', 'Dummy noise'], chdir_out=repo_dir) # Copy the "new" file shutil.copy2(ctx.board_file.replace(prj, prj+'_diff'), file) # Add it to the repo - ctx.run_command(['git', 'add', pcb], chdir_out=True) - ctx.run_command(['git', 'commit', '-m', 'New version'], chdir_out=True) + ctx.run_command(['git', 'add', pcb], chdir_out=repo_dir) + ctx.run_command(['git', 'commit', '-m', 'New version'], chdir_out=repo_dir) # Now just wipe the current file shutil.copy2(ctx.board_file.replace(prj, '3Rs'), file) + # Change the file in the submodule + some_file = os.path.join(repo_dir, 'sub', 'some_file.txt') + with open(some_file, 'wt') as f: + f.write('Bye!\n') # Run the test ctx.run(extra=['-b', file], no_board_file=True, extra_debug=True) ctx.compare_pdf(prj+'-diff_pcb.pdf') + # Check the submodule was restored + with open(some_file, 'rt') as f: + msg = f.read() + assert msg == 'Bye!\n' ctx.clean_up(keep_project=True) diff --git a/tests/utils/context.py b/tests/utils/context.py index 6a073a93..d97e7804 100644 --- a/tests/utils/context.py +++ b/tests/utils/context.py @@ -332,7 +332,7 @@ class TestContext(object): def run_command(self, cmd, chdir_out=False): if chdir_out: cwd = os.getcwd() - os.chdir(self.output_dir) + os.chdir(self.output_dir if isinstance(chdir_out, bool) else chdir_out) logging.debug('Executing: '+usable_cmd(cmd)) try: res = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)