[Diff] Added support for stashing submodules

Related to #265
This commit is contained in:
Salvador E. Tropea 2022-09-05 13:35:04 -03:00
parent 11d1b7ffcb
commit a4abb65ef3
3 changed files with 69 additions and 22 deletions

View File

@ -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']

View File

@ -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)

View File

@ -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)