Skip to content

Commit

Permalink
Merge pull request #737 from seeM/fix-nbdev-merge-during-rebase
Browse files Browse the repository at this point in the history
fix `nbdev_merge` during rebase; fix `nbdev_fix` `nobackup` default
  • Loading branch information
seeM authored Aug 3, 2022
2 parents a833ac8 + 58ff0ee commit 3c991e6
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 61 deletions.
30 changes: 22 additions & 8 deletions nbdev/merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

# %% ../nbs/06_merge.ipynb 16
_BEG,_MID,_END = '<'*7,'='*7,'>'*7
conf_re = re.compile(rf'^{_BEG}\s+(\S+)\n(.*?)\n{_MID}\n(.*?)^{_END}\s+(\S+)\n', re.MULTILINE|re.DOTALL)
conf_re = re.compile(rf'^{_BEG}\s+(\S+)\n(.*?)\n{_MID}\n(.*?)^{_END}\s+([\S ]+)\n', re.MULTILINE|re.DOTALL)

def _unpatch_f(before, cb1, cb2, c, r):
if cb1 is not None and cb1 != cb2: raise Exception(f'Branch mismatch: {cb1}/{cb2}')
Expand Down Expand Up @@ -55,10 +55,10 @@ def _merge_cells(a, b, brancha, branchb, theirs):

# %% ../nbs/06_merge.ipynb 23
def _nbdev_fix(nbname:str, # Notebook filename to fix
outname:str=None, # Filename of output notebook (defaults to `nbname`)
nobackup:bool=True, # Do not backup `nbname` to `nbname`.bak if `outname` not provided
theirs:bool=False, # Use their outputs and metadata instead of ours
noprint:bool=False): # Do not print info about whether conflicts are found
outname:str=None, # Filename of output notebook (defaults to `nbname`)
nobackup:bool_arg=True, # Do not backup `nbname` to `nbname`.bak if `outname` not provided
theirs:bool=False, # Use their outputs and metadata instead of ours
noprint:bool=False): # Do not print info about whether conflicts are found
"Create working notebook from conflicted notebook `nbname`"
nbname = Path(nbname)
if not nobackup and not outname: shutil.copy(nbname, nbname.with_suffix('.ipynb.bak'))
Expand Down Expand Up @@ -91,11 +91,25 @@ def _only(o):
def _git_branch_merge(): return _only(v for k,v in os.environ.items() if k.startswith('GITHEAD'))

# %% ../nbs/06_merge.ipynb 31
def _git_rebase_head():
for d in ('apply','merge'):
d = Path(f'.git/rebase-{d}')
if d.is_dir():
cmt = (d/'orig-head').read_text()
msg = run(f'git show-branch --no-name {cmt}')
return f'{cmt[:7]} ({msg})'

# %% ../nbs/06_merge.ipynb 32
def _git_merge_file(base, ours, theirs):
"`git merge-file` with expected labels depending on if a `merge` or `rebase` is in-progress"
l_theirs = _git_rebase_head() or _git_branch_merge()
cmd = f"git merge-file -L HEAD -L BASE -L '{l_theirs}' {ours} {base} {theirs}"
return subprocess.run(cmd, shell=True, capture_output=True, text=True)

