Skip to content

Commit

Permalink
Review feedback + testing
Browse files Browse the repository at this point in the history
  • Loading branch information
Marc Udoff committed Aug 3, 2020
1 parent 1fa946d commit a0f38bf
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 22 deletions.
6 changes: 3 additions & 3 deletions jupyterlab_git/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class JupyterLabGit(Configurable):
help='Actions to be taken after a git command. Each action takes a list of commands to execute (strings). Supported actions: post_init',
config=True,
trait=List(
trait=Unicode,
trait=Unicode(),
help='List of commands to run. E.g. ["touch baz.py"]'
)
# TODO Validate
Expand All @@ -35,7 +35,7 @@ def load_jupyter_server_extension(nbapp):
"""Load the Jupyter server extension.
"""

user_custom_actions = JupyterLabGit(config=nbapp.config).actions
git = Git(nbapp.web_app.settings['contents_manager'], user_custom_actions)
config = JupyterLabGit(config=nbapp.config)
git = Git(nbapp.web_app.settings['contents_manager'], config)
nbapp.web_app.settings["git"] = git
setup_handlers(nbapp.web_app)
56 changes: 37 additions & 19 deletions jupyterlab_git/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,10 @@ class Git:
A single parent class containing all of the individual git methods in it.
"""

def __init__(self, contents_manager, user_custom_actions):
def __init__(self, contents_manager, config=None):
self.contents_manager = contents_manager
self.root_dir = os.path.expanduser(contents_manager.root_dir)
self.user_custom_actions = user_custom_actions
self._config = config

async def config(self, top_repo_path, **kwargs):
"""Get or set Git options.
Expand Down Expand Up @@ -878,28 +878,46 @@ async def init(self, current_path):
code, _, error = await execute(
cmd, cwd=cwd
)

actions = None
if code == 0:
code, _, error = await self._maybe_run_actions('post_init', cwd)
code, actions = await self._maybe_run_actions('post_init', cwd)

if code != 0:
return {"code": code, "command": " ".join(cmd), "message": error}
return {"code": code}
return {"code": code, "command": " ".join(cmd), "message": error, "actions": actions}
return {"code": code, "actions": actions}

async def _maybe_run_actions(self, name, cwd):
code = 0
stdout = None
stderr = None
if name in self.user_custom_actions:
actions_list = self.user_custom_actions[name]
actions = None
if self._config and name in self._config.actions:
actions = []
actions_list = self._config.actions[name]
for action in actions_list:
# We trust the actions as they were passed via a config and not the UI
code, stdout, stderr = await execute(
shlex.split(action), cwd=cwd
)
# After any failure, stop
try:
# We trust the actions as they were passed via a config and not the UI
code, stdout, stderr = await execute(
shlex.split(action), cwd=cwd
)
actions.append({
'cmd': action,
'code': code,
'stdout': stdout,
'stderr': stderr
})
# After any failure, stop
except Exception as e:
code = 1
action.append({
'cmd': action,
'code': 1,
'stdout': None,
'stderr': 'Exception: {}'.format(e)
})
if code != 0:
break
return code, stdout, stderr

return code, actions

def _is_remote_branch(self, branch_reference):
"""Check if given branch is remote branch by comparing with 'remotes/',
Expand Down Expand Up @@ -1133,7 +1151,7 @@ def remote_add(self, top_repo_path, url, name=DEFAULT_REMOTE_NAME):

async def version(self):
"""Return the Git command version.
If an error occurs, return None.
"""
command = ["git", "--version"]
Expand All @@ -1142,12 +1160,12 @@ async def version(self):
version = GIT_VERSION_REGEX.match(output)
if version is not None:
return version.group('version')

return None

async def tags(self, current_path):
"""List all tags of the git repository.
current_path: str
Git path repository
"""
Expand All @@ -1160,7 +1178,7 @@ async def tags(self, current_path):

async def tag_checkout(self, current_path, tag):
"""Checkout the git repository at a given tag.
current_path: str
Git path repository
tag : str
Expand Down
88 changes: 88 additions & 0 deletions jupyterlab_git/tests/test_init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import os
from subprocess import CalledProcessError
from unittest.mock import Mock, call, patch

import pytest
import tornado

from jupyterlab_git import JupyterLabGit
from jupyterlab_git.git import Git

from .testutils import FakeContentManager, maybe_future


@pytest.mark.asyncio
async def test_init():
with patch("jupyterlab_git.git.execute") as mock_execute:
# Given
mock_execute.return_value = maybe_future((0, "", ""))

# When
actual_response = await Git(FakeContentManager("/bin")).init("test_curr_path")

mock_execute.assert_called_once_with(
["git", "init"], cwd=os.path.join("/bin", "test_curr_path")
)

assert {"code": 0, "actions": None} == actual_response


@pytest.mark.asyncio
async def test_init_and_post_init():
with patch("jupyterlab_git.git.execute") as mock_execute:
# Given
mock_execute.side_effect = [
maybe_future((0, "", "")),
maybe_future((0, "hello", "")),
]

# When
actual_response = await Git(
FakeContentManager("/bin"),
JupyterLabGit(actions={"post_init": ['echo "hello"']}),
).init("test_curr_path")

mock_execute.assert_called_with(
["echo", "hello"], cwd=os.path.join("/bin", "test_curr_path")
)

assert {
"code": 0,
"actions": [
{"cmd": 'echo "hello"', "code": 0, "stderr": "", "stdout": "hello"}
],
} == actual_response


@pytest.mark.asyncio
async def test_init_and_post_init_fail():
with patch("jupyterlab_git.git.execute") as mock_execute:
# Given
mock_execute.side_effect = [
maybe_future((0, "", "")),
maybe_future((1, "", "not_there: command not found")),
]

# When
actual_response = await Git(
FakeContentManager("/bin"),
JupyterLabGit(actions={"post_init": ["not_there arg"]}),
).init("test_curr_path")

mock_execute.assert_called_with(
["not_there", "arg"], cwd=os.path.join("/bin", "test_curr_path")
)

assert {
"code": 1,
"message": "",
"command": "git init",
"actions": [
{
"stderr": "not_there: command not found",
"stdout": "",
"code": 1,
"cmd": "not_there arg",
}
],
} == actual_response

0 comments on commit a0f38bf

Please sign in to comment.