# %% ../nbs/06_merge.ipynb 33
@call_parse
def nbdev_merge(base:str, ours:str, theirs:str, path:str):
"Git merge driver for notebooks"
proc = subprocess.run(f'git merge-file -L HEAD -L BASE -L {_git_branch_merge()} {ours} {base} {theirs}',
shell=True, capture_output=True, text=True)
if proc.returncode == 0: return
if not _git_merge_file(base, ours, theirs).returncode: return
theirs = str2bool(os.environ.get('THEIRS', False))
return _nbdev_fix(ours, theirs=theirs)
112 changes: 60 additions & 52 deletions nbs/06_merge.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@
"source": [
"#|export\n",
"_BEG,_MID,_END = '<'*7,'='*7,'>'*7\n",
"conf_re = re.compile(rf'^{_BEG}\\s+(\\S+)\\n(.*?)\\n{_MID}\\n(.*?)^{_END}\\s+(\\S+)\\n', re.MULTILINE|re.DOTALL)\n",
"conf_re = re.compile(rf'^{_BEG}\\s+(\\S+)\\n(.*?)\\n{_MID}\\n(.*?)^{_END}\\s+([\\S ]+)\\n', re.MULTILINE|re.DOTALL)\n",
"\n",
"def _unpatch_f(before, cb1, cb2, c, r):\n",
" if cb1 is not None and cb1 != cb2: raise Exception(f'Branch mismatch: {cb1}/{cb2}')\n",
Expand Down Expand Up @@ -271,28 +271,18 @@
"outputs": [
{
"data": {
"text/markdown": [
"```json\n",
"{ 'cells': [{'cell_type': 'code', 'execution_count': 6, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['3']}, 'execution_count': 6, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'z=3\\nz', 'idx_': 0}, {'cell_type': 'code', 'execution_count': 5, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['6']}, 'execution_count': 7, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'x=3\\ny=3\\nx+y', 'idx_': 1}, {'cell_type': 'code', 'execution_count': None, 'metadata': {}, 'outputs': [], 'source': '', 'idx_': 2}],\n",
" 'metadata': { 'kernelspec': { 'display_name': 'Python 3',\n",
" 'language': 'python',\n",
" 'name': 'python3'}},\n",
" 'nbformat': 4,\n",
" 'nbformat_minor': 2}\n",
"```"
],
"text/plain": [
"{'cells': [{'cell_type': 'code',\n",
" 'execution_count': 6,\n",
" 'metadata': {},\n",
" 'outputs': [{'data': {'text/plain': ['3']},\n",
" 'execution_count': 6,\n",
" 'metadata': {},\n",
" 'output_type': 'execute_result'}],\n",
" 'source': ['z=3\\n', 'z']},\n",
" {'cell_type': 'code',\n",
" 'execution_count': 5,\n",
" 'metadata': {},\n",
" 'outputs': [{'data': {'text/plain': ['6']},\n",
" 'execution_count': 7,\n",
" 'metadata': {},\n",
" 'output_type': 'execute_result'}],\n",
" 'source': ['x=3\\n', 'y=3\\n', 'x+y']},\n",
" {'cell_type': 'code',\n",
" 'execution_count': None,\n",
" 'metadata': {},\n",
" 'outputs': [],\n",
" 'source': []}],\n",
"{'cells': (#3) [{'cell_type': 'code', 'execution_count': 6, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['3']}, 'execution_count': 6, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'z=3\\nz', 'idx_': 0},{'cell_type': 'code', 'execution_count': 5, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['6']}, 'execution_count': 7, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'x=3\\ny=3\\nx+y', 'idx_': 1},{'cell_type': 'code', 'execution_count': None, 'metadata': {}, 'outputs': [], 'source': '', 'idx_': 2}],\n",
" 'metadata': {'kernelspec': {'display_name': 'Python 3',\n",
" 'language': 'python',\n",
" 'name': 'python3'}},\n",
Expand All @@ -307,7 +297,7 @@
],
"source": [
"a,b,branch1,branch2 = unpatch(tst_nb)\n",
"loads(a)"
"dict2nb(loads(a))"
]
},
{
Expand All @@ -317,28 +307,18 @@
"outputs": [
{
"data": {
"text/markdown": [
"```json\n",
"{ 'cells': [{'cell_type': 'code', 'execution_count': 6, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['3']}, 'execution_count': 6, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'z=2\\nz', 'idx_': 0}, {'cell_type': 'code', 'execution_count': 5, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['6']}, 'execution_count': 5, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'x=3\\ny=3\\nx+y', 'idx_': 1}, {'cell_type': 'code', 'execution_count': None, 'metadata': {}, 'outputs': [], 'source': '', 'idx_': 2}],\n",
" 'metadata': { 'kernelspec': { 'display_name': 'Python 3',\n",
" 'language': 'python',\n",
" 'name': 'python3'}},\n",
" 'nbformat': 4,\n",
" 'nbformat_minor': 2}\n",
"```"
],
"text/plain": [
"{'cells': [{'cell_type': 'code',\n",
" 'execution_count': 6,\n",
" 'metadata': {},\n",
" 'outputs': [{'data': {'text/plain': ['3']},\n",
" 'execution_count': 6,\n",
" 'metadata': {},\n",
" 'output_type': 'execute_result'}],\n",
" 'source': ['z=2\\n', 'z']},\n",
" {'cell_type': 'code',\n",
" 'execution_count': 5,\n",
" 'metadata': {},\n",
" 'outputs': [{'data': {'text/plain': ['6']},\n",
" 'execution_count': 5,\n",
" 'metadata': {},\n",
" 'output_type': 'execute_result'}],\n",
" 'source': ['x=3\\n', 'y=3\\n', 'x+y']},\n",
" {'cell_type': 'code',\n",
" 'execution_count': None,\n",
" 'metadata': {},\n",
" 'outputs': [],\n",
" 'source': []}],\n",
"{'cells': (#3) [{'cell_type': 'code', 'execution_count': 6, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['3']}, 'execution_count': 6, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'z=2\\nz', 'idx_': 0},{'cell_type': 'code', 'execution_count': 5, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['6']}, 'execution_count': 5, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'x=3\\ny=3\\nx+y', 'idx_': 1},{'cell_type': 'code', 'execution_count': None, 'metadata': {}, 'outputs': [], 'source': '', 'idx_': 2}],\n",
" 'metadata': {'kernelspec': {'display_name': 'Python 3',\n",
" 'language': 'python',\n",
" 'name': 'python3'}},\n",
Expand All @@ -352,7 +332,7 @@
}
],
"source": [
"loads(b)"
"dict2nb(loads(b))"
]
},
{
Expand Down Expand Up @@ -407,10 +387,10 @@
"source": [
"#|export\n",
"def _nbdev_fix(nbname:str, # Notebook filename to fix\n",
" outname:str=None, # Filename of output notebook (defaults to `nbname`)\n",
" nobackup:bool=True, # Do not backup `nbname` to `nbname`.bak if `outname` not provided\n",
" theirs:bool=False, # Use their outputs and metadata instead of ours\n",
" noprint:bool=False): # Do not print info about whether conflicts are found\n",
" outname:str=None, # Filename of output notebook (defaults to `nbname`)\n",
" nobackup:bool_arg=True, # Do not backup `nbname` to `nbname`.bak if `outname` not provided\n",
" theirs:bool=False, # Use their outputs and metadata instead of ours\n",
" noprint:bool=False): # Do not print info about whether conflicts are found\n",
" \"Create working notebook from conflicted notebook `nbname`\"\n",
" nbname = Path(nbname)\n",
" if not nobackup and not outname: shutil.copy(nbname, nbname.with_suffix('.ipynb.bak'))\n",
Expand Down Expand Up @@ -512,6 +492,36 @@
"def _git_branch_merge(): return _only(v for k,v in os.environ.items() if k.startswith('GITHEAD'))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#|export\n",
"def _git_rebase_head():\n",
" for d in ('apply','merge'):\n",
" d = Path(f'.git/rebase-{d}')\n",
" if d.is_dir():\n",
" cmt = (d/'orig-head').read_text()\n",
" msg = run(f'git show-branch --no-name {cmt}')\n",
" return f'{cmt[:7]} ({msg})'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#|export\n",
"def _git_merge_file(base, ours, theirs):\n",
" \"`git merge-file` with expected labels depending on if a `merge` or `rebase` is in-progress\"\n",
" l_theirs = _git_rebase_head() or _git_branch_merge()\n",
" cmd = f\"git merge-file -L HEAD -L BASE -L '{l_theirs}' {ours} {base} {theirs}\"\n",
" return subprocess.run(cmd, shell=True, capture_output=True, text=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand All @@ -522,9 +532,7 @@
"@call_parse\n",
"def nbdev_merge(base:str, ours:str, theirs:str, path:str):\n",
" \"Git merge driver for notebooks\"\n",
" proc = subprocess.run(f'git merge-file -L HEAD -L BASE -L {_git_branch_merge()} {ours} {base} {theirs}',\n",
" shell=True, capture_output=True, text=True)\n",
" if proc.returncode == 0: return\n",
" if not _git_merge_file(base, ours, theirs).returncode: return\n",
" theirs = str2bool(os.environ.get('THEIRS', False))\n",
" return _nbdev_fix(ours, theirs=theirs)"
]
Expand Down
2 changes: 1 addition & 1 deletion nbs/11_clean.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@
" feature = 'add-heading'\n",
" _run(f'git checkout -b {feature}')\n",
" write_nb(thrs, p)\n",
" _run(\"git commit -am 'add {fn}'\")\n",
" _run(\"git commit -am 'heading'\")\n",
"\n",
" _run(f'git checkout {default}')\n",
" write_nb(ours, p)\n",
Expand Down

0 comments on commit 3c991e6

Please sign in to comment.